// Copyright (c) 2018, 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.

import 'dart:collection';
import 'dart:typed_data';

import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart' show ResourceProvider;
import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver.dart' show AnalysisDriver;
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/library_analyzer.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/link.dart' as summary_link;
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/summary/resynthesize.dart';
import 'package:analyzer/src/summary/summarize_ast.dart';
import 'package:analyzer/src/summary/summarize_elements.dart';
import 'package:meta/meta.dart';

import '../compiler/shared_command.dart' show sdkLibraryVariables;
import 'context.dart' show AnalyzerOptions, createSourceFactory;
import 'extension_types.dart' show ExtensionTypeSet;

/// The analysis driver for `dartdevc`.
///
/// [linkLibraries] can be used to link input sources and input summaries,
/// producing a [LinkedAnalysisDriver] that can analyze those sources.
///
/// This class can be reused to link different input files if they share the
/// same [analysisOptions] and [summaryData].
class CompilerAnalysisDriver {
  /// The Analyzer options used for analyzing the input sources.
  final AnalysisOptionsImpl analysisOptions;

  /// The input summaries used for analyzing/compiling the input sources.
  ///
  /// This should contain the summary of all imported/exported libraries and
  /// transitive dependencies, including the Dart SDK.
  final SummaryDataStore summaryData;

  final ResourceProvider _resourceProvider;

  final List<String> _summaryPaths;

  @visibleForTesting
  final DartSdk dartSdk;

  /// SDK summary path, used by [isCompatibleWith] for batch/worker mode.
  final String _dartSdkSummaryPath;

  ExtensionTypeSet _extensionTypes;

  CompilerAnalysisDriver._(this.dartSdk, this._summaryPaths, this.summaryData,
      this.analysisOptions, this._resourceProvider, this._dartSdkSummaryPath) {
    var bundle = dartSdk.getLinkedBundle();
    if (bundle != null) summaryData.addBundle(null, bundle);
  }

  /// Information about native extension types.
  ///
  /// This will be `null` until [linkLibraries] has been called (because we
  /// could be compiling the Dart SDK, so it would not be available yet).
  ExtensionTypeSet get extensionTypes => _extensionTypes;

  factory CompilerAnalysisDriver(AnalyzerOptions options,
      {SummaryDataStore summaryData, List<String> summaryPaths = const []}) {
    AnalysisEngine.instance.processRequiredPlugins();

    var resourceProvider = options.resourceProvider;
    var contextBuilder = options.createContextBuilder();

    var analysisOptions =
        contextBuilder.getAnalysisOptions(options.analysisRoot);
    var dartSdk = contextBuilder.findSdk(null, analysisOptions);

    // Read the summaries.
    summaryData ??= SummaryDataStore(summaryPaths,
        resourceProvider: resourceProvider,
        // TODO(vsm): Reset this to true once we cleanup internal build rules.
        disallowOverlappingSummaries: false);

    return CompilerAnalysisDriver._(dartSdk, summaryPaths, summaryData,
        analysisOptions, resourceProvider, options.dartSdkSummaryPath);
  }

  /// Whether this driver can be reused for the given [dartSdkSummaryPath] and
  /// [summaryPaths].
  bool isCompatibleWith(AnalyzerOptions options, List<String> summaryPaths) {
    return _dartSdkSummaryPath == options.dartSdkSummaryPath &&
        _summaryPaths.toSet().containsAll(summaryPaths);
  }

