// 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,
        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);
  }
}
