// Copyright (c) 2016, 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/messages/severity.dart' show Severity;
import 'package:front_end/src/builder/property_builder.dart';
import 'package:kernel/ast.dart' show Annotatable, Library, Version;
import 'package:kernel/reference_from_index.dart';

import '../api_prototype/experimental_flags.dart';
import '../base/combinator.dart' show CombinatorBuilder;
import '../base/export.dart' show Export;
import '../base/loader.dart' show Loader;
import '../base/lookup_result.dart';
import '../base/messages.dart'
    show
        FormattedMessage,
        LocatedMessage,
        Message,
        ProblemReporting,
        noLength,
        templateDuplicatedExport,
        templateInternalProblemConstructorNotFound,
        templateInternalProblemNotFoundIn,
        templateInternalProblemPrivateConstructorAccess;
import '../base/name_space.dart';
import '../base/problems.dart' show internalProblem;
import '../base/scope.dart';
import '../base/uri_offset.dart';
import '../fragment/fragment.dart';
import '../kernel/body_builder_context.dart';
import '../kernel/load_library_builder.dart';
import '../source/offset_map.dart';
import '../source/outline_builder.dart';
import '../source/source_class_builder.dart';
import '../source/source_library_builder.dart';
import '../source/source_loader.dart';
import '../source/type_parameter_scope_builder.dart';
import 'builder.dart';
import 'constructor_builder.dart';
import 'declaration_builders.dart';
import 'factory_builder.dart';
import 'member_builder.dart';
import 'metadata_builder.dart';
import 'name_iterator.dart';
import 'prefix_builder.dart';
import 'type_builder.dart';

sealed class CompilationUnit {
  /// Returns the import uri for the compilation unit.
  ///
  /// This is the canonical uri for the compilation unit, for instance
  /// 'dart:core'.
  Uri get importUri;

  Uri get fileUri;

  bool get isSynthetic;

  /// If true, the library is not supported through the 'dart.library.*' value
  /// used in conditional imports and `bool.fromEnvironment` constants.
  bool get isUnsupported;

  Loader get loader;

  /// The [LibraryBuilder] for the library that this compilation unit belongs
  /// to.
  ///
  /// This is only valid after `SourceLoader.resolveParts` has be called.
  LibraryBuilder get libraryBuilder;

  bool get isPart;

  bool get isAugmenting;

  LibraryBuilder? get partOfLibrary;

  /// Returns the [Uri]s for the libraries that this library depend upon, either
  /// through import or export.
  Iterable<Uri> get dependencies;

  void recordAccess(
      CompilationUnit accessor, int charOffset, int length, Uri fileUri);

  List<Export> get exporters;

  void addExporter(CompilationUnit exporter,
      List<CombinatorBuilder>? combinators, int charOffset);

  /// Add a problem with a severity determined by the severity of the message.
  ///
  /// If [fileUri] is null, it defaults to `this.fileUri`.
  ///
  /// See `Loader.addMessage` for an explanation of the
  /// arguments passed to this method.
  void addProblem(Message message, int charOffset, int length, Uri? fileUri,
      {bool wasHandled = false,
      List<LocatedMessage>? context,
      Severity? severity,
      bool problemOnLibrary = false});
}

abstract class DillCompilationUnit implements CompilationUnit {}

