#!/usr/bin/env dart
// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// Command line tool to merge the SDK libraries and our patch files.
/// This is currently designed as an offline tool, but we could automate it.

import 'dart:io';

import 'package:_fe_analyzer_shared/src/util/relativize.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:args/args.dart';
import 'package:front_end/src/base/libraries_specification.dart';
import 'package:front_end/src/fasta/resolve_input_uri.dart';

void main(List<String> argv) {
  var args = _parser.parse(argv);
  if (args['libraries'] == null || args['out'] == null) {
    var self = relativizeUri(Uri.base, Platform.script, isWindows);
    var librariesJson = relativizeUri(Uri.base,
        Platform.script.resolve('../../../sdk/lib/libraries.json'), isWindows);
    print('Usage: $self [other options]'
        ' --libraries <libraries.json> --out <output-dir>');
    print('For example:');
    print('\$ $self --nnbd --libraries $librariesJson --out patched-sdk-dir');
    exit(1);
  }

  var useNnbd = args['nnbd'] as bool;
  var target = args['target'] as String;
  var jsonUri = resolveInputUri(args['libraries'] as String);
  var libRoot = jsonUri.resolve('./');
  var outPath = args['out'] as String;
  var outDir = resolveInputUri(outPath.endsWith('/') ? outPath : '$outPath/');
  var outLibRoot = outDir.resolve('lib/');

  var inputVersion = Platform.script.resolve('../../../tools/VERSION');
  var outVersion = outDir.resolve('version');

  var specification = LibrariesSpecification.parse(
          jsonUri, File.fromUri(jsonUri).readAsStringSync())
      .specificationFor(target);

  // Copy libraries.dart and version
  _writeSync(outVersion, File.fromUri(inputVersion).readAsStringSync());

  // Enumerate sdk libraries and apply patches
  for (var library in specification.allLibraries) {
    var libraryFile = File.fromUri(library.uri);
    var libraryOut =
        outLibRoot.resolve(relativizeLibraryUri(libRoot, library.uri, useNnbd));
    if (libraryFile.existsSync()) {
      var outUris = <Uri>[libraryOut];
      var libraryContents = libraryFile.readAsStringSync();
      var contents = <String>[libraryContents];

      for (var part
          in _parseString(libraryContents, useNnbd: useNnbd).unit.directives) {
        if (part is PartDirective) {
          var partPath = part.uri.stringValue;
          outUris.add(libraryOut.resolve(partPath));
          contents.add(
              File.fromUri(library.uri.resolve(partPath)).readAsStringSync());
        }
      }

      if (args['merge-parts'] as bool && outUris.length > 1) {
        outUris.length = 1;
        contents = [
          contents
              .join('\n')
              .replaceAll(RegExp('^part [^\n]*\$', multiLine: true), '')
        ];
      }

      var buffer = StringBuffer();
      for (var patchUri in library.patches) {
        // Note: VM targets enumerate more than one patch file, they are
        // currently written so that the first file is a valid patch file and
        // all other files can be appended at the end.
        buffer.write(File.fromUri(patchUri).readAsStringSync());
      }
      var patchContents = '$buffer';

      if (patchContents.isNotEmpty) {
        contents = _patchLibrary(contents, patchContents, useNnbd: useNnbd);
      }

      if (contents != null) {
        for (var i = 0; i < outUris.length; i++) {
          _writeSync(outUris[i], contents[i]);
        }
      } else {
        exitCode = 2;
      }
    }
  }

  var outLibrariesDart =
      outLibRoot.resolve('_internal/sdk_library_metadata/lib/libraries.dart');
  _writeSync(outLibrariesDart,
      _generateLibrariesDart(libRoot, specification, useNnbd));
}

/// Writes a file, creating the directory if needed.
void _writeSync(Uri fileUri, String contents) {
  var outDir = Directory.fromUri(fileUri.resolve('.'));
  if (!outDir.existsSync()) outDir.createSync(recursive: true);

  File.fromUri(fileUri).writeAsStringSync(contents);
}

