// Copyright (c) 2017, 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 'package:_fe_analyzer_shared/src/scanner/string_scanner.dart'
    show StringScanner;

import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;

import 'package:kernel/core_types.dart' show CoreTypes;

import 'package:kernel/kernel.dart'
    show Component, Library, Procedure, DartType, TypeParameter;

import '../base/processed_options.dart' show ProcessedOptions;

import '../fasta/compiler_context.dart' show CompilerContext;

import '../fasta/incremental_compiler.dart' show IncrementalCompiler;

import '../fasta/incremental_serializer.dart' show IncrementalSerializer;

import 'compiler_options.dart' show CompilerOptions;

export '../fasta/incremental_serializer.dart' show IncrementalSerializer;

abstract class IncrementalKernelGenerator {
  factory IncrementalKernelGenerator(
      CompilerOptions options, List<Uri> entryPoints,
      [Uri? initializeFromDillUri,
      bool? outlineOnly,
      IncrementalSerializer? incrementalSerializer]) {
    return new IncrementalCompiler(
        new CompilerContext(
            new ProcessedOptions(options: options, inputs: entryPoints)),
        initializeFromDillUri,
        outlineOnly,
        incrementalSerializer);
  }

  /// Initialize the incremental compiler from a component.
  ///
  /// Notice that the component has to include the platform, and that no other
  /// platform will be loaded.
  factory IncrementalKernelGenerator.fromComponent(
      CompilerOptions options, List<Uri> entryPoints, Component? component,
      [bool? outlineOnly, IncrementalSerializer? incrementalSerializer]) {
    return new IncrementalCompiler.fromComponent(
        new CompilerContext(
            new ProcessedOptions(options: options, inputs: entryPoints)),
        component,
        outlineOnly,
        incrementalSerializer);
  }

  /// Initialize the incremental compiler specifically for expression
  /// compilation where the dill is external and we cannot expect to have access
  /// to the sources.
  ///
  /// The resulting incremental compiler allows for expression compilation,
  /// but not for general compilation. Note that computeDelta will have to be
  /// called once to setup properly though.
  ///
  /// Notice that the component has to include the platform, and that no other
  /// platform will be loaded.
  factory IncrementalKernelGenerator.forExpressionCompilationOnly(
      CompilerOptions options, List<Uri> entryPoints, Component component) {
    return new IncrementalCompiler.forExpressionCompilationOnly(
        new CompilerContext(
            new ProcessedOptions(options: options, inputs: entryPoints)),
        component);
  }

  /// Returns an [IncrementalCompilerResult] with the component whose libraries
  /// are the recompiled libraries, or - in the case of [fullComponent] - a full
  /// Component.
  Future<IncrementalCompilerResult> computeDelta(
      {List<Uri>? entryPoints,
      bool fullComponent = false,
      bool trackNeededDillLibraries = false});

  /// Remove the file associated with the given file [uri] from the set of
  /// valid files.  This guarantees that those files will be re-read on the
  /// next call to [computeDelta]).
  void invalidate(Uri uri);

  /// Invalidate all libraries that were build from source.
  ///
  /// This is equivalent to a number of calls to [invalidate]: One for each URI
  /// that happens to have been read from source.
  /// Said another way, this invalidates everything not loaded from dill
  /// (at startup) or via [setModulesToLoadOnNextComputeDelta].
  void invalidateAllSources();

  /// Set the given [components] as components to load on the next iteration
  /// of [computeDelta].
  ///
  /// If specified, all libraries not compiled from source and not included in
  /// these components will be invalidated and the libraries inside these
  /// components will be loaded instead.
  ///
  /// Useful for, for instance, modular compilation, where modules
  /// (created externally) via this functionality can be added, changed or
  /// removed.
  void setModulesToLoadOnNextComputeDelta(List<Component> components);

  /// Compile [expression] as an [Expression]. A function returning that
  /// expression is compiled.
  ///
  /// [expression] may use the variables supplied in [definitions] as free
  /// variables and [typeDefinitions] as free type variables. These will become
  /// required parameters to the compiled function. All elements of
  /// [definitions] and [typeDefinitions] will become parameters/type
  /// parameters, whether or not they appear free in [expression]. The type
  /// parameters should have a null parent pointer.
  ///
  /// [libraryUri] must refer to either a previously compiled library.
  /// [className] may optionally refer to a class within such library to use for
  /// the scope of the expression. In that case, [isStatic] indicates whether
  /// the scope can access this [IncrementalKernelGenerator].
  ///
  /// It is illegal to use "await" in [expression] and the compiled function
  /// will always be synchronous.
  ///
  /// [computeDelta] must have been called at least once prior.
  ///
  /// [compileExpression] will return [null] if the library or class for
  /// [enclosingNode] could not be found. Otherwise, errors are reported in the
  /// normal way.
  Future<Procedure?> compileExpression(
      String expression,
      Map<String, DartType> definitions,
      List<TypeParameter> typeDefinitions,
      String syntheticProcedureName,
      Uri libraryUri,
      {String? className,
      String? methodName,
      int offset = -1,
      String? scriptUri,
      bool isStatic = false});

  /// Sets experimental features.
  ///
  /// This is currently only meant for testing purposes.
  void setExperimentalFeaturesForTesting(Set<String> features);
}

bool isLegalIdentifier(String identifier) {
  return StringScanner.isLegalIdentifier(identifier);
}

class IncrementalCompilerResult {
  final Component component;
  final ClassHierarchy? classHierarchy;
  final CoreTypes? coreTypes;
  final Set<Library>? neededDillLibraries;

  IncrementalCompilerResult(this.component,
      {this.classHierarchy, this.coreTypes, this.neededDillLibraries});
}
