// 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.

part of 'declaration_builders.dart';

const Uri? noUri = null;

abstract class ClassMemberAccess {
  /// [Iterator] for all constructors declared in this class or any of its
  /// augmentations.
  ///
  /// Duplicates and augmenting constructor are _not_ included.
  ///
  /// For instance:
  ///
  ///     class Class {
  ///       Class(); // declared, so it is included
  ///       Class.named(); // declared, so it is included
  ///       Class.named(); // duplicate, so it is *not* included
  ///     }
  ///
  ///     augment class Class {
  ///       augment Class(); // augmenting, so it is *not* included
  ///       Class.extra(); // declared, so it is included
  ///     }
  ///
  Iterator<T> fullConstructorIterator<T extends MemberBuilder>();

  /// [NameIterator] for all constructors declared in this class or any of its
  /// augmentations.
  ///
  /// Duplicates and augmenting constructors are _not_ included.
  ///
  /// For instance:
  ///
  ///     class Class {
  ///       Class(); // declared, so it is included
  ///       Class.named(); // declared, so it is included
  ///       Class.named(); // duplicate, so it is *not* included
  ///     }
  ///
  ///     augment class Class {
  ///       augment Class(); // augmenting, so it is *not* included
  ///       Class.extra(); // declared, so it is included
  ///     }
  ///
  NameIterator<T> fullConstructorNameIterator<T extends MemberBuilder>();

  /// [Iterator] for all members declared in this class or any of its
  /// augmentations.
  ///
  /// Duplicates and augmenting members are _not_ included.
  ///
  /// For instance:
  ///
  ///     class Class {
  ///       method() {} // Declared, so it is included.
  ///       method2() {} // Declared, so it is included.
  ///       method2() {} // Duplicate, so it is *not* included.
  ///     }
  ///
  ///     augment class Class {
  ///       augment method() {} // Augmenting, so it is *not* included.
  ///       extra() {} // Declared, so it is included.
  ///     }
  ///
  Iterator<T> fullMemberIterator<T extends Builder>();

  /// [NameIterator] for all members declared in this class or any of its
  /// augmentations.
  ///
  /// Duplicates and augmenting members are _not_ included.
  ///
  /// For instance:
  ///
  ///     class Class {
  ///       method() {} // Declared, so it is included.
  ///       method2() {} // Declared, so it is included.
  ///       method2() {} // Duplicate, so it is *not* included.
  ///     }
  ///
  ///     augment class Class {
  ///       augment method() {} // Augmenting, so it is *not* included.
  ///       extra() {} // Declared, so it is included.
  ///     }
  ///
  NameIterator<T> fullMemberNameIterator<T extends Builder>();
}

abstract class ClassBuilder implements DeclarationBuilder, ClassMemberAccess {
  /// The type in the `extends` clause of a class declaration.
  ///
  /// Currently this also holds the synthesized super class for a mixin
  /// declaration.
  TypeBuilder? get supertypeBuilder;

  /// The type in the `implements` clause of a class or mixin declaration.
  List<TypeBuilder>? get interfaceBuilders;

  /// The types in the `on` clause of an extension or mixin declaration.
  List<TypeBuilder>? get onTypes;

  @override
  Uri get fileUri;

  bool get isAbstract;

  bool get isMacro;

  bool get isSealed;

  bool get isBase;

  bool get isInterface;

  bool get isFinal;

  bool get declaresConstConstructor;

  bool get isMixinClass;

  bool get isMixinDeclaration;

  bool get isMixinApplication;

  bool get isAnonymousMixinApplication;

  abstract TypeBuilder? mixedInTypeBuilder;

  bool get isFutureOr;

  /// The [Class] built by this builder.
  ///
  /// For an augmentation class the origin class is returned.
  Class get cls;

  @override
  ClassBuilder get origin;

  abstract bool isNullClass;

  @override
  InterfaceType get thisType;