final _parser = ArgParser()
  ..addFlag('nnbd',
      help: 'Whether to enable the nnbd feature.', defaultsTo: false)
  ..addFlag('merge-parts',
      help: 'Whether to merge part files. '
          'Technically this is not necessary, but dartanalyzer '
          'produces less warnings when enabling this flag.',
      defaultsTo: false)
  ..addOption('libraries',
      help: 'Path to a libraries.json specification file (required). '
          'All libary URIs within libraries.json are expected to be somewhere '
          'under the directory containing the libraries.json file. Reaching '
          'out above such directory is generally not supported. Today it is '
          'only allowed for the nnbd sdk to reuse libraries of the non-nnbd '
          'sdk, in which case the path starts with "../../sdk/lib/".')
  ..addOption('out', help: 'Path to an output folder (required).')
  ..addOption('target',
      help: 'The target tool. '
          'This name matches one of the possible targets in libraries.json '
          'and it is used to pick which patch files will be applied.',
      allowed: ['dartdevc', 'dart2js', 'dart2js_server', 'vm', 'flutter']);

/// Merges dart:* library code with code from *_patch.dart file.
///
/// Takes a list of the library's parts contents, with the main library contents
/// first in the list, and the contents of the patch file.
///
/// The result will have `@patch` implementations merged into the correct place
/// (e.g. the class or top-level function declaration) and all other
/// declarations introduced by the patch will be placed into the main library
/// file.
///
/// This is purely a syntactic transformation. Unlike dart2js patch files, there
/// is no semantic meaning given to the *_patch files, and they do not magically
/// get their own library scope, etc.
///
/// Editorializing: the dart2js approach requires a Dart front end such as
/// package:analyzer to semantically model a feature beyond what is specified
/// in the Dart language. Since this feature is only for the convenience of
/// writing the dart:* libraries, and not a tool given to Dart developers, it
/// seems like a non-ideal situation. Instead we keep the preprocessing simple.
List<String> _patchLibrary(List<String> partsContents, String patchContents,
    {bool useNnbd = false}) {
  var results = <StringEditBuffer>[];

  // Parse the patch first. We'll need to extract bits of this as we go through
  // the other files.
  var patchFinder = PatchFinder.parseAndVisit(patchContents, useNnbd: useNnbd);

  // Merge `external` declarations with the corresponding `@patch` code.
  var failed = false;
  for (var partContent in partsContents) {
    var partEdits = StringEditBuffer(partContent);
    var partUnit = _parseString(partContent, useNnbd: useNnbd).unit;
    var patcher = PatchApplier(partEdits, patchFinder);
    partUnit.accept(patcher);
    if (!failed) failed = patcher.patchWasMissing;
    results.add(partEdits);
  }
  if (failed) return null;
  return List<String>.from(results.map((e) => e.toString()));
}

/// Merge `@patch` declarations into `external` declarations.
class PatchApplier extends GeneralizingAstVisitor<void> {
  final StringEditBuffer edits;
  final PatchFinder patch;

  bool _isLibrary = true; // until proven otherwise.
  bool patchWasMissing = false;

  PatchApplier(this.edits, this.patch);

  @override
  void visitCompilationUnit(CompilationUnit node) {
    super.visitCompilationUnit(node);
    if (_isLibrary) _mergeUnpatched(node);
  }

  void _merge(AstNode node, int pos) {
    var code = patch.contents.substring(node.offset, node.end);
    edits.insert(pos, '\n' + code);
  }