abstract class SourceCompilationUnit
    implements CompilationUnit, LibraryFragment {
  OutlineBuilder createOutlineBuilder();

  /// Creates a [SourceLibraryBuilder] for with this [SourceCompilationUnit] as
  /// the main compilation unit.
  SourceLibraryBuilder createLibrary([Library? library]);

  @override
  SourceLoader get loader;

  OffsetMap get offsetMap;

  /// The language version of this compilation unit as defined by the language
  /// version of the package it belongs to, if present, or the current language
  /// version otherwise.
  ///
  /// This language version will be used as the language version for the
  /// compilation unit if the compilation unit does not contain an explicit
  /// `@dart=` annotation.
  LanguageVersion get packageLanguageVersion;

  /// Set the language version to an explicit major and minor version.
  ///
  /// The default language version specified by the `package_config.json` file
  /// is passed to the constructor, but the library can have source code that
  /// specifies another one which should be supported.
  ///
  /// Only the first registered language version is used.
  ///
  /// [offset] and [length] refers to the offset and length of the source code
  /// specifying the language version.
  void registerExplicitLanguageVersion(Version version,
      {int offset = 0, int length = noLength});

  // TODO(johnniwinther): Remove this.
  bool get forAugmentationLibrary;

  // TODO(johnniwinther): Remove this.
  bool get forPatchLibrary;

  /// If this is an compilation unit for an augmentation library, returns the
  /// import uri for the origin library. Otherwise the [importUri] for the
  /// compilation unit itself.
  Uri get originImportUri;

  @override
  SourceLibraryBuilder get libraryBuilder;

  /// The parent compilation unit.
  ///
  /// This is the compilation unit that included this compilation unit as a
  /// part or `null` if this is the root compilation unit of a library.
  SourceCompilationUnit? get parentCompilationUnit;

  LibraryFeatures get libraryFeatures;

  /// Returns `true` if the compilation unit is part of a `dart:` library.
  bool get isDartLibrary;

  LanguageVersion get languageVersion;

  String? get name;

  int finishNativeMethods();

  String? get partOfName;

  Uri? get partOfUri;

  List<MetadataBuilder>? get metadata;

  /// The scope of this compilation unit.
  ///
  /// This is the enclosing scope for all declarations within the compilation
  /// unit.
  LookupScope get compilationUnitScope;

  /// The prefix scope of this compilation unit.
  ///
  /// This contains all imports with prefixes declared in this compilation unit.
  LookupScope get prefixScope;

  NameSpace get prefixNameSpace;

  bool get mayImplementRestrictedTypes;

  void takeMixinApplications(
      Map<SourceClassBuilder, TypeBuilder> mixinApplications);

  void addDependencies(Library library, Set<SourceCompilationUnit> seen);

  /// Runs through all part directives in this compilation unit and adds the
  /// compilation unit for the parts to the [libraryBuilder] by adding them
  /// to [includedParts]
  ///
  /// [usedParts] is used to ensure that a compilation unit is only included in
  /// one library. If the compilation unit is part of two libraries, it is only
  /// included in the first and reported as an error on the second.
  ///
  /// This should only be called on the main compilation unit for
  /// [libraryBuilder]. Inclusion of nested parts is from within this method,
  /// using [becomePart] for each individual subpart.
  void includeParts(
      List<SourceCompilationUnit> includedParts, Set<Uri> usedParts);

  /// Includes this compilation unit as a part of [libraryBuilder] with
  /// [parentCompilationUnit] as the parent compilation unit.
  ///
  /// The parent compilation unit is used to define the compilation unit
  /// scope of this compilation unit.
  ///
  /// All fragment in this compilation unit will be added to
  /// [libraryNameSpaceBuilder].
  ///
  /// If parts with parts is supported (through the enhanced parts feature),
  /// the compilation units of the part directives in this compilation unit
  /// will be added [libraryBuilder] recursively.
  void becomePart(
      SourceLibraryBuilder libraryBuilder,
      LibraryNameSpaceBuilder libraryNameSpaceBuilder,
      SourceCompilationUnit parentCompilationUnit,
      List<SourceCompilationUnit> includedParts,
      Set<Uri> usedParts,
      {required bool allowPartInParts});

  void buildOutlineExpressions(
      {required Annotatable annotatable,
      required Uri annotatableFileUri,
      required BodyBuilderContext bodyBuilderContext});

  /// Reports that [feature] is not enabled, using [charOffset] and
  /// [length] for the location of the message.
  ///
  /// Return the primary message.
  Message reportFeatureNotEnabled(
      LibraryFeature feature, Uri fileUri, int charOffset, int length);

  /// Registers that [augmentation] is a part of the library for which this is
  /// the main compilation unit.
  void registerAugmentation(CompilationUnit augmentation);

  /// Reports [message] on all compilation units that access this compilation
  /// unit.
  void addProblemAtAccessors(Message message);

  Iterable<LibraryAccess> get accessors;

  /// Non-null if this library causes an error upon access, that is, there was
  /// an error reading its source.
  abstract Message? accessProblem;

  /// Add a problem that might not be reported immediately.
  ///
  /// Problems will be issued after source information has been added.
  /// Once the problems has been issued, adding a new "postponed" problem will
  /// be issued immediately.
  void addPostponedProblem(
      Message message, int charOffset, int length, Uri fileUri);

  void issuePostponedProblems();

  void markLanguageVersionFinal();

  /// Index of the library we use references for.
  IndexedLibrary? get indexedLibrary;

  void addSyntheticImport(
      {required String uri,
      required String? prefix,
      required List<CombinatorBuilder>? combinators,
      required bool deferred});

  void addImportedBuilderToScope(
      {required String name,
      required Builder builder,
      required int charOffset});

  void addImportsToScope();

  void buildOutlineNode(Library library);

  int finishDeferredLoadTearOffs(Library library);

  /// This method instantiates type parameters to their bounds in some cases
  /// where they were omitted by the programmer and not provided by the type
  /// inference.  The method returns the number of distinct type parameters
  /// that were instantiated in this library.
  int computeDefaultTypes(TypeBuilder dynamicType, TypeBuilder nullType,
      TypeBuilder bottomType, ClassBuilder objectClass);

  /// Computes variances of type parameters on typedefs.
  ///
  /// The variance property of type parameters on typedefs is computed from the
  /// use of the parameters in the right-hand side of the typedef definition.
  int computeVariances();

  /// Adds all unbound nominal parameters to [nominalParameters] and unbound
  /// structural parameters to [structuralParameters], mapping them to
  /// [libraryBuilder].
  ///
  /// This is used to compute the bounds of type parameters while taking the
  /// bound dependencies, which might span multiple libraries, into account.
  void collectUnboundTypeParameters(
      SourceLibraryBuilder libraryBuilder,
      Map<NominalParameterBuilder, SourceLibraryBuilder> nominalParameters,
      Map<StructuralParameterBuilder, SourceLibraryBuilder>
          structuralParameters);

  /// Adds [prefixFragment] to library name space.
  ///
  /// Returns `true` if the prefix name was new to the name space. Otherwise the
  /// prefix was merged with an existing prefix of the same name.
  // TODO(johnniwinther): Remove this.
  bool addPrefixFragment(
      String name, PrefixFragment prefixFragment, int charOffset);

  int resolveTypes(ProblemReporting problemReporting);
}