  Supertype buildMixedInType(
      LibraryBuilder library, List<TypeBuilder>? arguments);

  /// Looks up the member by [name] on the class built by this class builder.
  ///
  /// If [isSetter] is `false`, only fields, methods, and getters with that name
  /// will be found.  If [isSetter] is `true`, only non-final fields and setters
  /// will be found.
  ///
  /// If [isSuper] is `false`, the member is found among the interface members
  /// the class built by this class builder. If [isSuper] is `true`, the member
  /// is found among the class members of the superclass.
  ///
  /// If this class builder is an augmentation, interface members declared in
  /// this augmentation are searched before searching the interface members in
  /// the origin class.
  ///
  /// Unused in interface; left in on purpose.
  Member? lookupInstanceMember(ClassHierarchy hierarchy, Name name,
      {bool isSetter = false, bool isSuper = false});
}

abstract class ClassBuilderImpl extends DeclarationBuilderImpl
    implements ClassBuilder {
  @override
  bool isNullClass = false;

  InterfaceType? _legacyRawType;
  InterfaceType? _nullableRawType;
  InterfaceType? _nonNullableRawType;
  InterfaceType? _thisType;

  @override
  bool get isMixinApplication => mixedInTypeBuilder != null;

  @override
  bool get isAnonymousMixinApplication {
    return isMixinApplication &&
        // Coverage-ignore(suite): Not run.
        !isNamedMixinApplication;
  }

  @override
  Builder? findStaticBuilder(
      String name, int fileOffset, Uri fileUri, LibraryBuilder accessingLibrary,
      {bool isSetter = false}) {
    if (accessingLibrary.nameOriginBuilder.origin !=
            libraryBuilder.nameOriginBuilder.origin &&
        name.startsWith("_")) {
      return null;
    }
    Builder? declaration = normalizeLookup(
        getable: nameSpace.lookupLocalMember(name, setter: false),
        setable: nameSpace.lookupLocalMember(name, setter: true),
        name: name,
        charOffset: fileOffset,
        fileUri: fileUri,
        classNameOrDebugName: this.name,
        isSetter: isSetter,
        forStaticAccess: true);
    if (declaration == null && isAugmenting) {
      return origin.findStaticBuilder(
          name, fileOffset, fileUri, accessingLibrary,
          isSetter: isSetter);
    }
    return declaration;
  }

  @override
  Builder? lookupLocalMember(String name,
      {bool setter = false, bool required = false}) {
    Builder? builder = nameSpace.lookupLocalMember(name, setter: setter);
    if (builder == null && isAugmenting) {
      // Coverage-ignore-block(suite): Not run.
      builder = origin.nameSpace.lookupLocalMember(name, setter: setter);
    }
    if (required && builder == null) {
      internalProblem(
          templateInternalProblemNotFoundIn.withArguments(
              name, fullNameForErrors),
          -1,
          null);
    }
    return builder;
  }

  /// Find the first member of this class with [name]. This method isn't
  /// suitable for scope lookups as it will throw an error if the name isn't
  /// declared. The [scope] should be used for that. This method is used to
  /// find a member that is known to exist and it will pick the first
  /// declaration if the name is ambiguous.
  ///
  /// For example, this method is convenient for use when building synthetic
  /// members, such as those of an enum.
  MemberBuilder? firstMemberNamed(String name) {
    MemberBuilder declaration =
        lookupLocalMember(name, required: true) as MemberBuilder;
    while (declaration.next != null) {
      declaration = declaration.next as MemberBuilder;
    }
    return declaration;
  }

  @override
  InterfaceType get thisType {
    return _thisType ??= new InterfaceType(cls, Nullability.nonNullable,
        getAsTypeArguments(cls.typeParameters, libraryBuilder.library));
  }

  // Coverage-ignore(suite): Not run.
  InterfaceType get legacyRawType {
    return _legacyRawType ??= new InterfaceType(cls, Nullability.legacy,
        new List<DartType>.filled(typeParametersCount, const DynamicType()));
  }

  InterfaceType get nullableRawType {
    return _nullableRawType ??= new InterfaceType(cls, Nullability.nullable,
        new List<DartType>.filled(typeParametersCount, const DynamicType()));
  }

  InterfaceType get nonNullableRawType {
    return _nonNullableRawType ??= new InterfaceType(
        cls,
        Nullability.nonNullable,
        new List<DartType>.filled(typeParametersCount, const DynamicType()));
  }

  InterfaceType rawType(Nullability nullability) {
    switch (nullability) {
      case Nullability.legacy:
        // Coverage-ignore(suite): Not run.
        return legacyRawType;
      case Nullability.nullable:
        return nullableRawType;
      case Nullability.nonNullable:
        return nonNullableRawType;
      // Coverage-ignore(suite): Not run.
      case Nullability.undetermined:
        return unhandled("$nullability", "rawType", TreeNode.noOffset, noUri);
    }
  }

  InterfaceType? aliasedTypeWithBuiltArgumentsCacheNonNullable;
  InterfaceType? aliasedTypeWithBuiltArgumentsCacheNullable;

  @override
  bool get isFutureOr {
    if (name == "FutureOr") {
      if (parent.importUri.isScheme("dart") &&
          parent.importUri.path == "async") {
        return true;
      }
    }
    return false;
  }

  @override
  DartType buildAliasedTypeWithBuiltArguments(
      LibraryBuilder library,
      Nullability nullability,
      List<DartType> arguments,
      TypeUse typeUse,
      Uri fileUri,
      int charOffset,
      {required bool hasExplicitTypeArguments}) {
    assert(cls.typeParameters.length == arguments.length);
    if (isNullClass) {
      return const NullType();
    }
    if (isFutureOr) {
      assert(arguments.length == 1);
      return new FutureOrType(arguments.single, nullability);
    }
    if (arguments.isEmpty) {
      return rawType(nullability);
    }
    if (aliasedTypeWithBuiltArgumentsCacheNonNullable != null &&
        // Coverage-ignore(suite): Not run.
        nullability == Nullability.nonNullable) {
      // Coverage-ignore-block(suite): Not run.
      assert(aliasedTypeWithBuiltArgumentsCacheNonNullable!.classReference ==
          cls.reference);
      assert(arguments.isEmpty);
      return aliasedTypeWithBuiltArgumentsCacheNonNullable!;
    } else if (aliasedTypeWithBuiltArgumentsCacheNullable != null &&
        // Coverage-ignore(suite): Not run.
        nullability == Nullability.nullable) {
      // Coverage-ignore-block(suite): Not run.
      assert(aliasedTypeWithBuiltArgumentsCacheNullable!.classReference ==
          cls.reference);
      assert(arguments.isEmpty);
      return aliasedTypeWithBuiltArgumentsCacheNullable!;
    }
    InterfaceType type = new InterfaceType(cls, nullability, arguments);
    if (arguments.isEmpty) {
      // Coverage-ignore-block(suite): Not run.
      assert(typeParametersCount == 0);
      if (nullability == Nullability.nonNullable) {
        aliasedTypeWithBuiltArgumentsCacheNonNullable = type;
      } else if (nullability == Nullability.nullable) {
        aliasedTypeWithBuiltArgumentsCacheNullable = type;
      }
    }

    if (typeParametersCount != 0 && library is SourceLibraryBuilder) {
      library.registerBoundsCheck(type, fileUri, charOffset, typeUse,
          inferred: !hasExplicitTypeArguments);
    }
    return type;
  }

  @override
  DartType buildAliasedType(
      LibraryBuilder library,
      NullabilityBuilder nullabilityBuilder,
      List<TypeBuilder>? arguments,
      TypeUse typeUse,
      Uri fileUri,
      int charOffset,
      ClassHierarchyBase? hierarchy,
      {required bool hasExplicitTypeArguments}) {
    if (name == "Record" &&
        libraryBuilder.importUri.scheme == "dart" &&
        libraryBuilder.importUri.path == "core" &&
        library is SourceLibraryBuilder &&
        !isRecordAccessAllowed(library)) {
      // Coverage-ignore-block(suite): Not run.
      library.reportFeatureNotEnabled(
          library.libraryFeatures.records, fileUri, charOffset, name.length);
      return const InvalidType();
    }
    return buildAliasedTypeWithBuiltArguments(
        library,
        nullabilityBuilder.build(),
        buildAliasedTypeArguments(library, arguments, hierarchy),
        typeUse,
        fileUri,
        charOffset,
        hasExplicitTypeArguments: hasExplicitTypeArguments);
  }

  @override
  Supertype buildMixedInType(
      LibraryBuilder library, List<TypeBuilder>? arguments) {
    Class cls = isAugmenting
        ?
        // Coverage-ignore(suite): Not run.
        origin.cls
        : this.cls;
    if (arguments != null) {
      List<DartType> typeArguments =
          buildAliasedTypeArguments(library, arguments, /* hierarchy = */ null);
      typeArguments = unaliasTypes(typeArguments, legacyEraseAliases: false)!;
      return new Supertype(cls, typeArguments);
    } else {
      return new Supertype(
          cls,
          new List<DartType>.filled(
              cls.typeParameters.length, const UnknownType(),
              growable: true));
    }
  }

  @override
  String get fullNameForErrors {
    return isMixinApplication && !isNamedMixinApplication
        ? "${supertypeBuilder!.fullNameForErrors} with "
            "${mixedInTypeBuilder!.fullNameForErrors}"
        : name;
  }

  @override
  Member? lookupInstanceMember(ClassHierarchy hierarchy, Name name,
      {bool isSetter = false, bool isSuper = false}) {
    Class? instanceClass = cls;
    if (isAugmenting) {
      // Coverage-ignore-block(suite): Not run.
      assert(identical(instanceClass, origin.cls),
          "Found ${origin.cls} expected $instanceClass");
      if (isSuper) {
        // The super class is only correctly found through the origin class.
        instanceClass = origin.cls;
      } else {
        Member? member =
            hierarchy.getInterfaceMember(instanceClass, name, setter: isSetter);
        if (member?.parent == instanceClass) {
          // Only if the member is found in the augmentation can we use it.
          return member;
        } else {
          // Otherwise, we need to keep searching in the origin class.
          instanceClass = origin.cls;
        }
      }
    }

    if (isSuper) {
      instanceClass = instanceClass.superclass;
      if (instanceClass == null) return null;
    }
    Member? target = isSuper
        ? hierarchy.getDispatchTarget(instanceClass, name, setter: isSetter)
        :
        // Coverage-ignore(suite): Not run.
        hierarchy.getInterfaceMember(instanceClass, name, setter: isSetter);
    if (isSuper && target == null) {
      if (cls.isMixinDeclaration) {
        target =
            hierarchy.getInterfaceMember(instanceClass, name, setter: isSetter);
      }
    }
    return target;
  }

  @override
  Nullability computeNullabilityWithArguments(List<TypeBuilder>? typeArguments,
      {required Map<TypeParameterBuilder, TraversalState>
          typeParametersTraversalState}) {
    if (isNullClass) {
      return Nullability.nullable;
    } else if (isFutureOr) {
      if (typeArguments != null && typeArguments.length == 1) {
        return typeArguments.single.computeNullability(
            typeParametersTraversalState: typeParametersTraversalState);
      } else {
        // This is `FutureOr<dynamic>`.
        return Nullability.nullable;
      }
    }
    return Nullability.nonNullable;
  }
}

class ConstructorRedirection {
  String target;
  bool cycleReported;

  ConstructorRedirection(this.target) : cycleReported = false;
}