  /// Merges directives and declarations that are not `@patch` into the library.
  void _mergeUnpatched(CompilationUnit unit) {
    // Merge imports from the patch
    // TODO(jmesserly): remove duplicate imports

    // To patch a library, we must have a library directive
    var libDir = unit.directives.first as LibraryDirective;
    var importPos = unit.directives
        .lastWhere((d) => d is ImportDirective, orElse: () => libDir)
        .end;
    for (var d in patch.unit.directives.whereType<ImportDirective>()) {
      _merge(d, importPos);
    }

    var partPos = unit.directives.last.end;
    for (var d in patch.unit.directives.whereType<PartDirective>()) {
      _merge(d, partPos);
    }

    // Merge declarations from the patch
    var declPos = edits.original.length;
    for (var d in patch.mergeDeclarations) {
      _merge(d, declPos);
    }
  }

  @override
  void visitPartOfDirective(PartOfDirective node) {
    _isLibrary = false;
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    _maybePatch(node);
  }

  /// Merge patches and extensions into the class
  @override
  void visitClassDeclaration(ClassDeclaration node) {
    node.members.forEach(_maybePatch);

    var mergeMembers = patch.mergeMembers[_qualifiedName(node)];
    if (mergeMembers == null) return;

    // Merge members from the patch
    var pos = node.members.last.end;
    for (var member in mergeMembers) {
      var code = patch.contents.substring(member.offset, member.end);
      edits.insert(pos, '\n\n  ' + code);
    }
  }

  void _maybePatch(Declaration node) {
    if (node is FieldDeclaration) return;

    var externalKeyword = (node as dynamic).externalKeyword as Token;
    if (externalKeyword == null) return;

    var name = _qualifiedName(node);
    var patchNode = patch.patches[name];
    if (patchNode == null) {
      // *.fromEnvironment are left unpatched by dart2js and are handled via
      // codegen.
      if (name != 'bool.fromEnvironment' &&
          name != 'int.fromEnvironment' &&
          name != 'String.fromEnvironment') {
        print('warning: patch not found for $name: $node');
        // TODO(sigmund): delete this fail logic? Rather than emit an empty
        // file, it's more useful to emit a file with missing patches.
        // patchWasMissing = true;
      }
      return;
    }

    var patchMeta = patchNode.metadata.lastWhere(_isPatchAnnotation);
    var start = patchMeta.endToken.next.offset;
    var code = patch.contents.substring(start, patchNode.end);

    // Const factory constructors can't be legally parsed from the patch file,
    // so we need to omit the "const" there, but still preserve it.
    if (node is ConstructorDeclaration &&
        node.constKeyword != null &&
        patchNode is ConstructorDeclaration &&
        patchNode.constKeyword == null) {
      code = 'const $code';
    }

    // For some node like static fields, the node's offset doesn't include
    // the external keyword. Also starting from the keyword lets us preserve
    // documentation comments.
    edits.replace(externalKeyword.offset, node.end, code);
  }
}

class PatchFinder extends GeneralizingAstVisitor<void> {
  final String contents;
  final CompilationUnit unit;

  final patches = <String, Declaration>{};
  final mergeMembers = <String, List<ClassMember>>{};
  final mergeDeclarations = <CompilationUnitMember>[];

  PatchFinder.parseAndVisit(String contents, {bool useNnbd})
      : contents = contents,
        unit = _parseString(contents, useNnbd: useNnbd).unit {
    visitCompilationUnit(unit);
  }

  @override
  void visitCompilationUnitMember(CompilationUnitMember node) {
    mergeDeclarations.add(node);
  }

  @override
  void visitClassDeclaration(ClassDeclaration node) {
    if (_isPatch(node)) {
      var members = <ClassMember>[];
      for (var member in node.members) {
        if (_isPatch(member)) {
          patches[_qualifiedName(member)] = member;
        } else {
          members.add(member);
        }
      }
      if (members.isNotEmpty) {
        mergeMembers[_qualifiedName(node)] = members;
      }
    } else {
      mergeDeclarations.add(node);
    }
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    if (_isPatch(node)) {
      patches[_qualifiedName(node)] = node;
    } else {
      mergeDeclarations.add(node);
    }
  }

  @override
  void visitFunctionBody(node) {} // skip method bodies
}