abstract class LibraryBuilder implements Builder, ProblemReporting {
  NameSpace get libraryNameSpace;

  NameSpace get exportNameSpace;

  List<Export> get exporters;

  LibraryBuilder? get partOfLibrary;

  LibraryBuilder get nameOriginBuilder;

  bool get mayImplementRestrictedTypes;

  bool get isPart;

  Loader get loader;

  /// Returns the [Library] built by this builder.
  Library get library;

  @override
  Uri get fileUri;

  /// Returns the [Uri]s for the libraries that this library depend upon, either
  /// through import or export.
  Iterable<Uri> get dependencies;

  /// Returns the import uri for the library.
  ///
  /// This is the canonical uri for the library, for instance 'dart:core'.
  Uri get importUri;

  /// Returns the language [Version] used for this library.
  Version get languageVersion;

  /// If true, the library is not supported through the 'dart.library.*' value
  /// used in conditional imports and `bool.fromEnvironment` constants.
  bool get isUnsupported;

  /// Returns an iterator of all members (typedefs, classes and members)
  /// declared in this library, including duplicate declarations.
  // TODO(johnniwinther): Should the only exist on [SourceLibraryBuilder]?
  Iterator<Builder> get localMembersIterator;

  /// Returns an iterator of all members of specified type
  /// declared in this library, including duplicate declarations.
  // TODO(johnniwinther): Should the only exist on [SourceLibraryBuilder]?
  Iterator<T> localMembersIteratorOfType<T extends Builder>();

  /// Returns an iterator of all members (typedefs, classes and members)
  /// declared in this library, including duplicate declarations.
  ///
  /// Compared to [localMembersIterator] this also gives access to the name
  /// that the builders are mapped to.
  NameIterator<Builder> get localMembersNameIterator;

  /// [Iterator] for all declarations declared in this library or any of its
  /// augmentations.
  ///
  /// Duplicates and augmenting members are _not_ included.
  Iterator<T> fullMemberIterator<T extends Builder>();

  /// [NameIterator] for all declarations declared in this class or any of its
  /// augmentations.
  ///
  /// Duplicates and augmenting members are _not_ included.
  NameIterator<T> fullMemberNameIterator<T extends Builder>();

  /// Returns true if the export scope was modified.
  bool addToExportScope(String name, Builder member,
      {required UriOffset uriOffset});