  /// Parses [explicitSources] and any imports/exports/parts (that are not
  /// included in [summaryData]), and links the results so
  /// [LinkedAnalysisDriver.analyzeLibrary] can be called.
  ///
  /// The analyzer [options] are used to configure URI resolution (Analyzer's
  /// [SourceFactory]) and declared variables, if any (`-Dfoo=bar`).
  LinkedAnalysisDriver linkLibraries(
      List<Uri> explicitSources, AnalyzerOptions options) {
    /// This code was ported from analyzer_cli (with a few changes/improvements).
    ///
    /// Here's a summary of the process:
    ///
    /// 1. starting with [explicitSources], visit all transitive
    ///    imports/exports/parts, and create an unlinked unit for each
    ///    (unless it's provided by an input summary). Add these to [assembler].
    ///
    /// 2. call [summary_link.link] to create the linked libraries, and add the
    ///    results to the assembler.
    ///
    /// 3. serialize the data into [summaryBytes], then deserialize it back into
    ///    the [bundle] that contains the summary for all [explicitSources] and
    ///    their transitive dependencies.
    ///
    /// 4. create the analysis [context] and element [resynthesizer], and use
    ///    them to return a new [LinkedAnalysisDriver] that can analyze all of
    ///    the compilation units (and provide the resolved AST/errors for each).
    var assembler = PackageBundleAssembler();

    /// The URI resolution logic for this build unit.
    var sourceFactory = createSourceFactory(options,
        sdkResolver: DartUriResolver(dartSdk), summaryData: summaryData);

    /// A fresh file system state for this list of [explicitSources].
    var fsState = _createFileSystemState(sourceFactory);

    var uriToUnit = <String, UnlinkedUnit>{};

    /// The sources that have been added to [sourcesToProcess], used to ensure
    /// we only visit a given source once.
    var knownSources = HashSet<Uri>.from(explicitSources);

    /// The pending list of sources to visit.
    var sourcesToProcess = Queue<Uri>.from(explicitSources);

    /// Prepare URIs of unlinked units (for libraries) that should be linked.
    var libraryUris = <String>[];

    /// Ensure that the [UnlinkedUnit] for [absoluteUri] is available.
    ///
    /// If the unit is in the input [summaryData], do nothing.
    /// Otherwise compute it and store into the [uriToUnit] and [assembler].
    void prepareUnlinkedUnit(Uri uri) {
      var absoluteUri = uri.toString();
      // Maybe an input package contains the source.
      if (summaryData.unlinkedMap[absoluteUri] != null) {
        return;
      }
      // Parse the source and serialize its AST.
      var source = sourceFactory.forUri2(uri);
      if (source == null || !source.exists()) {
        // Skip this source. We don't need to report an error here because it
        // will be reported later during analysis.
        return;
      }
      var file = fsState.getFileForPath(source.fullName);
      var unit = file.parse();
      var unlinkedUnit = serializeAstUnlinked(unit);
      uriToUnit[absoluteUri] = unlinkedUnit;
      assembler.addUnlinkedUnit(source, unlinkedUnit);

      /// The URI to resolve imports/exports/parts against.
      var baseUri = uri;
      if (baseUri.scheme == 'dart' && baseUri.pathSegments.length == 1) {
        // Add a trailing slash so relative URIs will resolve correctly, e.g.
        // "map.dart" from "dart:core/" yields "dart:core/map.dart".
        baseUri = Uri(scheme: 'dart', path: baseUri.path + '/');
      }

      void enqueueSource(String relativeUri) {
        var sourceUri = baseUri.resolve(relativeUri);
        if (knownSources.add(sourceUri)) {
          sourcesToProcess.add(sourceUri);
        }
      }

      // Add reachable imports/exports/parts, if any.
      var isPart = false;
      for (var directive in unit.directives) {
        if (directive is UriBasedDirective) {
          enqueueSource(directive.uri.stringValue);
          // Handle conditional imports.
          if (directive is NamespaceDirective) {
            for (var config in directive.configurations) {
              enqueueSource(config.uri.stringValue);
            }
          }
        } else if (directive is PartOfDirective) {
          isPart = true;
        }
      }

      // Remember library URIs, so we can use it for linking libraries and
      // compiling them.
      if (!isPart) libraryUris.add(absoluteUri);
    }

    // Collect the unlinked units for all transitive sources.
    //
    // TODO(jmesserly): consider using parallelism via asynchronous IO here,
    // once we fix debugger extension (web/web_command.dart) to allow async.
    //
    // It would let computation tasks (parsing/serializing unlinked units)
    // proceed in parallel with reading the sources from disk.
    while (sourcesToProcess.isNotEmpty) {
      prepareUnlinkedUnit(sourcesToProcess.removeFirst());
    }

    /// Gets the URIs to link.
    ///
    /// Unlike analyzer_cli, this only includes library URIs, not all
    /// compilation units. This appears to be what [summary_link.link] wants as
    /// input. If all units are passed in, the resulting summary has extra data
    /// in the linkedLibraries list, which appears to be unnecessary.
    var unlinkedUris = Set<String>.from(summaryData.uriToSummaryPath.keys)
      ..addAll(libraryUris);
    var declaredVariables = DeclaredVariables.fromMap(
        Map.of(options.declaredVariables)..addAll(sdkLibraryVariables));

    /// Perform the linking step and store the result.
    ///
    /// TODO(jmesserly): can we pass in `getAst` to reuse existing ASTs we
    /// created when we did `file.parse()` in [prepareUnlinkedUnit]?
    var linkResult = summary_link.link(
        unlinkedUris,
        (uri) => summaryData.linkedMap[uri],
        (uri) => summaryData.unlinkedMap[uri] ?? uriToUnit[uri],
        declaredVariables.get);
    linkResult.forEach(assembler.addLinkedLibrary);

    var summaryBytes = assembler.assemble().toBuffer();
    var bundle = PackageBundle.fromBuffer(summaryBytes);

    /// Create an analysis context to contain the state for this build unit.
    var context =
        AnalysisEngine.instance.createAnalysisContext() as AnalysisContextImpl;
    context.sourceFactory = sourceFactory;
    var resultProvider = InputPackagesResultProvider(
        context,
        SummaryDataStore([])
          ..addStore(summaryData)
          ..addBundle(null, bundle));
    context.resultProvider = resultProvider;
    context.contentCache = _ContentCacheWrapper(fsState);

    var resynthesizer = resultProvider.resynthesizer;
    _extensionTypes ??= ExtensionTypeSet(context.typeProvider, resynthesizer);

    return LinkedAnalysisDriver(analysisOptions, resynthesizer, sourceFactory,
        libraryUris, declaredVariables, summaryBytes, fsState);
  }