String _qualifiedName(Declaration node) {
  var result = '';

  var parent = node.parent;
  if (parent is ClassDeclaration) {
    result = '${parent.name.name}.';
  }

  var name = (node as dynamic).name as SimpleIdentifier;
  if (name != null) result += name.name;

  // Make sure setters and getters don't collide.
  if (node is FunctionDeclaration && node.isSetter ||
      node is MethodDeclaration && node.isSetter) {
    result += '=';
  }

  return result;
}

bool _isPatch(AnnotatedNode node) => node.metadata.any(_isPatchAnnotation);

bool _isPatchAnnotation(Annotation m) =>
    m.name.name == 'patch' && m.constructorName == null && m.arguments == null;

/// Editable string buffer.
///
/// Applies a series of edits (insertions, removals, replacements) using
/// original location information, and composes them into the edited string.
///
/// For example, starting with a parsed AST with original source locations,
/// this type allows edits to be made without regards to other edits.
class StringEditBuffer {
  final String original;
  final _edits = <_StringEdit>[];

  /// Creates a new transaction.
  StringEditBuffer(this.original);

  bool get hasEdits => _edits.isNotEmpty;

  /// Edit the original text, replacing text on the range [begin] and
  /// exclusive [end] with the [replacement] string.
  void replace(int begin, int end, String replacement) {
    _edits.add(_StringEdit(begin, end, replacement));
  }

  /// Insert [string] at [offset].
  /// Equivalent to `replace(offset, offset, string)`.
  void insert(int offset, String string) => replace(offset, offset, string);

  /// Remove text from the range [begin] to exclusive [end].
  /// Equivalent to `replace(begin, end, '')`.
  void remove(int begin, int end) => replace(begin, end, '');

  /// Applies all pending [edit]s and returns a new string.
  ///
  /// This method is non-destructive: it does not discard existing edits or
  /// change the [original] string. Further edits can be added and this method
  /// can be called again.
  ///
  /// Throws [UnsupportedError] if the edits were overlapping. If no edits were
  /// made, the original string will be returned.
  @override
  String toString() {
    var sb = StringBuffer();
    if (_edits.isEmpty) return original;

    // Sort edits by start location.
    _edits.sort();

    var consumed = 0;
    for (var edit in _edits) {
      if (consumed > edit.begin) {
        sb = StringBuffer();
        sb.write('overlapping edits. Insert at offset ');
        sb.write(edit.begin);
        sb.write(' but have consumed ');
        sb.write(consumed);
        sb.write(' input characters. List of edits:');
        for (var e in _edits) {
          sb.write('\n    ');
          sb.write(e);
        }
        throw UnsupportedError(sb.toString());
      }

      // Add characters from the original string between this edit and the last
      // one, if any.
      var betweenEdits = original.substring(consumed, edit.begin);
      sb.write(betweenEdits);
      sb.write(edit.replace);
      consumed = edit.end;
    }

    // Add any text from the end of the original string that was not replaced.
    sb.write(original.substring(consumed));
    return sb.toString();
  }
}

class _StringEdit implements Comparable<_StringEdit> {
  final int begin;
  final int end;
  final String replace;

  _StringEdit(this.begin, this.end, this.replace);

  int get length => end - begin;

  @override
  String toString() => '(Edit @ $begin,$end: "$replace")';

  @override
  int compareTo(_StringEdit other) {
    var diff = begin - other.begin;
    if (diff != 0) return diff;
    return end - other.end;
  }
}

ParseStringResult _parseString(String source, {bool useNnbd}) {
  var features = FeatureSet.fromEnableFlags([if (useNnbd) 'non-nullable']);
  return parseString(content: source, featureSet: features);
}