  /// Looks up [constructorName] in the class named [className].
  ///
  /// The class is looked up in this library's export scope unless
  /// [bypassLibraryPrivacy] is true, in which case it is looked up in the
  /// library scope of this library.
  ///
  /// It is an error if no such class is found, or if the class doesn't have a
  /// matching constructor (or factory).
  ///
  /// If [constructorName] is null or the empty string, it's assumed to be an
  /// unnamed constructor. it's an error if [constructorName] starts with
  /// `"_"`, and [bypassLibraryPrivacy] is false.
  MemberBuilder getConstructor(String className,
      {String constructorName, bool bypassLibraryPrivacy = false});

  void becomeCoreLibrary();

  /// Lookups the member [name] declared in this library.
  ///
  /// If [required] is `true` and no member is found an internal problem is
  /// reported.
  Builder? lookupLocalMember(String name, {bool required = false});

  void recordAccess(
      CompilationUnit accessor, int charOffset, int length, Uri fileUri);

  /// Returns `true` if [typeDeclarationBuilder] is the 'Function' class defined
  /// in [coreLibrary].
  static bool isFunction(TypeDeclarationBuilder? typeDeclarationBuilder,
      LibraryBuilder coreLibrary) {
    return typeDeclarationBuilder is ClassBuilder &&
        typeDeclarationBuilder.name == 'Function' &&
        typeDeclarationBuilder.libraryBuilder == coreLibrary;
  }

  /// Returns `true` if [typeDeclarationBuilder] is the 'Record' class defined
  /// in [coreLibrary].
  static bool isRecord(TypeDeclarationBuilder? typeDeclarationBuilder,
      LibraryBuilder coreLibrary) {
    return typeDeclarationBuilder is ClassBuilder &&
        typeDeclarationBuilder.name == 'Record' &&
        typeDeclarationBuilder.libraryBuilder == coreLibrary;
  }
}