  FileSystemState _createFileSystemState(SourceFactory sourceFactory) {
    var unlinkedSalt =
        Uint32List(1 + AnalysisOptionsImpl.unlinkedSignatureLength);
    unlinkedSalt[0] = AnalysisDriver.DATA_VERSION;
    unlinkedSalt.setAll(1, analysisOptions.unlinkedSignature);

    var linkedSalt = Uint32List(1 + AnalysisOptions.signatureLength);
    linkedSalt[0] = AnalysisDriver.DATA_VERSION;
    linkedSalt.setAll(1, analysisOptions.signature);

    return FileSystemState(
        PerformanceLog(StringBuffer()),
        MemoryByteStore(),
        FileContentOverlay(),
        _resourceProvider,
        sourceFactory,
        analysisOptions,
        unlinkedSalt,
        linkedSalt,
        externalSummaries: summaryData);
  }
}

/// The analysis driver used after linking all input summaries and explicit
/// sources, produced by [CompilerAnalysisDriver.linkLibraries].
class LinkedAnalysisDriver {
  final AnalysisOptions analysisOptions;
  final SummaryResynthesizer resynthesizer;
  final SourceFactory sourceFactory;
  final List<String> libraryUris;
  final DeclaredVariables declaredVariables;

  /// The summary bytes for this linked build unit.
  final List<int> summaryBytes;

  final FileSystemState _fsState;

  LinkedAnalysisDriver(
      this.analysisOptions,
      this.resynthesizer,
      this.sourceFactory,
      this.libraryUris,
      this.declaredVariables,
      this.summaryBytes,
      this._fsState);

  AnalysisContextImpl get context => resynthesizer.context;

  /// Clean up any state used by this driver.
  void dispose() => context.dispose();

  /// True if [uri] refers to a Dart library (i.e. a Dart source file exists
  /// with this uri, and it is not a part file).
  bool _isLibraryUri(String uri) {
    return resynthesizer.hasLibrarySummary(uri);
  }

  /// Analyzes the library at [uri] and returns the results of analysis for all
  /// file(s) in that library.
  Map<FileState, UnitAnalysisResult> analyzeLibrary(String libraryUri) {
    if (!_isLibraryUri(libraryUri)) {
      throw ArgumentError('"$libraryUri" is not a library');
    }

    var libraryFile = _fsState.getFileForUri(Uri.parse(libraryUri));
    var analyzer = LibraryAnalyzer(
        analysisOptions,
        declaredVariables,
        resynthesizer.sourceFactory,
        (uri) => _isLibraryUri('$uri'),
        context,
        resynthesizer,
        libraryFile);
    // TODO(jmesserly): ideally we'd use the existing public `analyze()` method,
    // but it's async. We can't use `async` here because it would break our
    // developer tools extension (see web/web_command.dart). We should be able
    // to fix it, but it requires significant changes to code outside of this
    // repository.
    return analyzer.analyzeSync();
  }

  ClassElement getClass(String uri, String name) {
    return getLibrary(uri).getType(name);
  }

  LibraryElement getLibrary(String uri) {
    return resynthesizer.getLibraryElement(uri);
  }
}

/// [ContentCache] wrapper around [FileSystemState].
class _ContentCacheWrapper implements ContentCache {
  final FileSystemState fsState;

  _ContentCacheWrapper(this.fsState);

  @override
  void accept(ContentCacheVisitor visitor) {
    throw new UnimplementedError();
  }

  @override
  String getContents(Source source) {
    return _getFileForSource(source).content;
  }

  @override
  bool getExists(Source source) {
    if (source.isInSystemLibrary) {
      return true;
    }
    String uriStr = source.uri.toString();
    if (fsState.externalSummaries != null &&
        fsState.externalSummaries.hasUnlinkedUnit(uriStr)) {
      return true;
    }
    return _getFileForSource(source).exists;
  }

  @override
  int getModificationStamp(Source source) {
    if (source.isInSystemLibrary) {
      return 0;
    }
    return _getFileForSource(source).exists ? 0 : -1;
  }

  @override
  String setContents(Source source, String contents) {
    throw new UnimplementedError();
  }

  FileState _getFileForSource(Source source) {
    String path = source.fullName;
    return fsState.getFileForPath(path);
  }
}
