// 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/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/dart/analysis/restricted_analysis_context.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
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 [],
      Map<String, bool> experiments = const {}}) {
    var resourceProvider = options.resourceProvider;
    var contextBuilder = options.createContextBuilder();

    var analysisOptions =
        contextBuilder.getAnalysisOptions(options.analysisRoot);

    (analysisOptions as AnalysisOptionsImpl).enabledExperiments =
        experiments.entries.where((e) => e.value).map((e) => e.key).toList();

    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());
    }

    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(
        libraryUris.toSet(),
        (uri) => summaryData.linkedMap[uri],
        (uri) => summaryData.unlinkedMap[uri] ?? uriToUnit[uri],
        declaredVariables.get,
        analysisOptions);
    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 = RestrictedAnalysisContext(
        analysisOptions, declaredVariables, sourceFactory);
    var resultProvider = InputPackagesResultProvider(
        context,
        SummaryDataStore([])
          ..addStore(summaryData)
          ..addBundle(null, bundle));

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

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

  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;

  final ResourceProvider _resourceProvider;

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

  TypeProvider get typeProvider => resynthesizer.typeProvider;

  /// 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'),
        resynthesizer.context,
        resynthesizer,
        InheritanceManager2(resynthesizer.typeSystem),
        libraryFile,
        _resourceProvider);
    // 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);
  }
}
