// 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/dart/element/inheritance_manager2.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());
    }

    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);
    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,
        InheritanceManager2(context.typeSystem),
        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);
  }
}