abstract class LibraryBuilderImpl extends BuilderImpl
    implements LibraryBuilder {
  @override
  final Uri fileUri;

  LibraryBuilderImpl(this.fileUri);

  @override
  // Coverage-ignore(suite): Not run.
  bool get isSynthetic => false;

  @override
  // Coverage-ignore(suite): Not run.
  Builder? get parent => null;

  @override
  int get fileOffset => -1;

  @override
  bool get isPart => false;

  @override
  Loader get loader;

  @override
  Uri get importUri;

  @override
  Iterator<Builder> get localMembersIterator {
    return libraryNameSpace.filteredIterator(includeDuplicates: true);
  }

  @override
  Iterator<T> localMembersIteratorOfType<T extends Builder>() {
    return libraryNameSpace.filteredIterator<T>(includeDuplicates: true);
  }

  @override
  NameIterator<Builder> get localMembersNameIterator {
    return libraryNameSpace.filteredNameIterator(includeDuplicates: true);
  }

  @override
  FormattedMessage? addProblem(
      Message message, int charOffset, int length, Uri? fileUri,
      {bool wasHandled = false,
      List<LocatedMessage>? context,
      Severity? severity,
      bool problemOnLibrary = false}) {
    fileUri ??= this.fileUri;

    return loader.addProblem(message, charOffset, length, fileUri,
        wasHandled: wasHandled,
        context: context,
        severity: severity,
        problemOnLibrary: true);
  }

  /// Computes a builder for the export collision between [declaration] and
  /// [other]. If [declaration] is declared in [libraryNameSpace] then this is
  /// returned instead of reporting a collision.
  Builder _computeAmbiguousDeclarationForExport(
      String name, Builder declaration, Builder other,
      {required UriOffset uriOffset}) {
    // Prefix builders and load library builders are not part of an export
    // scope.
    assert(declaration is! PrefixBuilder,
        "Unexpected prefix builder $declaration.");
    assert(other is! PrefixBuilder, "Unexpected prefix builder $other.");
    assert(declaration is! LoadLibraryBuilder,
        "Unexpected load library builder $declaration.");
    assert(other is! LoadLibraryBuilder,
        "Unexpected load library builder $other.");

    if (declaration == other) return declaration;
    if (declaration is InvalidTypeDeclarationBuilder) return declaration;
    if (other is InvalidTypeDeclarationBuilder) return other;
    Builder? preferred;
    Uri? uri;
    Uri? otherUri;
    if (libraryNameSpace.lookupLocalMember(name)?.getable == declaration) {
      return declaration;
    } else {
      uri = computeLibraryUri(declaration);
      otherUri = computeLibraryUri(other);
      if (otherUri.isScheme("dart") && !uri.isScheme("dart")) {
        preferred = declaration;
      } else if (uri.isScheme("dart") && !otherUri.isScheme("dart")) {
        preferred = other;
      }
    }
    if (preferred != null) {
      return preferred;
    }

    Uri firstUri = uri;
    Uri secondUri = otherUri;
    if (firstUri.toString().compareTo(secondUri.toString()) > 0) {
      firstUri = secondUri;
      secondUri = uri;
    }

    // TODO(ahe): We should probably use a context object here
    // instead of including URIs in this message.
    Message message =
        templateDuplicatedExport.withArguments(name, firstUri, secondUri);
    addProblem(message, uriOffset.fileOffset, noLength, uriOffset.uri);
    // We report the error lazily (setting suppressMessage to false) because the
    // spec 18.1 states that 'It is not an error if N is introduced by two or
    // more imports but never referred to.'
    return new InvalidTypeDeclarationBuilder(name,
        message.withLocation(uriOffset.uri, uriOffset.fileOffset, name.length),
        suppressMessage: false);
  }

  @override
  bool addToExportScope(String name, Builder member,
      {required UriOffset uriOffset}) {
    if (name.startsWith("_")) return false;
    if (member is PrefixBuilder) return false;
    bool isSetter = isMappedAsSetter(member);
    LookupResult? result = exportNameSpace.lookupLocalMember(name);
    Builder? existing = isSetter ? result?.setable : result?.getable;
    if (existing == member) {
      return false;
    } else {
      if (member is MemberBuilder && member.isConflictingSetter) {
        // TODO(johnniwinther): Remove this case when getables and setables are
        //  contained in the same map in the name space.
        exportNameSpace.addLocalMember(name, member, setter: isSetter);
        return true;
      } else if (existing != null) {
        exportNameSpace.lookupLocalMember(name);
        Builder result = _computeAmbiguousDeclarationForExport(
            name, existing, member,
            uriOffset: uriOffset);
        exportNameSpace.addLocalMember(name, result, setter: isSetter);
        return result != existing;
      } else {
        exportNameSpace.addLocalMember(name, member, setter: isSetter);
        return true;
      }
    }
  }

  @override
  MemberBuilder getConstructor(String className,
      {String? constructorName, bool bypassLibraryPrivacy = false}) {
    constructorName ??= "";
    if (constructorName.startsWith("_") && !bypassLibraryPrivacy) {
      return internalProblem(
          templateInternalProblemPrivateConstructorAccess
              .withArguments(constructorName),
          -1,
          null);
    }
    Builder? cls = (bypassLibraryPrivacy ? libraryNameSpace : exportNameSpace)
        .lookupLocalMember(className)
        ?.getable;
    if (cls is TypeAliasBuilder) {
      // Coverage-ignore-block(suite): Not run.
      TypeAliasBuilder aliasBuilder = cls;
      // No type arguments are available, but this method is only called in
      // order to find constructors of specific non-generic classes (errors),
      // so we can pass the empty list.
      cls = aliasBuilder.unaliasDeclaration(const <TypeBuilder>[]);
    }
    if (cls is ClassBuilder) {
      // TODO(ahe): This code is similar to code in `endNewExpression` in
      // `body_builder.dart`, try to share it.
      MemberBuilder? constructor =
          cls.findConstructorOrFactory(constructorName, -1, fileUri, this);
      if (constructor == null) {
        // Fall-through to internal error below.
      } else if (constructor is ConstructorBuilder) {
        if (!cls.isAbstract) {
          return constructor;
        }
      }
      // Coverage-ignore(suite): Not run.
      else if (constructor is FactoryBuilder) {
        return constructor;
      }
    }
    // Coverage-ignore-block(suite): Not run.
    throw internalProblem(
        templateInternalProblemConstructorNotFound.withArguments(
            "$className.$constructorName", importUri),
        -1,
        null);
  }

  @override
  Builder? lookupLocalMember(String name, {bool required = false}) {
    Builder? builder = libraryNameSpace.lookupLocalMember(name)?.getable;
    if (required && builder == null) {
      internalProblem(
          templateInternalProblemNotFoundIn.withArguments(
              name, fullNameForErrors),
          -1,
          null);
    }
    return builder;
  }

  @override
  void recordAccess(
      CompilationUnit accessor, int charOffset, int length, Uri fileUri) {}

  @override
  String toString() {
    return '$runtimeType(${isPart ? fileUri : importUri})';
  }
}