/// Use the data from a libraries.json specification to generate the contents
/// of `sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart`, which is
/// needed by dartdevc-legacy and dartanalyzer.
String _generateLibrariesDart(
    Uri libBaseUri, TargetLibrariesSpecification specification, bool usdNnbd) {
  var contents = StringBuffer();
  contents.write(_LIBRARIES_DART_PREFIX);
  for (var library in specification.allLibraries) {
    var path = relativizeLibraryUri(libBaseUri, library.uri, usdNnbd);
    contents.write('  "${library.name}": \n'
        '      const LibraryInfo("$path",\n'
        '          categories: "Client,Server"),\n');
  }
  contents.write(_LIBRARIES_DART_SUFFIX);
  return '$contents';
}

String relativizeLibraryUri(Uri libRoot, Uri uri, bool useNnbd) {
  var relativePath = relativizeUri(libRoot, uri, isWindows);
  // During the nnbd-migration we may have paths that reach out into the
  // non-nnbd directory.
  if (relativePath.startsWith('..')) {
    if (!useNnbd || !relativePath.startsWith('../../sdk/lib/')) {
      print("error: can't handle libraries that live out of the sdk folder"
          ': $relativePath');
      exit(1);
    }
    relativePath = relativePath.replaceFirst('../../sdk/lib/', '');
  }
  return relativePath;
}

final _LIBRARIES_DART_PREFIX = r'''
library libraries;

const int DART2JS_PLATFORM = 1;
const int VM_PLATFORM = 2;

enum Category { client, server, embedded }

Category parseCategory(String name) {
  switch (name) {
    case "Client":
      return Category.client;
    case "Server":
      return Category.server;
    case "Embedded":
      return Category.embedded;
  }
  return null;
}

const Map<String, LibraryInfo> libraries = const {
''';

final _LIBRARIES_DART_SUFFIX = r'''
};

class LibraryInfo {
  final String path;
  final String _categories;
  final String dart2jsPath;
  final String dart2jsPatchPath;
  final bool documented;
  final int platforms;
  final bool implementation;
  final Maturity maturity;

  const LibraryInfo(this.path,
      {String categories: "",
      this.dart2jsPath,
      this.dart2jsPatchPath,
      this.implementation: false,
      this.documented: true,
      this.maturity: Maturity.UNSPECIFIED,
      this.platforms: DART2JS_PLATFORM | VM_PLATFORM})
      : _categories = categories;

  bool get isDart2jsLibrary => (platforms & DART2JS_PLATFORM) != 0;
  bool get isVmLibrary => (platforms & VM_PLATFORM) != 0;
  List<Category> get categories {
    // `"".split(,)` returns [""] not [], so we handle that case separately.
    if (_categories == "") return const <Category>[];
    return _categories.split(",").map(parseCategory).toList();
  }

  bool get isInternal => categories.isEmpty;
  String get categoriesString => _categories;
}

class Maturity {
  final int level;
  final String name;
  final String description;

  const Maturity(this.level, this.name, this.description);

  String toString() => "$name: $level\n$description\n";

  static const Maturity DEPRECATED = const Maturity(0, "Deprecated",
      "This library will be remove before next major release.");

  static const Maturity EXPERIMENTAL = const Maturity(
      1,
      "Experimental",
      "This library is experimental and will likely change or be removed\n"
          "in future versions.");

  static const Maturity UNSTABLE = const Maturity(
      2,
      "Unstable",
      "This library is in still changing and have not yet endured\n"
          "sufficient real-world testing.\n"
          "Backwards-compatibility is NOT guaranteed.");

  static const Maturity WEB_STABLE = const Maturity(
      3,
      "Web Stable",
      "This library is tracking the DOM evolution as defined by WC3.\n"
          "Backwards-compatibility is NOT guaranteed.");

  static const Maturity STABLE = const Maturity(
      4,
      "Stable",
      "The library is stable. API backwards-compatibility is guaranteed.\n"
          "However implementation details might change.");

  static const Maturity LOCKED = const Maturity(5, "Locked",
      "This library will not change except when serious bugs are encountered.");

  static const Maturity UNSPECIFIED = const Maturity(-1, "Unspecified",
      "The maturity for this library has not been specified.");
}
''';
