// Copyright (c) 2014, 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 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:_fe_analyzer_shared/src/parser/util.dart' as shared;
import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer_operations.dart'
    show Variance;
import 'package:_fe_analyzer_shared/src/types/shared_type.dart';
import 'package:analyzer/dart/analysis/analysis_options.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/syntactic_entity.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/analysis/analysis_options.dart';
import 'package:analyzer/src/dart/analysis/file_analysis.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/results.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/class_hierarchy.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/extensions.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/non_covariant_type_parameter_position.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/element/well_bounded.dart';
import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/diagnostic/diagnostic.dart';
import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/error/const_argument_verifier.dart';
import 'package:analyzer/src/error/constructor_fields_verifier.dart';
import 'package:analyzer/src/error/correct_override.dart';
import 'package:analyzer/src/error/duplicate_definition_verifier.dart';
import 'package:analyzer/src/error/getter_setter_types_verifier.dart';
import 'package:analyzer/src/error/literal_element_verifier.dart';
import 'package:analyzer/src/error/required_parameters_verifier.dart';
import 'package:analyzer/src/error/return_type_verifier.dart';
import 'package:analyzer/src/error/super_formal_parameters_verifier.dart';
import 'package:analyzer/src/error/type_arguments_verifier.dart';
import 'package:analyzer/src/error/use_result_verifier.dart';
import 'package:analyzer/src/generated/element_resolver.dart';
import 'package:analyzer/src/generated/error_detection_helpers.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
import 'package:analyzer/src/summary2/macro_application_error.dart';
import 'package:analyzer/src/summary2/macro_type_location.dart';
import 'package:analyzer/src/utilities/extensions/element.dart';
import 'package:analyzer/src/utilities/extensions/object.dart';
import 'package:analyzer/src/utilities/extensions/string.dart';
import 'package:collection/collection.dart';
import 'package:macros/macros.dart' as macro;

class EnclosingExecutableContext {
  final ExecutableElement? element;
  final bool isAsynchronous;
  final bool isConstConstructor;
  final bool isGenerativeConstructor;
  final bool isGenerator;
  final bool inFactoryConstructor;
  final bool inStaticMethod;

  /// If this [EnclosingExecutableContext] is the first argument in a method
  /// invocation of [Future.catchError], returns the return type expected for
  /// `Future<T>.catchError`'s `onError` parameter, which is `FutureOr<T>`,
  /// otherwise `null`.
  final InterfaceType? catchErrorOnErrorReturnType;

  /// The return statements that have a value.
  final List<ReturnStatement> _returnsWith = [];

  /// The return statements that do not have a value.
  final List<ReturnStatement> _returnsWithout = [];

  /// This flag is set to `false` when the declared return type is not legal
  /// for the kind of the function body, e.g. not `Future` for `async`.
  bool hasLegalReturnType = true;

  /// The number of enclosing [CatchClause] in this executable.
  int catchClauseLevel = 0;

  EnclosingExecutableContext(this.element,
      {bool? isAsynchronous, this.catchErrorOnErrorReturnType})
      : isAsynchronous =
            isAsynchronous ?? (element != null && element.isAsynchronous),
        isConstConstructor = element is ConstructorElement && element.isConst,
        isGenerativeConstructor =
            element is ConstructorElement && !element.isFactory,
        isGenerator = element != null && element.isGenerator,
        inFactoryConstructor = _inFactoryConstructor(element),
        inStaticMethod = _inStaticMethod(element);

  EnclosingExecutableContext.empty() : this(null);

  factory EnclosingExecutableContext.tmp(ExecutableElement2? element,
      {bool? isAsynchronous, InterfaceType? catchErrorOnErrorReturnType}) {
    return EnclosingExecutableContext(
      element.asElement,
      isAsynchronous: isAsynchronous,
      catchErrorOnErrorReturnType: catchErrorOnErrorReturnType,
    );
  }

  String? get displayName {
    return element?.displayName;
  }

  bool get isClosure {
    return element is FunctionElement && element!.displayName.isEmpty;
  }

  bool get isConstructor => element is ConstructorElement;

  bool get isFunction {
    if (element is FunctionElement) {
      return element!.displayName.isNotEmpty;
    }
    return element is PropertyAccessorElement;
  }

  bool get isMethod => element is MethodElement;

  bool get isSynchronous => !isAsynchronous;

  DartType get returnType {
    return catchErrorOnErrorReturnType ?? element!.returnType;
  }

  static bool _inFactoryConstructor(Element? element) {
    var enclosing = element?.enclosingElement3;
    if (enclosing == null) {
      return false;
    }
    if (element is ConstructorElement) {
      return element.isFactory;
    }
    return _inFactoryConstructor(enclosing);
  }

  static bool _inStaticMethod(Element? element) {
    var enclosing = element?.enclosingElement3;
    if (enclosing == null) {
      return false;
    }
    if (enclosing is InterfaceElement || enclosing is ExtensionElement) {
      if (element is ExecutableElement) {
        return element.isStatic;
      }
    }
    return _inStaticMethod(enclosing);
  }
}

/// A visitor used to traverse an AST structure looking for additional errors
/// and warnings not covered by the parser and resolver.
class ErrorVerifier extends RecursiveAstVisitor<void>
    with ErrorDetectionHelpers {
  /// The error reporter by which errors will be reported.
  @override
  final ErrorReporter errorReporter;

  /// The current library that is being analyzed.
  final LibraryElementImpl _currentLibrary;

  /// The current unit that is being analyzed.
  final CompilationUnitElementImpl _currentUnit;

  /// The type representing the type 'int'.
  late final InterfaceType _intType;

  /// The options for verification.
  final AnalysisOptions options;

  /// The object providing access to the types defined by the language.
  final TypeProvider _typeProvider;

  /// The type system primitives
  @override
  late final TypeSystemImpl typeSystem;

  /// The manager for the inheritance mappings.
  final InheritanceManager3 _inheritanceManager;

  /// A flag indicating whether the visitor is currently within a comment.
  bool _isInComment = false;

  /// The stack of flags, where `true` at the top (last) of the stack indicates
  /// that the visitor is in the initializer of a lazy local variable. When the
  /// top is `false`, we might be not in a local variable, or it is not `lazy`,
  /// etc.
  final List<bool> _isInLateLocalVariable = [false];

  /// A flag indicating whether the visitor is currently within a native class
  /// declaration.
  bool _isInNativeClass = false;

  /// A flag indicating whether the visitor is currently within a static
  /// variable declaration.
  bool _isInStaticVariableDeclaration = false;

  /// A flag indicating whether the visitor is currently within an instance
  /// variable declaration, which is not `late`.
  bool _isInInstanceNotLateVariableDeclaration = false;

  /// A flag indicating whether the visitor is currently within a constructor
  /// initializer.
  bool _isInConstructorInitializer = false;

  /// This is set to `true` iff the visitor is currently within a function typed
  /// formal parameter.
  bool _isInFunctionTypedFormalParameter = false;

  /// A flag indicating whether the visitor is currently within code in the SDK.
  bool _isInSystemLibrary = false;

  /// The class containing the AST nodes being visited, or `null` if we are not
  /// in the scope of a class.
  InterfaceElement? _enclosingClass;

  /// The element of the extension being visited, or `null` if we are not
  /// in the scope of an extension.
  ExtensionElement? _enclosingExtension;

  /// Whether the current location has access to `this`.
  bool _hasAccessToThis = false;

  /// The context of the method or function that we are currently visiting, or
  /// `null` if we are not inside a method or function.
  EnclosingExecutableContext _enclosingExecutable =
      EnclosingExecutableContext.empty();

  /// A set of the names of the variable initializers we are visiting now.
  final HashSet<String> _namesForReferenceToDeclaredVariableInInitializer =
      HashSet<String>();

  /// The elements that will be defined later in the current scope, but right
  /// now are not declared.
  HiddenElements? _hiddenElements;

  final _UninstantiatedBoundChecker _uninstantiatedBoundChecker;

  /// The features enabled in the unit currently being checked for errors.
  FeatureSet? _featureSet;

  final LibraryVerificationContext libraryContext;
  final RequiredParametersVerifier _requiredParametersVerifier;
  final ConstArgumentsVerifier _constArgumentsVerifier;
  final DuplicateDefinitionVerifier _duplicateDefinitionVerifier;
  final UseResultVerifier _checkUseVerifier;
  late final TypeArgumentsVerifier _typeArgumentsVerifier;
  late final ReturnTypeVerifier _returnTypeVerifier;
  final TypeSystemOperations typeSystemOperations;

  /// Initialize a newly created error verifier.
  ErrorVerifier(
    this.errorReporter,
    this._currentLibrary,
    this._currentUnit,
    this._typeProvider,
    this._inheritanceManager,
    this.libraryContext,
    this.options, {
    required this.typeSystemOperations,
  })  : _uninstantiatedBoundChecker =
            _UninstantiatedBoundChecker(errorReporter),
        _checkUseVerifier = UseResultVerifier(errorReporter),
        _requiredParametersVerifier = RequiredParametersVerifier(errorReporter),
        _constArgumentsVerifier = ConstArgumentsVerifier(errorReporter),
        _duplicateDefinitionVerifier = DuplicateDefinitionVerifier(
          _currentLibrary,
          errorReporter,
          libraryContext.duplicationDefinitionContext,
        ) {
    _isInSystemLibrary = _currentLibrary.source.uri.isScheme('dart');
    _isInStaticVariableDeclaration = false;
    _isInConstructorInitializer = false;
    _intType = _typeProvider.intType;
    typeSystem = _currentLibrary.typeSystem;
    _typeArgumentsVerifier =
        TypeArgumentsVerifier(options, _currentLibrary, errorReporter);
    _returnTypeVerifier = ReturnTypeVerifier(
      typeProvider: _typeProvider as TypeProviderImpl,
      typeSystem: typeSystem,
      errorReporter: errorReporter,
      strictCasts: strictCasts,
    );
  }

  InterfaceElement? get enclosingClass => _enclosingClass;

  /// For consumers of error verification as a library, (currently just the
  /// angular plugin), expose a setter that can make the errors reported more
  /// accurate when dangling code snippets are being resolved from a class
  /// context. Note that this setter is very defensive for potential misuse; it
  /// should not be modified in the middle of visiting a tree and requires an
  /// analyzer-provided Impl instance to work.
  set enclosingClass(InterfaceElement? interfaceElement) {
    assert(_enclosingClass == null);
    assert(_enclosingExecutable.element == null);
  }

  @override
  InheritanceManager3 get inheritance => _inheritanceManager;

  @override
  bool get strictCasts => options.strictCasts;

  /// The language team is thinking about adding abstract fields, or external
  /// fields. But for now we will ignore such fields in `Struct` subtypes.
  bool get _isEnclosingClassFfiStruct {
    var superClass = _enclosingClass?.supertype?.element;
    return superClass != null &&
        _isDartFfiLibrary(superClass.library) &&
        superClass.name == 'Struct';
  }

  /// The language team is thinking about adding abstract fields, or external
  /// fields. But for now we will ignore such fields in `Struct` subtypes.
  bool get _isEnclosingClassFfiUnion {
    var superClass = _enclosingClass?.supertype?.element;
    return superClass != null &&
        _isDartFfiLibrary(superClass.library) &&
        superClass.name == 'Union';
  }

  @override
  List<DiagnosticMessage> computeWhyNotPromotedMessages(
      SyntacticEntity errorEntity,
      Map<SharedTypeView<DartType>, NonPromotionReason>? whyNotPromoted) {
    return [];
  }

  @override
  void visitAnnotation(Annotation node) {
    _checkForInvalidAnnotationFromDeferredLibrary(node);
    _requiredParametersVerifier.visitAnnotation(node);
    super.visitAnnotation(node);
  }

  @override
  void visitAsExpression(AsExpression node) {
    _checkForTypeAnnotationDeferredClass(node.type);
    super.visitAsExpression(node);
  }

  @override
  void visitAssertInitializer(AssertInitializer node) {
    _isInConstructorInitializer = true;
    try {
      super.visitAssertInitializer(node);
    } finally {
      _isInConstructorInitializer = false;
    }
  }

  @override
  void visitAssignmentExpression(AssignmentExpression node) {
    TokenType operatorType = node.operator.type;
    Expression lhs = node.leftHandSide;
    if (operatorType == TokenType.QUESTION_QUESTION_EQ) {
      _checkForDeadNullCoalesce(node.readType as TypeImpl, node.rightHandSide);
    }
    _checkForAssignmentToFinal(lhs);

    _constArgumentsVerifier.visitAssignmentExpression(node);
    super.visitAssignmentExpression(node);
  }

  @override
  void visitAwaitExpression(AwaitExpression node) {
    if (!_enclosingExecutable.isAsynchronous) {
      errorReporter.atToken(
        node.awaitKeyword,
        CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT,
      );
    }
    checkForUseOfVoidResult(node.expression);
    _checkForAwaitInLateLocalVariableInitializer(node);
    _checkForAwaitOfIncompatibleType(node);
    super.visitAwaitExpression(node);
  }

  @override
  void visitBinaryExpression(BinaryExpression node) {
    Token operator = node.operator;
    TokenType type = operator.type;
    if (type == TokenType.AMPERSAND_AMPERSAND || type == TokenType.BAR_BAR) {
      checkForUseOfVoidResult(node.rightOperand);
    } else {
      // Assignability checking is done by the resolver.
    }

    if (type == TokenType.QUESTION_QUESTION) {
      _checkForDeadNullCoalesce(
          node.leftOperand.staticType as TypeImpl, node.rightOperand);
    }

    checkForUseOfVoidResult(node.leftOperand);
    _constArgumentsVerifier.visitBinaryExpression(node);

    super.visitBinaryExpression(node);
  }

  @override
  void visitBlock(Block node) {
    _withHiddenElements(node.statements, () {
      _duplicateDefinitionVerifier.checkStatements(node.statements);
      super.visitBlock(node);
    });
  }

  @override
  void visitBlockFunctionBody(BlockFunctionBody node) {
    var oldHasAccessToThis = _hasAccessToThis;
    try {
      _hasAccessToThis = _computeThisAccessForFunctionBody(node);
      super.visitBlockFunctionBody(node);
    } finally {
      _hasAccessToThis = oldHasAccessToThis;
    }
  }

  @override
  void visitBreakStatement(BreakStatement node) {
    var labelNode = node.label;
    if (labelNode != null) {
      var labelElement = labelNode.staticElement;
      if (labelElement is LabelElementImpl && labelElement.isOnSwitchMember) {
        errorReporter.atNode(
          labelNode,
          CompileTimeErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER,
        );
      }
    }
  }

  @override
  void visitCatchClause(CatchClause node) {
    _duplicateDefinitionVerifier.checkCatchClause(node);
    try {
      _enclosingExecutable.catchClauseLevel++;
      _checkForTypeAnnotationDeferredClass(node.exceptionType);
      super.visitCatchClause(node);
    } finally {
      _enclosingExecutable.catchClauseLevel--;
    }
  }

  @override
  void visitClassDeclaration(covariant ClassDeclarationImpl node) {
    try {
      var declaredFragment = node.declaredElement!;
      var declaredElement = declaredFragment.element;
      var firstFragment = declaredElement.firstFragment;

      _checkAugmentations(
        augmentKeyword: node.augmentKeyword,
        element: declaredFragment,
      );

      _checkClassAugmentationModifiers(
        augmentKeyword: node.augmentKeyword,
        augmentationNode: node,
        augmentationElement: declaredFragment,
      );

      if (!identical(firstFragment, declaredFragment)) {
        _checkAugmentationTypeParameters(
          nameToken: node.name,
          typeParameterList: node.typeParameters,
          declarationTypeParameters: firstFragment.typeParameters,
        );
      }

      _checkClassAugmentationTargetAlreadyHasExtendsClause(
        node: node,
        augmentationTarget: declaredFragment.augmentationTarget,
      );

      _isInNativeClass = node.nativeClause != null;

      var augmented = declaredFragment.element;
      var declarationElement = augmented.firstFragment;
      _enclosingClass = declarationElement;

      List<ClassMember> members = node.members;
      if (!declarationElement.isDartCoreFunctionImpl) {
        _checkForBuiltInIdentifierAsName(
            node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME);
      }
      _checkForConflictingClassTypeVariableErrorCodes();
      var superclass = node.extendsClause?.superclass;
      var implementsClause = node.implementsClause;
      var withClause = node.withClause;

      // Only do error checks on the clause nodes if there is a non-null clause
      if (implementsClause != null ||
          superclass != null ||
          withClause != null) {
        var moreChecks = _checkClassInheritance(
            declarationElement, node, superclass, withClause, implementsClause);
        if (moreChecks) {
          _checkForNoDefaultSuperConstructorImplicit(
              declaredFragment, augmented);
        }
      }

      if (node.nativeClause == null) {
        libraryContext.constructorFieldsVerifier
            .addConstructors(errorReporter, augmented, members);
      }

      _checkForConflictingClassMembers(declaredFragment);
      _checkForFinalNotInitializedInClass(declaredFragment, members);
      _checkForBadFunctionUse(
        superclass: node.extendsClause?.superclass,
        withClause: node.withClause,
        implementsClause: node.implementsClause,
      );
      _checkForWrongTypeParameterVarianceInSuperinterfaces();
      _checkForMainFunction1(node.name, node.declaredElement!);
      _checkForMixinClassErrorCodes(node, members, superclass, withClause);
      _reportMacroDiagnostics(declaredFragment);

      GetterSetterTypesVerifier(
        typeSystem: typeSystem,
        errorReporter: errorReporter,
      ).checkStaticGetters(augmented.getters2);

      super.visitClassDeclaration(node);
    } finally {
      _isInNativeClass = false;
      _enclosingClass = null;
    }
  }

  @override
  void visitClassTypeAlias(covariant ClassTypeAliasImpl node) {
    var element = node.declaredElement!;
    var augmented = element.augmented;
    var declarationElement = augmented.firstFragment;

    _checkForBuiltInIdentifierAsName(
        node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME);
    try {
      _enclosingClass = declarationElement;
      _checkClassInheritance(declarationElement, node, node.superclass,
          node.withClause, node.implementsClause);
      _checkForMainFunction1(node.name, node.declaredElement!);
      _checkForMixinClassErrorCodes(
          node, List.empty(), node.superclass, node.withClause);
      _checkForBadFunctionUse(
        superclass: node.superclass,
        withClause: node.withClause,
        implementsClause: node.implementsClause,
      );
      _checkForWrongTypeParameterVarianceInSuperinterfaces();
    } finally {
      _enclosingClass = null;
    }
    super.visitClassTypeAlias(node);
  }

  @override
  void visitComment(Comment node) {
    _isInComment = true;
    try {
      super.visitComment(node);
    } finally {
      _isInComment = false;
    }
  }

  @override
  void visitCompilationUnit(covariant CompilationUnitImpl node) {
    var fragment = node.declaredFragment!;
    _featureSet = node.featureSet;
    _duplicateDefinitionVerifier.checkUnit(node);
    _checkForDeferredPrefixCollisions(node);
    _checkForIllegalLanguageOverride(node);

    GetterSetterTypesVerifier(
      typeSystem: typeSystem,
      errorReporter: errorReporter,
    ).checkStaticGetters(fragment.element.getters);

    super.visitCompilationUnit(node);
    _featureSet = null;
  }

  @override
  void visitConstructorDeclaration(
    covariant ConstructorDeclarationImpl node,
  ) {
    var element = node.declaredElement!;
    _withEnclosingExecutable(element, () {
      _checkForNonConstGenerativeEnumConstructor(node);
      _checkForInvalidModifierOnBody(
          node.body, CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR);
      if (!_checkForConstConstructorWithNonConstSuper(node)) {
        _checkForConstConstructorWithNonFinalField(node, element);
      }
      _checkForRedirectingConstructorErrorCodes(node);
      _checkForConflictingInitializerErrorCodes(node);
      _checkForRecursiveConstructorRedirect(node, element);
      if (!_checkForRecursiveFactoryRedirect(node, element)) {
        _checkForAllRedirectConstructorErrorCodes(node);
      }
      _checkForUndefinedConstructorInInitializerImplicit(node);
      _checkForReturnInGenerativeConstructor(node);
      _checkAugmentations(
        augmentKeyword: node.augmentKeyword,
        element: element,
      );
      _reportMacroDiagnostics(element);
      super.visitConstructorDeclaration(node);
    });
  }

  @override
  void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
    _isInConstructorInitializer = true;
    try {
      SimpleIdentifier fieldName = node.fieldName;
      var staticElement = fieldName.staticElement;
      _checkForInvalidField(node, fieldName, staticElement);
      if (staticElement is FieldElement) {
        _checkForAbstractOrExternalFieldConstructorInitializer(
            node.fieldName.token, staticElement);
      }
      super.visitConstructorFieldInitializer(node);
    } finally {
      _isInConstructorInitializer = false;
    }
  }

  @override
  void visitConstructorReference(ConstructorReference node) {
    _typeArgumentsVerifier.checkConstructorReference(node);
    _checkForInvalidGenerativeConstructorReference(node.constructorName);
  }

  @override
  void visitDefaultFormalParameter(DefaultFormalParameter node) {
    var defaultValue = node.defaultValue;
    if (defaultValue != null) {
      checkForAssignableExpressionAtType(
        defaultValue,
        defaultValue.typeOrThrow,
        node.declaredElement!.type,
        CompileTimeErrorCode.INVALID_ASSIGNMENT,
      );
    }

    super.visitDefaultFormalParameter(node);
  }

  @override
  void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
    var element = node.declaredElement as FieldElementImpl;

    _checkAugmentations(
      augmentKeyword: node.augmentKeyword,
      element: element,
    );

    _requiredParametersVerifier.visitEnumConstantDeclaration(node);
    _typeArgumentsVerifier.checkEnumConstantDeclaration(node);
    super.visitEnumConstantDeclaration(node);
  }

  @override
  void visitEnumDeclaration(covariant EnumDeclarationImpl node) {
    try {
      var declaredFragment = node.declaredElement!;
      var declaredElement = declaredFragment.element;
      var firstFragment = declaredElement.firstFragment;

      _checkAugmentations(
        augmentKeyword: node.augmentKeyword,
        element: declaredFragment,
      );

      if (!identical(firstFragment, declaredFragment)) {
        _checkAugmentationTypeParameters(
          nameToken: node.name,
          typeParameterList: node.typeParameters,
          declarationTypeParameters: firstFragment.typeParameters,
        );
      }

      var augmented = declaredFragment.augmented;
      var declarationElement = augmented.firstFragment;
      _enclosingClass = declarationElement;

      _checkForBuiltInIdentifierAsName(
          node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME);
      _checkForConflictingEnumTypeVariableErrorCodes(declaredFragment);
      var implementsClause = node.implementsClause;
      var withClause = node.withClause;

      if (implementsClause != null || withClause != null) {
        _checkClassInheritance(
            declarationElement, node, null, withClause, implementsClause);
      }

      if (!declaredFragment.isAugmentation) {
        if (declaredFragment.augmented.constants.isEmpty) {
          errorReporter.atToken(
            node.name,
            CompileTimeErrorCode.ENUM_WITHOUT_CONSTANTS,
          );
        }
      }

      var members = node.members;
      libraryContext.constructorFieldsVerifier
          .addConstructors(errorReporter, augmented, members);
      _checkForFinalNotInitializedInClass(declaredFragment, members);
      _checkForWrongTypeParameterVarianceInSuperinterfaces();
      _checkForMainFunction1(node.name, node.declaredElement!);
      _checkForEnumInstantiatedToBoundsIsNotWellBounded(node, declaredFragment);

      GetterSetterTypesVerifier(
        typeSystem: typeSystem,
        errorReporter: errorReporter,
      ).checkStaticGetters(declaredElement.getters2);

      super.visitEnumDeclaration(node);
    } finally {
      _enclosingClass = null;
    }
  }

  @override
  void visitExportDirective(ExportDirective node) {
    var exportElement = node.element;
    if (exportElement != null) {
      var exportedLibrary = exportElement.exportedLibrary;
      _checkForAmbiguousExport(node, exportElement, exportedLibrary);
      _checkForExportInternalLibrary(node, exportElement);
    }
    super.visitExportDirective(node);
  }

  @override
  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
    var oldHasAccessToThis = _hasAccessToThis;
    try {
      _hasAccessToThis = _computeThisAccessForFunctionBody(node);
      _returnTypeVerifier.verifyExpressionFunctionBody(node);
      super.visitExpressionFunctionBody(node);
    } finally {
      _hasAccessToThis = oldHasAccessToThis;
    }
  }

  @override
  void visitExtensionDeclaration(covariant ExtensionDeclarationImpl node) {
    var declaredFragment = node.declaredElement!;
    var declaredElement = declaredFragment.element;
    var firstFragment = declaredElement.firstFragment;

    _checkAugmentations(
      augmentKeyword: node.augmentKeyword,
      element: declaredFragment,
    );

    if (!identical(firstFragment, declaredFragment)) {
      if (node.name case var nameToken?) {
        _checkAugmentationTypeParameters(
          nameToken: nameToken,
          typeParameterList: node.typeParameters,
          declarationTypeParameters: firstFragment.typeParameters,
        );
      }
    }

    _enclosingExtension = declaredFragment;
    _checkForConflictingExtensionTypeVariableErrorCodes();
    _checkForFinalNotInitializedInClass(declaredFragment, node.members);

    GetterSetterTypesVerifier(
      typeSystem: typeSystem,
      errorReporter: errorReporter,
    ).checkExtension(declaredElement);

    var name = node.name;
    if (name != null) {
      _checkForBuiltInIdentifierAsName(
          name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_EXTENSION_NAME);
    }
    super.visitExtensionDeclaration(node);
    _enclosingExtension = null;
  }

  @override
  void visitExtensionTypeDeclaration(
    covariant ExtensionTypeDeclarationImpl node,
  ) {
    try {
      var declaredFragment = node.declaredElement!;
      var declaredElement = declaredFragment.augmented;
      var firstFragment = declaredElement.firstFragment;

      _checkAugmentations(
        augmentKeyword: node.augmentKeyword,
        element: declaredFragment,
      );

      if (!identical(firstFragment, declaredFragment)) {
        _checkAugmentationTypeParameters(
          nameToken: node.name,
          typeParameterList: node.typeParameters,
          declarationTypeParameters: firstFragment.typeParameters,
        );
      }

      _enclosingClass = firstFragment;

      _checkForBuiltInIdentifierAsName(node.name,
          CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_EXTENSION_TYPE_NAME);
      _checkForConflictingExtensionTypeTypeVariableErrorCodes(declaredFragment);

      var members = node.members;
      _checkForRepeatedType(
        libraryContext.setOfImplements(firstFragment),
        node.implementsClause?.interfaces,
        CompileTimeErrorCode.IMPLEMENTS_REPEATED,
      );
      _checkForConflictingClassMembers(declaredFragment);
      _checkForConflictingGenerics(node);
      libraryContext.constructorFieldsVerifier
          .addConstructors(errorReporter, declaredElement, members);
      _checkForNonCovariantTypeParameterPositionInRepresentationType(
          node, declaredFragment);
      _checkForExtensionTypeRepresentationDependsOnItself(
          node, declaredFragment);
      _checkForExtensionTypeRepresentationTypeBottom(node, declaredFragment);
      _checkForExtensionTypeImplementsDeferred(node);
      _checkForExtensionTypeImplementsItself(node, declaredFragment);
      _checkForExtensionTypeMemberConflicts(
        node: node,
        element: firstFragment,
      );
      _checkForExtensionTypeWithAbstractMember(node);
      _checkForWrongTypeParameterVarianceInSuperinterfaces();

      var interface = _inheritanceManager.getInterface(firstFragment);
      GetterSetterTypesVerifier(
        typeSystem: typeSystem,
        errorReporter: errorReporter,
      ).checkExtensionType(declaredElement, interface);

      super.visitExtensionTypeDeclaration(node);
    } finally {
      _enclosingClass = null;
    }
  }

  @override
  void visitFieldDeclaration(covariant FieldDeclarationImpl node) {
    var fields = node.fields;
    _isInStaticVariableDeclaration = node.isStatic;
    _isInInstanceNotLateVariableDeclaration =
        !node.isStatic && !node.fields.isLate;
    if (!_isInStaticVariableDeclaration) {
      if (fields.isConst) {
        errorReporter.atToken(
          fields.keyword!,
          CompileTimeErrorCode.CONST_INSTANCE_FIELD,
        );
      }
    }
    var oldHasAccessToThis = _hasAccessToThis;
    try {
      _hasAccessToThis = !node.isStatic && node.fields.isLate;
      _checkForExtensionTypeDeclaresInstanceField(node);
      _checkForNotInitializedNonNullableStaticField(node);
      _checkForWrongTypeParameterVarianceInField(node);
      _checkForLateFinalFieldWithConstConstructor(node);
      _checkForNonFinalFieldInEnum(node);

      for (var field in fields.variables) {
        var element = field.declaredElement;
        element as FieldElementImpl;
        _checkAugmentations(
          augmentKeyword: node.augmentKeyword,
          element: element,
        );
        _reportMacroDiagnostics(element);
      }

      super.visitFieldDeclaration(node);
    } finally {
      _isInStaticVariableDeclaration = false;
      _isInInstanceNotLateVariableDeclaration = false;
      _hasAccessToThis = oldHasAccessToThis;
    }
  }

  @override
  void visitFieldFormalParameter(FieldFormalParameter node) {
    _checkForValidField(node);
    _checkForPrivateOptionalParameter(node);
    _checkForFieldInitializingFormalRedirectingConstructor(node);
    _checkForTypeAnnotationDeferredClass(node.type);
    ParameterElement element = node.declaredElement!;
    if (element is FieldFormalParameterElement) {
      var fieldElement = element.field;
      if (fieldElement != null) {
        _checkForAbstractOrExternalFieldConstructorInitializer(
            node.name, fieldElement);
      }
    }
    super.visitFieldFormalParameter(node);
  }

  @override
  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
    DeclaredIdentifier loopVariable = node.loopVariable;
    if (_checkForEachParts(node, loopVariable.declaredElement)) {
      if (loopVariable.isConst) {
        errorReporter.atToken(
          loopVariable.keyword!,
          CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE,
        );
      }
    }
    super.visitForEachPartsWithDeclaration(node);
  }

  @override
  void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
    SimpleIdentifier identifier = node.identifier;
    if (_checkForEachParts(node, identifier.staticElement)) {
      _checkForAssignmentToFinal(identifier);
    }
    super.visitForEachPartsWithIdentifier(node);
  }

  @override
  void visitFormalParameterList(FormalParameterList node) {
    _duplicateDefinitionVerifier.checkParameters(node);
    _checkUseOfCovariantInParameters(node);
    _checkUseOfDefaultValuesInParameters(node);
    super.visitFormalParameterList(node);
  }

  @override
  void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
    _duplicateDefinitionVerifier.checkForVariables(node.variables);
    super.visitForPartsWithDeclarations(node);
  }

  @override
  void visitFunctionDeclaration(covariant FunctionDeclarationImpl node) {
    var element = node.declaredElement!;
    if (element.enclosingElement3 is! CompilationUnitElement) {
      _hiddenElements!.declare(element);
    }

    _withEnclosingExecutable(element, () {
      TypeAnnotation? returnType = node.returnType;
      if (node.isSetter) {
        FunctionExpression functionExpression = node.functionExpression;
        _checkForWrongNumberOfParametersForSetter(
            node.name, functionExpression.parameters);
        _checkForNonVoidReturnTypeForSetter(returnType);
      }
      _checkForTypeAnnotationDeferredClass(returnType);
      _returnTypeVerifier.verifyReturnType(returnType);
      _checkForMainFunction1(node.name, node.declaredElement!);
      _checkForMainFunction2(node);
      _checkAugmentations(
        augmentKeyword: node.augmentKeyword,
        element: element,
      );
      _reportMacroDiagnostics(element);
      super.visitFunctionDeclaration(node);
    });
  }

  @override
  void visitFunctionExpression(FunctionExpression node) {
    _isInLateLocalVariable.add(false);

    if (node.parent is FunctionDeclaration) {
      super.visitFunctionExpression(node);
    } else {
      _withEnclosingExecutable(node.declaredElement!, () {
        super.visitFunctionExpression(node);
      });
    }

    _isInLateLocalVariable.removeLast();
  }

  @override
  void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
    var functionExpression = node.function;

    if (functionExpression is ExtensionOverride) {
      return super.visitFunctionExpressionInvocation(node);
    }

    _typeArgumentsVerifier.checkFunctionExpressionInvocation(node);
    _requiredParametersVerifier.visitFunctionExpressionInvocation(node);
    _constArgumentsVerifier.visitFunctionExpressionInvocation(node);
    _checkUseVerifier.checkFunctionExpressionInvocation(node);
    super.visitFunctionExpressionInvocation(node);
  }

  @override
  void visitFunctionReference(FunctionReference node) {
    _typeArgumentsVerifier.checkFunctionReference(node);
    super.visitFunctionReference(node);
  }

  @override
  void visitFunctionTypeAlias(FunctionTypeAlias node) {
    _checkForBuiltInIdentifierAsName(
        node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME);
    _checkForMainFunction1(node.name, node.declaredElement!);
    _checkForTypeAliasCannotReferenceItself(
        node.name, node.declaredElement as TypeAliasElementImpl);
    super.visitFunctionTypeAlias(node);
  }

  @override
  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
    bool old = _isInFunctionTypedFormalParameter;
    _isInFunctionTypedFormalParameter = true;
    try {
      _checkForTypeAnnotationDeferredClass(node.returnType);

      super.visitFunctionTypedFormalParameter(node);
    } finally {
      _isInFunctionTypedFormalParameter = old;
    }
  }

  @override
  void visitGenericTypeAlias(covariant GenericTypeAliasImpl node) {
    var element = node.declaredElement as TypeAliasElementImpl;

    _checkAugmentations(
      augmentKeyword: node.augmentKeyword,
      element: element,
    );

    _checkForBuiltInIdentifierAsName(
        node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME);
    _checkForMainFunction1(node.name, node.declaredElement!);
    _checkForTypeAliasCannotReferenceItself(
        node.name, node.declaredElement as TypeAliasElementImpl);
    _reportMacroDiagnostics(element);
    super.visitGenericTypeAlias(node);
  }

  @override
  void visitGuardedPattern(covariant GuardedPatternImpl node) {
    _withHiddenElementsGuardedPattern(node, () {
      node.pattern.accept(this);
    });
    node.whenClause?.accept(this);
  }

  @override
  void visitImportDirective(ImportDirective node) {
    var importElement = node.element;
    if (node.prefix != null) {
      _checkForBuiltInIdentifierAsName(node.prefix!.token,
          CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_PREFIX_NAME);
    }
    if (importElement != null) {
      _checkForImportInternalLibrary(node, importElement);
      if (importElement.prefix is DeferredImportElementPrefix) {
        _checkForDeferredImportOfExtensions(node, importElement);
      }
    }
    super.visitImportDirective(node);
  }

  @override
  void visitImportPrefixReference(ImportPrefixReference node) {
    _checkForReferenceBeforeDeclaration(
      nameToken: node.name,
      element: node.element,
    );
  }

  @override
  void visitIndexExpression(IndexExpression node) {
    if (node.isNullAware) {
      _checkForUnnecessaryNullAware(
        node.realTarget,
        node.question ?? node.period ?? node.leftBracket,
      );
    }

    super.visitIndexExpression(node);
  }

  @override
  void visitInstanceCreationExpression(InstanceCreationExpression node) {
    ConstructorName constructorName = node.constructorName;
    NamedType namedType = constructorName.type;
    DartType type = namedType.typeOrThrow;
    if (type is InterfaceType) {
      _checkForConstOrNewWithAbstractClass(node, namedType, type);
      _checkForInvalidGenerativeConstructorReference(constructorName);
      _checkForConstOrNewWithMixin(node, namedType, type);
      _requiredParametersVerifier.visitInstanceCreationExpression(node);
      _constArgumentsVerifier.visitInstanceCreationExpression(node);
      _checkUseVerifier.checkInstanceCreationExpression(node);
      if (node.isConst) {
        _checkForConstWithNonConst(node);
        _checkForConstWithUndefinedConstructor(
            node, constructorName, namedType);
        _checkForConstDeferredClass(node, constructorName, namedType);
      } else {
        _checkForNewWithUndefinedConstructor(node, constructorName, namedType);
      }
    }
    super.visitInstanceCreationExpression(node);
  }

  @override
  void visitIntegerLiteral(covariant IntegerLiteralImpl node) {
    _checkForOutOfRange(node);
    super.visitIntegerLiteral(node);
  }

  @override
  void visitInterpolationExpression(InterpolationExpression node) {
    checkForUseOfVoidResult(node.expression);
    super.visitInterpolationExpression(node);
  }

  @override
  void visitIsExpression(IsExpression node) {
    _checkForTypeAnnotationDeferredClass(node.type);
    checkForUseOfVoidResult(node.expression);
    super.visitIsExpression(node);
  }

  @override
  void visitLibraryDirective(covariant LibraryDirectiveImpl node) {
    if (node.element case var element?) {
      _reportMacroDiagnostics(element);
    }

    super.visitLibraryDirective(node);
  }

  @override
  void visitListLiteral(ListLiteral node) {
    _typeArgumentsVerifier.checkListLiteral(node);
    _checkForListElementTypeNotAssignable(node);

    super.visitListLiteral(node);
  }

  @override
  void visitMapLiteralEntry(MapLiteralEntry node) {
    if (node.keyQuestion != null) {
      _checkForUnnecessaryNullAware(node.key, node.keyQuestion!,
          nullAwareElementOrMapEntryKind:
              _NullAwareElementOrMapEntryKind.mapEntryKey);
    }
    if (node.valueQuestion != null) {
      _checkForUnnecessaryNullAware(node.value, node.valueQuestion!,
          nullAwareElementOrMapEntryKind:
              _NullAwareElementOrMapEntryKind.mapEntryValue);
    }
    super.visitMapLiteralEntry(node);
  }

  @override
  void visitMethodDeclaration(covariant MethodDeclarationImpl node) {
    var element = node.declaredElement!;
    _withEnclosingExecutable(element, () {
      var returnType = node.returnType;
      if (node.isSetter) {
        _checkForWrongNumberOfParametersForSetter(node.name, node.parameters);
        _checkForNonVoidReturnTypeForSetter(returnType);
      } else if (node.isOperator) {
        var hasWrongNumberOfParameters =
            _checkForWrongNumberOfParametersForOperator(node);
        if (!hasWrongNumberOfParameters) {
          // If the operator has too many parameters including one or more
          // optional parameters, only report one error.
          _checkForOptionalParameterInOperator(node);
        }
        _checkForNonVoidReturnTypeForOperator(node);
      }
      _checkForExtensionDeclaresMemberOfObject(node);
      _checkForTypeAnnotationDeferredClass(returnType);
      _returnTypeVerifier.verifyReturnType(returnType);
      _checkForWrongTypeParameterVarianceInMethod(node);
      _checkAugmentations(
        augmentKeyword: node.augmentKeyword,
        element: element,
      );
      _reportMacroDiagnostics(element);
      super.visitMethodDeclaration(node);
    });
  }

  @override
  void visitMethodInvocation(MethodInvocation node) {
    var target = node.realTarget;
    SimpleIdentifier methodName = node.methodName;
    if (target != null) {
      var typeReference = ElementResolver.getTypeReference(target);
      _checkForStaticAccessToInstanceMember(typeReference, methodName);
      _checkForInstanceAccessToStaticMember(
          typeReference, node.target, methodName);
      _checkForUnnecessaryNullAware(target, node.operator!);
    } else {
      _checkForUnqualifiedReferenceToNonLocalStaticMember(methodName);
    }
    _typeArgumentsVerifier.checkMethodInvocation(node);
    _requiredParametersVerifier.visitMethodInvocation(node);
    _constArgumentsVerifier.visitMethodInvocation(node);
    _checkUseVerifier.checkMethodInvocation(node);
    super.visitMethodInvocation(node);
  }

  @override
  void visitMixinDeclaration(covariant MixinDeclarationImpl node) {
    // TODO(scheglov): Verify for all mixin errors.
    try {
      var declaredFragment = node.declaredElement!;
      var declaredElement = declaredFragment.element;
      var firstFragment = declaredElement.firstFragment;

      _checkAugmentations(
        augmentKeyword: node.augmentKeyword,
        element: declaredFragment,
      );

      _checkMixinAugmentationModifiers(
        augmentKeyword: node.augmentKeyword,
        augmentationNode: node,
        augmentationElement: declaredFragment,
      );

      if (!identical(firstFragment, declaredFragment)) {
        _checkAugmentationTypeParameters(
          nameToken: node.name,
          typeParameterList: node.typeParameters,
          declarationTypeParameters: firstFragment.typeParameters,
        );
      }

      var augmented = declaredFragment.augmented;
      var declarationElement = augmented.firstFragment;
      _enclosingClass = declarationElement;

      List<ClassMember> members = node.members;
      _checkForBuiltInIdentifierAsName(
          node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME);
      _checkForConflictingClassTypeVariableErrorCodes();

      var onClause = node.onClause;
      var implementsClause = node.implementsClause;

      // Only do error checks only if there is a non-null clause.
      if (onClause != null || implementsClause != null) {
        _checkMixinInheritance(
            declarationElement, node, onClause, implementsClause);
      }

      _checkForConflictingClassMembers(declaredFragment);
      _checkForFinalNotInitializedInClass(declaredFragment, members);
      _checkForMainFunction1(node.name, declarationElement);
      _checkForWrongTypeParameterVarianceInSuperinterfaces();
      _reportMacroDiagnostics(declaredFragment);
      //      _checkForBadFunctionUse(node);
      super.visitMixinDeclaration(node);
    } finally {
      _enclosingClass = null;
    }
  }

  @override
  void visitNamedType(NamedType node) {
    _checkForAmbiguousImport(
      name: node.name2,
      element: node.element,
    );
    _checkForTypeParameterReferencedByStatic(
      name: node.name2,
      element: node.element,
    );
    _typeArgumentsVerifier.checkNamedType(node);
    super.visitNamedType(node);
  }

  @override
  void visitNativeClause(NativeClause node) {
    // TODO(brianwilkerson): Figure out the right rule for when 'native' is
    // allowed.
    if (!_isInSystemLibrary) {
      errorReporter.atNode(
        node,
        ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE,
      );
    }
    super.visitNativeClause(node);
  }

  @override
  void visitNativeFunctionBody(NativeFunctionBody node) {
    _checkForNativeFunctionBodyInNonSdkCode(node);
    super.visitNativeFunctionBody(node);
  }

  @override
  void visitNullAwareElement(NullAwareElement node) {
    _checkForUnnecessaryNullAware(node.value, node.question,
        nullAwareElementOrMapEntryKind:
            _NullAwareElementOrMapEntryKind.element);
    super.visitNullAwareElement(node);
  }

  @override
  void visitPatternVariableDeclarationStatement(
    covariant PatternVariableDeclarationStatementImpl node,
  ) {
    super.visitPatternVariableDeclarationStatement(node);
    for (var variable in node.declaration.elements) {
      _hiddenElements?.declare(variable);
    }
  }

  @override
  void visitPostfixExpression(PostfixExpression node) {
    var operand = node.operand;
    if (node.operator.type == TokenType.BANG) {
      checkForUseOfVoidResult(node);
      _checkForUnnecessaryNullAware(operand, node.operator);
    } else {
      _checkForAssignmentToFinal(operand);
      _checkForIntNotAssignable(operand);
    }
    super.visitPostfixExpression(node);
  }

  @override
  void visitPrefixedIdentifier(PrefixedIdentifier node) {
    if (node.parent is! Annotation) {
      var typeReference = ElementResolver.getTypeReference(node.prefix);
      SimpleIdentifier name = node.identifier;
      _checkForStaticAccessToInstanceMember(typeReference, name);
      _checkForInstanceAccessToStaticMember(typeReference, node.prefix, name);
    }
    super.visitPrefixedIdentifier(node);
  }

  @override
  void visitPrefixExpression(PrefixExpression node) {
    TokenType operatorType = node.operator.type;
    Expression operand = node.operand;
    if (operatorType != TokenType.BANG) {
      if (operatorType.isIncrementOperator) {
        _checkForAssignmentToFinal(operand);
      }
      checkForUseOfVoidResult(operand);
      _checkForIntNotAssignable(operand);
    }
    super.visitPrefixExpression(node);
  }

  @override
  void visitPropertyAccess(PropertyAccess node) {
    var target = node.realTarget;
    var typeReference = ElementResolver.getTypeReference(target);
    SimpleIdentifier propertyName = node.propertyName;
    _checkForStaticAccessToInstanceMember(typeReference, propertyName);
    _checkForInstanceAccessToStaticMember(
        typeReference, node.target, propertyName);
    _checkForUnnecessaryNullAware(target, node.operator);
    _checkUseVerifier.checkPropertyAccess(node);
    super.visitPropertyAccess(node);
  }

  @override
  void visitRedirectingConstructorInvocation(
      RedirectingConstructorInvocation node) {
    _requiredParametersVerifier.visitRedirectingConstructorInvocation(node);
    _constArgumentsVerifier.visitRedirectingConstructorInvocation(node);
    _isInConstructorInitializer = true;
    try {
      super.visitRedirectingConstructorInvocation(node);
    } finally {
      _isInConstructorInitializer = false;
    }
  }

  @override
  void visitRethrowExpression(RethrowExpression node) {
    _checkForRethrowOutsideCatch(node);
    super.visitRethrowExpression(node);
  }

  @override
  void visitReturnStatement(ReturnStatement node) {
    if (node.expression == null) {
      _enclosingExecutable._returnsWithout.add(node);
    } else {
      _enclosingExecutable._returnsWith.add(node);
    }
    _returnTypeVerifier.verifyReturnStatement(node);
    super.visitReturnStatement(node);
  }

  @override
  void visitSetOrMapLiteral(SetOrMapLiteral node) {
    if (node.isMap) {
      _typeArgumentsVerifier.checkMapLiteral(node);
      _checkForMapTypeNotAssignable(node);
      _checkForNonConstMapAsExpressionStatement3(node);
    } else if (node.isSet) {
      _typeArgumentsVerifier.checkSetLiteral(node);
      _checkForSetElementTypeNotAssignable3(node);
    }
    super.visitSetOrMapLiteral(node);
  }

  @override
  void visitSimpleFormalParameter(SimpleFormalParameter node) {
    _checkForPrivateOptionalParameter(node);
    _checkForTypeAnnotationDeferredClass(node.type);
    super.visitSimpleFormalParameter(node);
  }

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    _checkForAmbiguousImport(
      name: node.token,
      element: node.writeOrReadElement,
    );
    _checkForReferenceBeforeDeclaration(
      nameToken: node.token,
      element: node.staticElement,
    );
    _checkForInvalidInstanceMemberAccess(node);
    _checkForTypeParameterReferencedByStatic(
      name: node.token,
      element: node.staticElement,
    );
    if (!_isUnqualifiedReferenceToNonLocalStaticMemberAllowed(node)) {
      _checkForUnqualifiedReferenceToNonLocalStaticMember(node);
    }
    _checkUseVerifier.checkSimpleIdentifier(node);
    super.visitSimpleIdentifier(node);
  }

  @override
  void visitSpreadElement(SpreadElement node) {
    if (node.isNullAware) {
      _checkForUnnecessaryNullAware(node.expression, node.spreadOperator);
    }
    super.visitSpreadElement(node);
  }

  @override
  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
    _requiredParametersVerifier.visitSuperConstructorInvocation(
      node,
      enclosingConstructor: _enclosingExecutable.element.ifTypeOrNull(),
    );
    _constArgumentsVerifier.visitSuperConstructorInvocation(node);
    _isInConstructorInitializer = true;
    try {
      _checkForExtensionTypeConstructorWithSuperInvocation(node);
      super.visitSuperConstructorInvocation(node);
    } finally {
      _isInConstructorInitializer = false;
    }
  }

  @override
  void visitSuperFormalParameter(SuperFormalParameter node) {
    super.visitSuperFormalParameter(node);

    if (_enclosingClass is ExtensionTypeElement) {
      errorReporter.atToken(
        node.superKeyword,
        CompileTimeErrorCode
            .EXTENSION_TYPE_CONSTRUCTOR_WITH_SUPER_FORMAL_PARAMETER,
      );
      return;
    }

    var constructor = node.parentFormalParameterList.parent;
    if (!(constructor is ConstructorDeclaration &&
        constructor.isNonRedirectingGenerative)) {
      errorReporter.atToken(
        node.superKeyword,
        CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION,
      );
      return;
    }

    var element = node.declaredElement as SuperFormalParameterElementImpl;
    var superParameter = element.superConstructorParameter;

    if (superParameter == null) {
      errorReporter.atToken(
        node.name,
        node.isNamed
            ? CompileTimeErrorCode
                .SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED
            : CompileTimeErrorCode
                .SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL,
      );
      return;
    }

    if (!_currentLibrary.typeSystem
        .isSubtypeOf(element.type, superParameter.type)) {
      errorReporter.atToken(
        node.name,
        CompileTimeErrorCode
            .SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED,
        arguments: [element.type, superParameter.type],
      );
    }
  }

  @override
  void visitSwitchCase(SwitchCase node) {
    _withHiddenElements(node.statements, () {
      _duplicateDefinitionVerifier.checkStatements(node.statements);
      super.visitSwitchCase(node);
    });
  }

  @override
  void visitSwitchDefault(SwitchDefault node) {
    _withHiddenElements(node.statements, () {
      _duplicateDefinitionVerifier.checkStatements(node.statements);
      super.visitSwitchDefault(node);
    });
  }

  @override
  void visitSwitchExpression(SwitchExpression node) {
    checkForUseOfVoidResult(node.expression);
    super.visitSwitchExpression(node);
  }

  @override
  void visitSwitchPatternCase(SwitchPatternCase node) {
    _withHiddenElements(node.statements, () {
      _duplicateDefinitionVerifier.checkStatements(node.statements);
      super.visitSwitchPatternCase(node);
    });
  }

  @override
  void visitSwitchStatement(SwitchStatement node) {
    checkForUseOfVoidResult(node.expression);
    _checkForMissingEnumConstantInSwitch(node);
    super.visitSwitchStatement(node);
  }

  @override
  void visitThisExpression(ThisExpression node) {
    _checkForInvalidReferenceToThis(node);
    super.visitThisExpression(node);
  }

  @override
  void visitThrowExpression(ThrowExpression node) {
    _checkForConstEvalThrowsException(node);
    checkForUseOfVoidResult(node.expression);
    _checkForThrowOfInvalidType(node);
    super.visitThrowExpression(node);
  }

  @override
  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    _checkForFinalNotInitialized(node.variables);
    _checkForNotInitializedNonNullableVariable(node.variables, true);

    for (var variable in node.variables.variables) {
      var element = variable.declaredElement;
      element as TopLevelVariableElementImpl;
      _checkForMainFunction1(variable.name, element);
      _checkAugmentations(
        augmentKeyword: node.augmentKeyword,
        element: element,
      );
      _reportMacroDiagnostics(element);
    }

    super.visitTopLevelVariableDeclaration(node);
  }

  @override
  void visitTypeArgumentList(TypeArgumentList node) {
    NodeList<TypeAnnotation> list = node.arguments;
    for (TypeAnnotation type in list) {
      _checkForTypeAnnotationDeferredClass(type);
    }
    super.visitTypeArgumentList(node);
  }

  @override
  void visitTypeParameter(TypeParameter node) {
    _checkForBuiltInIdentifierAsName(node.name,
        CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME);
    _checkForTypeAnnotationDeferredClass(node.bound);
    _checkForGenericFunctionType(node.bound);
    node.bound?.accept(_uninstantiatedBoundChecker);
    super.visitTypeParameter(node);
  }

  @override
  void visitTypeParameterList(TypeParameterList node) {
    _duplicateDefinitionVerifier.checkTypeParameters(node);
    _checkForTypeParameterBoundRecursion(node.typeParameters);
    super.visitTypeParameterList(node);
  }

  @override
  void visitVariableDeclaration(VariableDeclaration node) {
    var nameToken = node.name;
    var initializerNode = node.initializer;
    // do checks
    _checkForAbstractOrExternalVariableInitializer(node);
    // visit initializer
    String name = nameToken.lexeme;
    _namesForReferenceToDeclaredVariableInInitializer.add(name);
    try {
      if (initializerNode != null) {
        initializerNode.accept(this);
      }
    } finally {
      _namesForReferenceToDeclaredVariableInInitializer.remove(name);
    }
    // declare the variable
    AstNode grandparent = node.parent!.parent!;
    if (grandparent is! TopLevelVariableDeclaration &&
        grandparent is! FieldDeclaration) {
      VariableElement element = node.declaredElement!;
      // There is no hidden elements if we are outside of a function body,
      // which will happen for variables declared in control flow elements.
      _hiddenElements?.declare(element);
    }
  }

  @override
  void visitVariableDeclarationList(VariableDeclarationList node) {
    _checkForTypeAnnotationDeferredClass(node.type);
    super.visitVariableDeclarationList(node);
  }

  @override
  void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
    _isInLateLocalVariable.add(node.variables.isLate);

    _checkForFinalNotInitialized(node.variables);
    super.visitVariableDeclarationStatement(node);

    _isInLateLocalVariable.removeLast();
  }

  void _checkAugmentations<T extends ElementImpl>({
    required Token? augmentKeyword,
    required T element,
  }) {
    if (augmentKeyword == null) {
      return;
    }

    if (element is! AugmentableElement<T>) {
      return;
    }

    // OK
    if (element.augmentationTarget != null) {
      return;
    }

    // Not the same kind.
    if (element.augmentationTargetAny case var target?) {
      errorReporter.atToken(
        augmentKeyword,
        CompileTimeErrorCode.AUGMENTATION_OF_DIFFERENT_DECLARATION_KIND,
        arguments: [
          target.kind.displayName,
          element.kind.displayName,
        ],
      );
      return;
    }

    errorReporter.atToken(
      augmentKeyword,
      CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION,
    );
  }

  void _checkAugmentationTypeParameters({
    required Token nameToken,
    required TypeParameterList? typeParameterList,
    required List<TypeParameterElement> declarationTypeParameters,
  }) {
    if (declarationTypeParameters.isEmpty) {
      if (typeParameterList != null) {
        errorReporter.atToken(
          typeParameterList.leftBracket,
          CompileTimeErrorCode.AUGMENTATION_TYPE_PARAMETER_COUNT,
        );
      }
    } else {
      if (typeParameterList == null) {
        errorReporter.atToken(
          nameToken,
          CompileTimeErrorCode.AUGMENTATION_TYPE_PARAMETER_COUNT,
        );
      } else {
        var declarationCount = declarationTypeParameters.length;
        var typeParameters = typeParameterList.typeParameters;
        switch (typeParameters.length.compareTo(declarationCount)) {
          case < 0:
            errorReporter.atToken(
              typeParameterList.rightBracket,
              CompileTimeErrorCode.AUGMENTATION_TYPE_PARAMETER_COUNT,
            );
          case > 0:
            errorReporter.atToken(
              typeParameters[declarationCount].name,
              CompileTimeErrorCode.AUGMENTATION_TYPE_PARAMETER_COUNT,
            );
          default:
            for (var index = 0; index < declarationCount; index++) {
              var ofDeclaration = declarationTypeParameters[index];
              var ofAugmentation = typeParameters[index];

              if (ofAugmentation.name.lexeme != ofDeclaration.name) {
                errorReporter.atToken(
                  ofAugmentation.name,
                  CompileTimeErrorCode.AUGMENTATION_TYPE_PARAMETER_NAME,
                );
                continue;
              }

              var declarationBound = ofDeclaration.bound;
              var augmentationBound = ofAugmentation.bound;
              switch ((declarationBound, augmentationBound)) {
                case (null, var augmentationBound?):
                  errorReporter.atNode(
                    augmentationBound,
                    CompileTimeErrorCode.AUGMENTATION_TYPE_PARAMETER_BOUND,
                  );
                case (_?, null):
                  errorReporter.atToken(
                    ofAugmentation.name,
                    CompileTimeErrorCode.AUGMENTATION_TYPE_PARAMETER_BOUND,
                  );
                case (var declarationBound?, var augmentationBound?):
                  var augmentationType = augmentationBound.typeOrThrow;
                  if (!typeSystem.isEqualTo(
                    declarationBound,
                    augmentationType,
                  )) {
                    errorReporter.atNode(
                      augmentationBound,
                      CompileTimeErrorCode.AUGMENTATION_TYPE_PARAMETER_BOUND,
                    );
                  }
              }
            }
        }
      }
    }
  }

  void _checkClassAugmentationModifiers({
    required Token? augmentKeyword,
    required ClassDeclarationImpl augmentationNode,
    required ClassElementImpl augmentationElement,
  }) {
    if (augmentKeyword == null) {
      return;
    }

    var target = augmentationElement.augmentationTarget;
    if (target == null) {
      return;
    }

    var declaration = target.augmented.firstFragment;

    void singleModifier({
      required String modifierName,
      required bool declarationFlag,
      required Token? augmentationModifier,
    }) {
      if (declarationFlag) {
        if (augmentationModifier == null) {
          errorReporter.atToken(
            augmentKeyword,
            CompileTimeErrorCode.AUGMENTATION_MODIFIER_MISSING,
            arguments: [modifierName],
          );
        }
      } else {
        if (augmentationModifier != null) {
          errorReporter.atToken(
            augmentationModifier,
            CompileTimeErrorCode.AUGMENTATION_MODIFIER_EXTRA,
            arguments: [modifierName],
          );
        }
      }
    }

    // Sealed classes are also abstract, report just `sealed` mismatch.
    if (!declaration.isSealed) {
      singleModifier(
        modifierName: 'abstract',
        declarationFlag: declaration.isAbstract,
        augmentationModifier: augmentationNode.abstractKeyword,
      );
    }

    singleModifier(
      modifierName: 'base',
      declarationFlag: declaration.isBase,
      augmentationModifier: augmentationNode.baseKeyword,
    );

    singleModifier(
      modifierName: 'final',
      declarationFlag: declaration.isFinal,
      augmentationModifier: augmentationNode.finalKeyword,
    );

    singleModifier(
      modifierName: 'interface',
      declarationFlag: declaration.isInterface,
      augmentationModifier: augmentationNode.interfaceKeyword,
    );

    singleModifier(
      modifierName: 'mixin',
      declarationFlag: declaration.isMixinClass,
      augmentationModifier: augmentationNode.mixinKeyword,
    );

    singleModifier(
      modifierName: 'sealed',
      declarationFlag: declaration.isSealed,
      augmentationModifier: augmentationNode.sealedKeyword,
    );
  }

  void _checkClassAugmentationTargetAlreadyHasExtendsClause({
    required ClassDeclarationImpl node,
    required ClassElementImpl? augmentationTarget,
  }) {
    var extendsClause = node.extendsClause;
    if (extendsClause == null) {
      return;
    }

    while (augmentationTarget != null) {
      if (augmentationTarget.hasExtendsClause) {
        errorReporter.atToken(
          extendsClause.extendsKeyword,
          CompileTimeErrorCode.AUGMENTATION_EXTENDS_CLAUSE_ALREADY_PRESENT,
          contextMessages: [
            DiagnosticMessageImpl(
              filePath: augmentationTarget.source.fullName,
              offset: augmentationTarget.nameOffset,
              length: augmentationTarget.nameLength,
              message: 'The extends clause is included here.',
              url: null,
            ),
          ],
        );
        return;
      }
      augmentationTarget = augmentationTarget.augmentationTarget;
    }
  }

  /// Checks the class for problems with the superclass, mixins, or implemented
  /// interfaces.
  ///
  /// Returns `false` if a severe hierarchy error was found, so that further
  /// checking is not useful.
  bool _checkClassInheritance(
      InterfaceElementImpl declarationElement,
      NamedCompilationUnitMember node,
      NamedType? superclass,
      WithClause? withClause,
      ImplementsClause? implementsClause) {
    // Only check for all of the inheritance logic around clauses if there
    // isn't an error code such as "Cannot extend double" already on the
    // class.
    if (!_checkForExtendsDisallowedClass(superclass) &&
        !_checkForImplementsClauseErrorCodes(implementsClause) &&
        !_checkForAllMixinErrorCodes(withClause) &&
        !_checkForNoGenerativeConstructorsInSuperclass(superclass)) {
      _checkForExtendsDeferredClass(superclass);
      _checkForRepeatedType(
        libraryContext.setOfImplements(declarationElement),
        implementsClause?.interfaces,
        CompileTimeErrorCode.IMPLEMENTS_REPEATED,
      );
      _checkImplementsSuperClass(implementsClause);
      _checkMixinsSuperClass(withClause);
      _checkForMixinWithConflictingPrivateMember(withClause, superclass);
      _checkForConflictingGenerics(node);
      _checkForBaseClassOrMixinImplementedOutsideOfLibrary(implementsClause);
      _checkForInterfaceClassOrMixinSuperclassOutsideOfLibrary(
          superclass, withClause);
      _checkForFinalSupertypeOutsideOfLibrary(
          superclass, withClause, implementsClause, null);
      _checkForClassUsedAsMixin(withClause);
      _checkForSealedSupertypeOutsideOfLibrary(
          superclass, withClause, implementsClause, null);
      return true;
    }
    return false;
  }

  /// Given a list of [directives] that have the same prefix, generate an error
  /// if there is more than one import and any of those imports is deferred.
  ///
  /// See [CompileTimeErrorCode.SHARED_DEFERRED_PREFIX].
  void _checkDeferredPrefixCollision(List<ImportDirective> directives) {
    int count = directives.length;
    if (count > 1) {
      for (int i = 0; i < count; i++) {
        var deferredToken = directives[i].deferredKeyword;
        if (deferredToken != null) {
          errorReporter.atToken(
            deferredToken,
            CompileTimeErrorCode.SHARED_DEFERRED_PREFIX,
          );
        }
      }
    }
  }

  void _checkForAbstractOrExternalFieldConstructorInitializer(
      Token identifier, FieldElement fieldElement) {
    if (fieldElement.isAbstract) {
      errorReporter.atToken(
        identifier,
        CompileTimeErrorCode.ABSTRACT_FIELD_CONSTRUCTOR_INITIALIZER,
      );
    }
    if (fieldElement.isExternal) {
      errorReporter.atToken(
        identifier,
        CompileTimeErrorCode.EXTERNAL_FIELD_CONSTRUCTOR_INITIALIZER,
      );
    }
  }

  void _checkForAbstractOrExternalVariableInitializer(
      VariableDeclaration node) {
    var declaredElement = node.declaredElement;
    if (node.initializer != null) {
      if (declaredElement is FieldElement) {
        if (declaredElement.isAbstract) {
          errorReporter.atToken(
            node.name,
            CompileTimeErrorCode.ABSTRACT_FIELD_INITIALIZER,
          );
        }
        if (declaredElement.isExternal) {
          errorReporter.atToken(
            node.name,
            CompileTimeErrorCode.EXTERNAL_FIELD_INITIALIZER,
          );
        }
      } else if (declaredElement is TopLevelVariableElement) {
        if (declaredElement.isExternal) {
          errorReporter.atToken(
            node.name,
            CompileTimeErrorCode.EXTERNAL_VARIABLE_INITIALIZER,
          );
        }
      }
    }
  }

  /// Verify that all classes of the given [withClause] are valid.
  ///
  /// See [CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR],
  /// [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT].
  bool _checkForAllMixinErrorCodes(WithClause? withClause) {
    if (withClause == null) {
      return false;
    }
    bool problemReported = false;
    int mixinTypeIndex = -1;
    for (int mixinNameIndex = 0;
        mixinNameIndex < withClause.mixinTypes.length;
        mixinNameIndex++) {
      NamedType mixinName = withClause.mixinTypes[mixinNameIndex];
      DartType mixinType = mixinName.typeOrThrow;
      if (mixinType is InterfaceType) {
        mixinTypeIndex++;
        if (_checkForExtendsOrImplementsDisallowedClass(
            mixinName, CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS)) {
          problemReported = true;
        } else {
          var mixinElement = mixinType.element;
          if (_checkForExtendsOrImplementsDeferredClass(
              mixinName, CompileTimeErrorCode.MIXIN_DEFERRED_CLASS)) {
            problemReported = true;
          }
          if (mixinType.element is ExtensionTypeElement) {
            // Already reported.
          } else if (mixinElement is MixinElement) {
            if (_checkForMixinSuperclassConstraints(
                mixinNameIndex, mixinName)) {
              problemReported = true;
            } else if (_checkForMixinSuperInvokedMembers(
                mixinTypeIndex, mixinName, mixinElement, mixinType)) {
              problemReported = true;
            }
          } else {
            bool isMixinClass =
                mixinElement is ClassElementImpl && mixinElement.isMixinClass;
            if (!isMixinClass &&
                _checkForMixinClassDeclaresConstructor(
                    mixinName, mixinElement)) {
              problemReported = true;
            }
            if (_checkForMixinInheritsNotFromObject(mixinName, mixinElement)) {
              problemReported = true;
            }
          }
        }
      }
    }
    return problemReported;
  }

  /// Check for errors related to the redirected constructors.
  void _checkForAllRedirectConstructorErrorCodes(
      ConstructorDeclaration declaration) {
    // Prepare redirected constructor node
    var redirectedConstructor = declaration.redirectedConstructor;
    if (redirectedConstructor == null) {
      return;
    }

    // Prepare redirected constructor type
    var redirectedElement = redirectedConstructor.staticElement;
    if (redirectedElement == null) {
      // If the element is null, we check for the
      // REDIRECT_TO_MISSING_CONSTRUCTOR case
      NamedType constructorNamedType = redirectedConstructor.type;
      DartType redirectedType = constructorNamedType.typeOrThrow;
      if (!(redirectedType is DynamicType || redirectedType is InvalidType)) {
        // Prepare the constructor name
        String constructorStrName = constructorNamedType.qualifiedName;
        if (redirectedConstructor.name != null) {
          constructorStrName += ".${redirectedConstructor.name!.name}";
        }
        errorReporter.atNode(
          redirectedConstructor,
          CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR,
          arguments: [constructorStrName, redirectedType],
        );
      }
      return;
    }
    FunctionType redirectedType = redirectedElement.type;
    DartType redirectedReturnType = redirectedType.returnType;

    // Report specific problem when return type is incompatible
    FunctionType constructorType = declaration.declaredElement!.type;
    DartType constructorReturnType = constructorType.returnType;
    if (!typeSystem.isAssignableTo(redirectedReturnType, constructorReturnType,
        strictCasts: strictCasts)) {
      errorReporter.atNode(
        redirectedConstructor,
        CompileTimeErrorCode.REDIRECT_TO_INVALID_RETURN_TYPE,
        arguments: [redirectedReturnType, constructorReturnType],
      );
      return;
    } else if (!typeSystem.isSubtypeOf(redirectedType, constructorType)) {
      // Check parameters.
      errorReporter.atNode(
        redirectedConstructor,
        CompileTimeErrorCode.REDIRECT_TO_INVALID_FUNCTION_TYPE,
        arguments: [redirectedType, constructorType],
      );
    }
  }

  /// Verify that the export namespace of the given export [directive] does not
  /// export any name already exported by another export directive. The
  /// [exportElement] is the [LibraryExportElement] retrieved from the node. If the
  /// element in the node was `null`, then this method is not called. The
  /// [exportedLibrary] is the library element containing the exported element.
  ///
  /// See [CompileTimeErrorCode.AMBIGUOUS_EXPORT].
  void _checkForAmbiguousExport(ExportDirective directive,
      LibraryExportElement exportElement, LibraryElement? exportedLibrary) {
    if (exportedLibrary == null) {
      return;
    }
    // check exported names
    Namespace namespace =
        NamespaceBuilder().createExportNamespaceForDirective(exportElement);
    Map<String, Element> definedNames = namespace.definedNames;
    for (String name in definedNames.keys) {
      var element = definedNames[name]!;
      var prevElement = libraryContext._exportedElements[name];
      if (prevElement != null && prevElement != element) {
        errorReporter.atNode(
          directive.uri,
          CompileTimeErrorCode.AMBIGUOUS_EXPORT,
          arguments: [
            name,
            prevElement.library!.definingCompilationUnit.source.uri,
            element.library!.definingCompilationUnit.source.uri
          ],
        );
        return;
      } else {
        libraryContext._exportedElements[name] = element;
      }
    }
  }

  /// Check the given node to see whether it was ambiguous because the name was
  /// imported from two or more imports.
  void _checkForAmbiguousImport({
    required Token name,
    required Element? element,
  }) {
    if (element is MultiplyDefinedElementImpl) {
      var conflictingMembers = element.conflictingElements;
      var libraryNames =
          conflictingMembers.map((e) => _getLibraryName(e)).toList();
      libraryNames.sort();
      errorReporter.atToken(
        name,
        CompileTimeErrorCode.AMBIGUOUS_IMPORT,
        arguments: [name.lexeme, libraryNames.quotedAndCommaSeparatedWithAnd],
      );
    }
  }

  /// Verify that the given [expression] is not final.
  ///
  /// See [CompileTimeErrorCode.ASSIGNMENT_TO_CONST],
  /// [CompileTimeErrorCode.ASSIGNMENT_TO_FINAL], and
  /// [CompileTimeErrorCode.ASSIGNMENT_TO_METHOD].
  void _checkForAssignmentToFinal(Expression expression) {
    // TODO(scheglov): Check SimpleIdentifier(s) as all other nodes.
    if (expression is! SimpleIdentifier) return;

    // Already handled in the assignment resolver.
    if (expression.parent is AssignmentExpression) {
      return;
    }

    // prepare element
    var highlightedNode = expression;
    var element = expression.staticElement;
    if (expression is PrefixedIdentifier) {
      var prefixedIdentifier = expression as PrefixedIdentifier;
      highlightedNode = prefixedIdentifier.identifier;
    }
    // check if element is assignable
    if (element is VariableElement) {
      if (element.isConst) {
        errorReporter.atNode(
          expression,
          CompileTimeErrorCode.ASSIGNMENT_TO_CONST,
        );
      }
    } else if (element is PropertyAccessorElement && element.isGetter) {
      var variable = element.variable2;
      if (variable == null) {
        return;
      }
      if (variable.isConst) {
        errorReporter.atNode(
          expression,
          CompileTimeErrorCode.ASSIGNMENT_TO_CONST,
        );
      } else if (variable is FieldElement && variable.isSynthetic) {
        errorReporter.atNode(
          highlightedNode,
          CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_NO_SETTER,
          arguments: [variable.name, variable.enclosingElement3.displayName],
        );
      } else {
        errorReporter.atNode(
          highlightedNode,
          CompileTimeErrorCode.ASSIGNMENT_TO_FINAL,
          arguments: [variable.name],
        );
      }
    } else if (element is FunctionElement) {
      errorReporter.atNode(
        expression,
        CompileTimeErrorCode.ASSIGNMENT_TO_FUNCTION,
      );
    } else if (element is MethodElement) {
      errorReporter.atNode(
        expression,
        CompileTimeErrorCode.ASSIGNMENT_TO_METHOD,
      );
    } else if (element is InterfaceElement ||
        element is DynamicElementImpl ||
        element is TypeParameterElement) {
      errorReporter.atNode(
        expression,
        CompileTimeErrorCode.ASSIGNMENT_TO_TYPE,
      );
    }
  }

  void _checkForAwaitInLateLocalVariableInitializer(AwaitExpression node) {
    if (_isInLateLocalVariable.last) {
      errorReporter.atToken(
        node.awaitKeyword,
        CompileTimeErrorCode.AWAIT_IN_LATE_LOCAL_VARIABLE_INITIALIZER,
      );
    }
  }

  void _checkForAwaitOfIncompatibleType(AwaitExpression node) {
    var expression = node.expression;
    var expressionType = expression.typeOrThrow;
    if (typeSystem.isIncompatibleWithAwait(expressionType)) {
      errorReporter.atToken(
        node.awaitKeyword,
        CompileTimeErrorCode.AWAIT_OF_INCOMPATIBLE_TYPE,
      );
    }
  }

  /// Verifies that the nodes don't reference `Function` from `dart:core`.
  void _checkForBadFunctionUse({
    required NamedType? superclass,
    required ImplementsClause? implementsClause,
    required WithClause? withClause,
  }) {
    // With the `class_modifiers` feature `Function` is final.
    if (_featureSet!.isEnabled(Feature.class_modifiers)) {
      return;
    }

    if (superclass != null) {
      var type = superclass.type;
      if (type != null && type.isDartCoreFunction) {
        errorReporter.atNode(
          superclass,
          WarningCode.DEPRECATED_EXTENDS_FUNCTION,
        );
      }
    }

    if (implementsClause != null) {
      for (var interface in implementsClause.interfaces) {
        var type = interface.type;
        if (type != null && type.isDartCoreFunction) {
          errorReporter.atNode(
            interface,
            WarningCode.DEPRECATED_IMPLEMENTS_FUNCTION,
          );
          break;
        }
      }
    }

    if (withClause != null) {
      for (NamedType mixin in withClause.mixinTypes) {
        var type = mixin.type;
        if (type != null && type.isDartCoreFunction) {
          errorReporter.atNode(
            mixin,
            WarningCode.DEPRECATED_MIXIN_FUNCTION,
          );
        }
      }
    }
  }

  /// Verify that if a class is implementing a base class or mixin, it must be
  /// within the same library as that class or mixin.
  ///
  /// See [CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY],
  /// [CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY].
  void _checkForBaseClassOrMixinImplementedOutsideOfLibrary(
      ImplementsClause? implementsClause) {
    if (implementsClause == null) return;
    for (NamedType interface in implementsClause.interfaces) {
      var interfaceType = interface.type;
      if (interfaceType is InterfaceType) {
        var implementedInterfaces = [
          interfaceType,
          ...interfaceType.element.allSupertypes,
        ].map((e) => e.element).toList();
        for (var interfaceElement in implementedInterfaces) {
          if (interfaceElement is ClassOrMixinElementImpl &&
              interfaceElement.isBase &&
              interfaceElement.library != _currentLibrary &&
              !_mayIgnoreClassModifiers(interfaceElement.library)) {
            // Should this be combined with _checkForImplementsClauseErrorCodes
            // to avoid double errors if implementing `int`.
            if (interfaceElement is ClassElementImpl &&
                !interfaceElement.isSealed) {
              errorReporter.atNode(
                interface,
                CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY,
                arguments: [interfaceElement.name],
              );
            } else if (interfaceElement is MixinElement) {
              errorReporter.atNode(
                interface,
                CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY,
                arguments: [interfaceElement.name],
              );
            }
            break;
          }
        }
      }
    }
  }

  /// Verify that the given [token] is not a keyword, and generates the
  /// given [errorCode] on the identifier if it is a keyword.
  ///
  /// See [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_EXTENSION_NAME],
  /// [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME],
  /// [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME], and
  /// [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME].
  void _checkForBuiltInIdentifierAsName(Token token, ErrorCode errorCode) {
    if (token.type.isKeyword && token.keyword?.isPseudo != true) {
      errorReporter.atToken(
        token,
        errorCode,
        arguments: [token.lexeme],
      );
    }
  }

  /// Verify that if a class is being mixed in and class modifiers are enabled
  /// in that class' library, then it must be a mixin class.
  ///
  /// See [CompileTimeErrorCode.CLASS_USED_AS_MIXIN].
  void _checkForClassUsedAsMixin(WithClause? withClause) {
    if (withClause != null) {
      for (NamedType withMixin in withClause.mixinTypes) {
        var withType = withMixin.type;
        if (withType is InterfaceType) {
          var withElement = withType.element;
          if (withElement is ClassElementImpl &&
              !withElement.isMixinClass &&
              withElement.library.featureSet
                  .isEnabled(Feature.class_modifiers) &&
              !_mayIgnoreClassModifiers(withElement.library)) {
            errorReporter.atNode(
              withMixin,
              CompileTimeErrorCode.CLASS_USED_AS_MIXIN,
              arguments: [withElement.name],
            );
          }
        }
      }
    }
  }

  /// Verify that the [_enclosingClass] does not have a method and getter pair
  /// with the same name, via inheritance.
  ///
  /// See [CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE],
  /// [CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD], and
  /// [CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD].
  void _checkForConflictingClassMembers(InterfaceElement fragment) {
    var enclosingClass = _enclosingClass;
    if (enclosingClass == null) {
      return;
    }

    Uri libraryUri = _currentLibrary.source.uri;
    var conflictingDeclaredNames = <String>{};

    // method declared in the enclosing class vs. inherited getter/setter
    for (MethodElement method in fragment.methods) {
      if (method.source != _currentUnit.source) {
        continue;
      }

      String name = method.name;

      // find inherited property accessors
      var getter = _inheritanceManager.getInherited2(
          enclosingClass, Name(libraryUri, name));
      var setter = _inheritanceManager.getInherited2(
          enclosingClass, Name(libraryUri, '$name='));

      if (method.isStatic) {
        void reportStaticConflict(ExecutableElement inherited) {
          errorReporter.atElement(
            method,
            CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
            arguments: [
              enclosingClass.displayName,
              name,
              inherited.enclosingElement3.displayName,
            ],
          );
        }

        if (getter != null) {
          reportStaticConflict(getter);
          continue;
        }

        if (setter != null) {
          reportStaticConflict(setter);
          continue;
        }
      }

      // Extension type methods preclude accessors.
      if (enclosingClass is ExtensionTypeElement) {
        continue;
      }

      void reportFieldConflict(PropertyAccessorElement inherited) {
        errorReporter.atElement(
          method,
          CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD,
          arguments: [
            enclosingClass.displayName,
            name,
            inherited.enclosingElement3.displayName
          ],
        );
      }

      if (getter is PropertyAccessorElement) {
        reportFieldConflict(getter);
        continue;
      }

      if (setter is PropertyAccessorElement) {
        reportFieldConflict(setter);
        continue;
      }
    }

    // getter declared in the enclosing class vs. inherited method
    for (PropertyAccessorElement accessor in fragment.accessors) {
      String name = accessor.displayName;

      // find inherited method or property accessor
      var inherited = _inheritanceManager.getInherited2(
          enclosingClass, Name(libraryUri, name));
      inherited ??= _inheritanceManager.getInherited2(
          enclosingClass, Name(libraryUri, '$name='));

      if (accessor.isStatic && inherited != null) {
        errorReporter.atElement(
          accessor,
          CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
          arguments: [
            enclosingClass.displayName,
            name,
            inherited.enclosingElement3.displayName,
          ],
        );
        conflictingDeclaredNames.add(name);
      } else if (inherited is MethodElement) {
        // Extension type accessors preclude inherited accessors/methods.
        if (enclosingClass is ExtensionTypeElement) {
          continue;
        }
        errorReporter.atElement(
          accessor,
          CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD,
          arguments: [
            enclosingClass.displayName,
            name,
            inherited.enclosingElement3.displayName
          ],
        );
        conflictingDeclaredNames.add(name);
      }
    }

    // Inherited method and setter with the same name.
    var inherited = _inheritanceManager.getInheritedMap2(enclosingClass);
    for (var entry in inherited.entries) {
      var method = entry.value;
      if (method is MethodElement) {
        var methodName = entry.key;
        if (conflictingDeclaredNames.contains(methodName.name)) {
          continue;
        }
        var setterName = methodName.forSetter;
        var setter = inherited[setterName];
        if (setter is PropertyAccessorElement) {
          errorReporter.atElement(
            enclosingClass,
            CompileTimeErrorCode.CONFLICTING_INHERITED_METHOD_AND_SETTER,
            arguments: [
              enclosingClass.kind.displayName,
              enclosingClass.displayName,
              methodName.name,
            ],
            contextMessages: [
              DiagnosticMessageImpl(
                filePath: method.source.fullName,
                message: formatList(
                  "The method is inherited from the {0} '{1}'.",
                  [
                    method.enclosingElement3.kind.displayName,
                    method.enclosingElement3.name,
                  ],
                ),
                offset: method.nameOffset,
                length: method.nameLength,
                url: null,
              ),
              DiagnosticMessageImpl(
                filePath: setter.source.fullName,
                message: formatList(
                  "The setter is inherited from the {0} '{1}'.",
                  [
                    setter.enclosingElement3.kind.displayName,
                    setter.enclosingElement3.name,
                  ],
                ),
                offset: setter.nameOffset,
                length: setter.nameLength,
                url: null,
              ),
            ],
          );
        }
      }
    }
  }

  /// Verify all conflicts between type variable and enclosing class.
  void _checkForConflictingClassTypeVariableErrorCodes() {
    var enclosingClass = _enclosingClass!;
    for (TypeParameterElement typeParameter in enclosingClass.typeParameters) {
      if (typeParameter.isWildcardVariable) continue;

      String name = typeParameter.name;
      // name is same as the name of the enclosing class
      if (enclosingClass.name == name) {
        var code = enclosingClass is MixinElement
            ? CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MIXIN
            : CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS;
        errorReporter.atElement(
          typeParameter,
          code,
          arguments: [name],
        );
      }
      // check members
      if (enclosingClass.getNamedConstructor(name) != null ||
          enclosingClass.getMethod(name) != null ||
          enclosingClass.getGetter(name) != null ||
          enclosingClass.getSetter(name) != null) {
        var code = enclosingClass is MixinElement
            ? CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_MIXIN
            : CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_CLASS;
        errorReporter.atElement(
          typeParameter,
          code,
          arguments: [name],
        );
      }
    }
  }

  void _checkForConflictingEnumTypeVariableErrorCodes(
    EnumElementImpl element,
  ) {
    for (var typeParameter in element.typeParameters) {
      var name = typeParameter.name;
      // name is same as the name of the enclosing enum
      if (element.name == name) {
        errorReporter.atElement(
          typeParameter,
          CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_ENUM,
          arguments: [name],
        );
      }
      // check members
      if (element.getMethod(name) != null ||
          element.getGetter(name) != null ||
          element.getSetter(name) != null) {
        errorReporter.atElement(
          typeParameter,
          CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM,
          arguments: [name],
        );
      }
    }
  }

  void _checkForConflictingExtensionTypeTypeVariableErrorCodes(
    ExtensionTypeElementImpl element,
  ) {
    for (var typeParameter in element.typeParameters) {
      if (typeParameter.isWildcardVariable) continue;

      var name = typeParameter.name;
      // name is same as the name of the enclosing class
      if (element.name == name) {
        errorReporter.atElement(
          typeParameter,
          CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_EXTENSION_TYPE,
          arguments: [name],
        );
      }
      // check members
      if (element.getNamedConstructor(name) != null ||
          element.getMethod(name) != null ||
          element.getGetter(name) != null ||
          element.getSetter(name) != null) {
        errorReporter.atElement(
          typeParameter,
          CompileTimeErrorCode
              .CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION_TYPE,
          arguments: [name],
        );
      }
    }
  }

  /// Verify all conflicts between type variable and enclosing extension.
  ///
  /// See [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_EXTENSION], and
  /// [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_EXTENSION_MEMBER].
  void _checkForConflictingExtensionTypeVariableErrorCodes() {
    for (TypeParameterElement typeParameter
        in _enclosingExtension!.typeParameters) {
      String name = typeParameter.name;
      // name is same as the name of the enclosing class
      if (_enclosingExtension!.name == name) {
        errorReporter.atElement(
          typeParameter,
          CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_EXTENSION,
          arguments: [name],
        );
      }
      // check members
      if (_enclosingExtension!.getMethod(name) != null ||
          _enclosingExtension!.getGetter(name) != null ||
          _enclosingExtension!.getSetter(name) != null) {
        errorReporter.atElement(
          typeParameter,
          CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION,
          arguments: [name],
        );
      }
    }
  }

  void _checkForConflictingGenerics(NamedCompilationUnitMember node) {
    var element = node.declaredElement as InterfaceElementImpl;

    // Report only on the declaration.
    if (element.isAugmentation) {
      return;
    }

    var analysisSession = _currentLibrary.session;
    var errors = analysisSession.classHierarchy.errors(element);

    for (var error in errors) {
      if (error is IncompatibleInterfacesClassHierarchyError) {
        errorReporter.atToken(
          node.name,
          CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES,
          arguments: [
            _enclosingClass!.kind.displayName,
            _enclosingClass!.name,
            error.first.getDisplayString(),
            error.second.getDisplayString(),
          ],
        );
      } else {
        throw UnimplementedError('${error.runtimeType}');
      }
    }
  }

  /// Check that the given constructor [declaration] has a valid combination of
  /// redirecting constructor invocation(s), super constructor invocation(s),
  /// field initializers, and assert initializers.
  void _checkForConflictingInitializerErrorCodes(
      ConstructorDeclaration declaration) {
    var enclosingClass = _enclosingClass;
    if (enclosingClass == null) {
      return;
    }
    // Count and check each redirecting initializer.
    var redirectingInitializerCount = 0;
    var superInitializerCount = 0;
    late SuperConstructorInvocation superInitializer;
    for (ConstructorInitializer initializer in declaration.initializers) {
      if (initializer is RedirectingConstructorInvocation) {
        if (redirectingInitializerCount > 0) {
          errorReporter.atNode(
            initializer,
            CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS,
          );
        }
        if (declaration.factoryKeyword == null) {
          RedirectingConstructorInvocation invocation = initializer;
          var redirectingElement = invocation.staticElement;
          if (redirectingElement == null) {
            String enclosingNamedType = enclosingClass.displayName;
            String constructorStrName = enclosingNamedType;
            if (invocation.constructorName != null) {
              constructorStrName += ".${invocation.constructorName!.name}";
            }
            errorReporter.atNode(
              invocation,
              CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR,
              arguments: [constructorStrName, enclosingNamedType],
            );
          } else {
            if (redirectingElement.isFactory) {
              errorReporter.atNode(
                initializer,
                CompileTimeErrorCode
                    .REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR,
              );
            }
          }
        }
        // [declaration] is a redirecting constructor via a redirecting
        // initializer.
        _checkForRedirectToNonConstConstructor(
          declaration.declaredElement!,
          initializer.staticElement,
          initializer.constructorName ?? initializer.thisKeyword,
        );
        redirectingInitializerCount++;
      } else if (initializer is SuperConstructorInvocation) {
        if (enclosingClass is EnumElement) {
          errorReporter.atToken(
            initializer.superKeyword,
            CompileTimeErrorCode.SUPER_IN_ENUM_CONSTRUCTOR,
          );
        } else if (superInitializerCount == 1) {
          // Only report the second (first illegal) superinitializer.
          errorReporter.atNode(
            initializer,
            CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS,
          );
        }
        superInitializer = initializer;
        superInitializerCount++;
      }
    }
    // Check for initializers which are illegal when alongside a redirecting
    // initializer.
    if (redirectingInitializerCount > 0) {
      for (ConstructorInitializer initializer in declaration.initializers) {
        if (initializer is SuperConstructorInvocation) {
          if (enclosingClass is! EnumElement) {
            errorReporter.atNode(
              initializer,
              CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR,
            );
          }
        }
        if (initializer is ConstructorFieldInitializer) {
          errorReporter.atNode(
            initializer,
            CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR,
          );
        }
        if (initializer is AssertInitializer) {
          errorReporter.atNode(
            initializer,
            CompileTimeErrorCode.ASSERT_IN_REDIRECTING_CONSTRUCTOR,
          );
        }
      }
    }
    if (enclosingClass is! EnumElement &&
        redirectingInitializerCount == 0 &&
        superInitializerCount == 1 &&
        superInitializer != declaration.initializers.last) {
      var superType = enclosingClass.supertype;
      if (superType != null) {
        var superNamedType = superType.element.displayName;
        var constructorStrName = superNamedType;
        var constructorName = superInitializer.constructorName;
        if (constructorName != null) {
          constructorStrName += '.${constructorName.name}';
        }
        errorReporter.atToken(
          superInitializer.superKeyword,
          CompileTimeErrorCode.SUPER_INVOCATION_NOT_LAST,
          arguments: [constructorStrName],
        );
      }
    }
  }

  /// Verify that if the given [constructor] declaration is 'const' then there
  /// are no invocations of non-'const' super constructors, and that there are
  /// no instance variables mixed in.
  ///
  /// Return `true` if an error is reported here, and the caller should stop
  /// checking the constructor for constant-related errors.
  ///
  /// See [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER], and
  /// [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD].
  bool _checkForConstConstructorWithNonConstSuper(
      ConstructorDeclaration constructor) {
    var enclosingClass = _enclosingClass;
    if (enclosingClass == null || !_enclosingExecutable.isConstConstructor) {
      return false;
    }

    // OK, const factory, checked elsewhere
    if (constructor.factoryKeyword != null) {
      return false;
    }

    // check for mixins
    var instanceFields = <FieldElement>[];
    for (var mixin in enclosingClass.mixins) {
      instanceFields.addAll(mixin.element.fields.where((field) {
        if (field.isStatic) {
          return false;
        }
        if (field.isSynthetic) {
          return false;
        }
        // From the abstract and external fields specification:
        // > An abstract instance variable declaration D is treated as an
        // > abstract getter declaration and possibly an abstract setter
        // > declaration. The setter is included if and only if D is non-final.
        if (field.isAbstract && field.isFinal) {
          return false;
        }
        return true;
      }));
    }
    if (instanceFields.length == 1) {
      var field = instanceFields.single;
      errorReporter.atNode(
        constructor.returnType,
        CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
        arguments: ["'${field.enclosingElement3.name}.${field.name}'"],
      );
      return true;
    } else if (instanceFields.length > 1) {
      var fieldNames = instanceFields
          .map((field) => "'${field.enclosingElement3.name}.${field.name}'")
          .join(', ');
      errorReporter.atNode(
        constructor.returnType,
        CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELDS,
        arguments: [fieldNames],
      );
      return true;
    }

    // Enum(s) always call a const super-constructor.
    if (enclosingClass is EnumElement) {
      return false;
    }

    var element = constructor.declaredElement;
    if (element == null) {
      return false;
    }

    // Redirecting constructors are checked to be const elsewhere.
    if (element.redirectedConstructor != null) {
      return false;
    }

    var invokedSuper = element.superConstructor;
    if (invokedSuper == null || invokedSuper.isConst) {
      return false;
    }

    // Often there is an explicit `super()` invocation, report on it.
    var superInvocation = constructor.initializers
        .whereType<SuperConstructorInvocation>()
        .firstOrNull;
    var errorNode = superInvocation ?? constructor.returnType;

    errorReporter.atNode(
      errorNode,
      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER,
      arguments: [element.enclosingElement3.displayName],
    );
    return true;
  }

  /// Verify that if the given [constructor] declaration is 'const' then there
  /// are no non-final instance variable. The [constructorElement] is the
  /// constructor element.
  void _checkForConstConstructorWithNonFinalField(
      ConstructorDeclaration constructor,
      ConstructorElement constructorElement) {
    if (!_enclosingExecutable.isConstConstructor) {
      return;
    }
    if (!_enclosingExecutable.isGenerativeConstructor) {
      return;
    }
    // check if there is non-final field
    var classElement = constructorElement.enclosingElement3;
    if (classElement is! ClassElement || !classElement.hasNonFinalField) {
      return;
    }
    errorReporter.atConstructorDeclaration(
      constructor,
      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD,
    );
  }

  /// Verify that the given 'const' instance creation [expression] is not
  /// creating a deferred type. The [constructorName] is the constructor name,
  /// always non-`null`. The [namedType] is the name of the type defining the
  /// constructor, always non-`null`.
  ///
  /// See [CompileTimeErrorCode.CONST_DEFERRED_CLASS].
  void _checkForConstDeferredClass(InstanceCreationExpression expression,
      ConstructorName constructorName, NamedType namedType) {
    if (namedType.isDeferred) {
      errorReporter.atNode(
        constructorName,
        CompileTimeErrorCode.CONST_DEFERRED_CLASS,
      );
    }
  }

  /// Verify that the given throw [expression] is not enclosed in a 'const'
  /// constructor declaration.
  ///
  /// See [CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION].
  void _checkForConstEvalThrowsException(ThrowExpression expression) {
    if (_enclosingExecutable.isConstConstructor) {
      errorReporter.atNode(
        expression,
        CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION,
      );
    }
  }

  /// Verify that the given instance creation [expression] is not being invoked
  /// on an abstract class. The [namedType] is the [NamedType] of the
  /// [ConstructorName] from the [InstanceCreationExpression], this is the AST
  /// node that the error is attached to. The [type] is the type being
  /// constructed with this [InstanceCreationExpression].
  void _checkForConstOrNewWithAbstractClass(
      InstanceCreationExpression expression,
      NamedType namedType,
      InterfaceType type) {
    var element = type.element;
    if (element is ClassElement && element.isAbstract) {
      var element = expression.constructorName.staticElement;
      if (element != null && !element.isFactory) {
        bool isImplicit =
            (expression as InstanceCreationExpressionImpl).isImplicit;
        if (!isImplicit) {
          errorReporter.atNode(
            namedType,
            CompileTimeErrorCode.INSTANTIATE_ABSTRACT_CLASS,
          );
        } else {
          errorReporter.atNode(
            namedType,
            CompileTimeErrorCode.INSTANTIATE_ABSTRACT_CLASS,
          );
        }
      }
    }
  }

  /// Verify that the given [expression] is not a mixin instantiation.
  void _checkForConstOrNewWithMixin(InstanceCreationExpression expression,
      NamedType namedType, InterfaceType type) {
    if (type.element is MixinElement) {
      errorReporter.atNode(
        namedType,
        CompileTimeErrorCode.MIXIN_INSTANTIATE,
      );
    }
  }

  /// Verify that the given 'const' instance creation [expression] is not being
  /// invoked on a constructor that is not 'const'.
  ///
  /// This method assumes that the instance creation was tested to be 'const'
  /// before being called.
  ///
  /// See [CompileTimeErrorCode.CONST_WITH_NON_CONST].
  void _checkForConstWithNonConst(InstanceCreationExpression expression) {
    var constructorElement = expression.constructorName.staticElement;
    if (constructorElement != null && !constructorElement.isConst) {
      if (expression.keyword != null) {
        errorReporter.atToken(
          expression.keyword!,
          CompileTimeErrorCode.CONST_WITH_NON_CONST,
        );
      } else {
        errorReporter.atNode(
          expression,
          CompileTimeErrorCode.CONST_WITH_NON_CONST,
        );
      }
    }
  }

  /// Verify that if the given 'const' instance creation [expression] is being
  /// invoked on the resolved constructor. The [constructorName] is the
  /// constructor name, always non-`null`. The [namedType] is the name of the
  /// type defining the constructor, always non-`null`.
  ///
  /// This method assumes that the instance creation was tested to be 'const'
  /// before being called.
  ///
  /// See [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR], and
  /// [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT].
  void _checkForConstWithUndefinedConstructor(
      InstanceCreationExpression expression,
      ConstructorName constructorName,
      NamedType namedType) {
    // OK if resolved
    if (constructorName.staticElement != null) {
      return;
    }
    // report as named or default constructor absence
    var name = constructorName.name;
    if (name != null) {
      errorReporter.atNode(
        name,
        CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR,
        arguments: [namedType.qualifiedName, name.name],
      );
    } else {
      errorReporter.atNode(
        constructorName,
        CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT,
        arguments: [namedType.qualifiedName],
      );
    }
  }

  void _checkForDeadNullCoalesce(TypeImpl lhsType, Expression rhs) {
    if (typeSystem.isStrictlyNonNullable(lhsType)) {
      errorReporter.atNode(
        rhs,
        StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION,
      );
    }
  }

  /// Report a diagnostic if there are any extensions in the imported library
  /// that are not hidden.
  void _checkForDeferredImportOfExtensions(
      ImportDirective directive, LibraryImportElement importElement) {
    for (var element in importElement.namespace.definedNames.values) {
      if (element is ExtensionElement) {
        errorReporter.atNode(
          directive.uri,
          CompileTimeErrorCode.DEFERRED_IMPORT_OF_EXTENSION,
        );
        return;
      }
    }
  }

  /// Verify that any deferred imports in the given compilation [unit] have a
  /// unique prefix.
  ///
  /// See [CompileTimeErrorCode.SHARED_DEFERRED_PREFIX].
  void _checkForDeferredPrefixCollisions(CompilationUnit unit) {
    NodeList<Directive> directives = unit.directives;
    int count = directives.length;
    if (count > 0) {
      Map<PrefixElement, List<ImportDirective>> prefixToDirectivesMap =
          HashMap<PrefixElement, List<ImportDirective>>();
      for (int i = 0; i < count; i++) {
        Directive directive = directives[i];
        if (directive is ImportDirective) {
          var prefix = directive.prefix;
          if (prefix != null) {
            var element = prefix.staticElement;
            if (element is PrefixElement) {
              var elements = prefixToDirectivesMap[element];
              if (elements == null) {
                elements = <ImportDirective>[];
                prefixToDirectivesMap[element] = elements;
              }
              elements.add(directive);
            }
          }
        }
      }
      for (List<ImportDirective> imports in prefixToDirectivesMap.values) {
        _checkDeferredPrefixCollision(imports);
      }
    }
  }

  /// Return `true` if the caller should continue checking the rest of the
  /// information in the for-each part.
  bool _checkForEachParts(ForEachParts node, Element? variableElement) {
    if (checkForUseOfVoidResult(node.iterable)) {
      return false;
    }

    DartType iterableType = node.iterable.typeOrThrow;

    Token? awaitKeyword;
    var parent = node.parent;
    if (parent is ForStatement) {
      awaitKeyword = parent.awaitKeyword;
    } else if (parent is ForElement) {
      awaitKeyword = parent.awaitKeyword;
    }

    // Use an explicit string instead of [loopType] to remove the "<E>".
    String loopNamedType = awaitKeyword != null ? 'Stream' : 'Iterable';

    if (iterableType is DynamicType && strictCasts) {
      errorReporter.atNode(
        node.iterable,
        CompileTimeErrorCode.FOR_IN_OF_INVALID_TYPE,
        arguments: [iterableType, loopNamedType],
      );
      return false;
    }

    // TODO(scheglov): use NullableDereferenceVerifier
    if (typeSystem.isNullable(iterableType)) {
      return false;
    }

    // The type of the loop variable.
    DartType variableType;
    if (variableElement is VariableElement) {
      variableType = variableElement.type;
    } else {
      return false;
    }

    // The object being iterated has to implement Iterable<T> for some T that
    // is assignable to the variable's type.
    // TODO(rnystrom): Move this into mostSpecificTypeArgument()?
    iterableType = typeSystem.resolveToBound(iterableType);

    var requiredSequenceType = awaitKeyword != null
        ? _typeProvider.streamDynamicType
        : _typeProvider.iterableDynamicType;

    if (typeSystem.isTop(iterableType)) {
      iterableType = requiredSequenceType;
    }

    if (!typeSystem.isAssignableTo(iterableType, requiredSequenceType,
        strictCasts: strictCasts)) {
      errorReporter.atNode(
        node.iterable,
        CompileTimeErrorCode.FOR_IN_OF_INVALID_TYPE,
        arguments: [iterableType, loopNamedType],
      );
      return false;
    }

    DartType? sequenceElementType;
    {
      var sequenceElement = awaitKeyword != null
          ? _typeProvider.streamElement
          : _typeProvider.iterableElement;
      var sequenceType = iterableType.asInstanceOf(sequenceElement);
      if (sequenceType != null) {
        sequenceElementType = sequenceType.typeArguments[0];
      }
    }

    if (sequenceElementType == null) {
      return true;
    }

    if (!typeSystem.isAssignableTo(sequenceElementType, variableType,
        strictCasts: strictCasts)) {
      // Use an explicit string instead of [loopType] to remove the "<E>".
      String loopNamedType = awaitKeyword != null ? 'Stream' : 'Iterable';

      // A for-in loop is specified to desugar to a different set of statements
      // which include an assignment of the sequence element's `iterator`'s
      // `current` value, at which point "implicit tear-off conversion" may be
      // performed. We do not perform this desugaring; instead we allow a
      // special assignability here.
      var implicitCallMethod = getImplicitCallMethod(
          sequenceElementType, variableType, node.iterable);
      if (implicitCallMethod == null) {
        errorReporter.atNode(
          node.iterable,
          CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE,
          arguments: [iterableType, loopNamedType, variableType],
        );
      } else {
        var tearoffType = implicitCallMethod.type;
        // An implicit tear-off conversion does occur on the values of the
        // iterator, but this does not guarantee their assignability.

        if (_featureSet?.isEnabled(Feature.constructor_tearoffs) ?? true) {
          var typeArguments = typeSystem.inferFunctionTypeInstantiation(
            variableType as FunctionType,
            tearoffType,
            errorReporter: errorReporter,
            errorNode: node.iterable,
            genericMetadataIsEnabled: true,
            inferenceUsingBoundsIsEnabled:
                _featureSet?.isEnabled(Feature.inference_using_bounds) ?? true,
            strictInference: options.strictInference,
            strictCasts: options.strictCasts,
            typeSystemOperations: typeSystemOperations,
            dataForTesting: null,
            nodeForTesting: null,
          );
          if (typeArguments.isNotEmpty) {
            tearoffType = tearoffType.instantiate(typeArguments);
          }
        }

        if (!typeSystem.isAssignableTo(tearoffType, variableType,
            strictCasts: strictCasts)) {
          errorReporter.atNode(
            node.iterable,
            CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE,
            arguments: [iterableType, loopNamedType, variableType],
          );
        }
      }
    }

    return true;
  }

  void _checkForEnumInstantiatedToBoundsIsNotWellBounded(
    EnumDeclaration node,
    EnumElementImpl element,
  ) {
    var valuesFieldType = element.valuesField?.type;
    if (valuesFieldType is InterfaceType) {
      var isWellBounded = typeSystem.isWellBounded(
        valuesFieldType.typeArguments.single,
        allowSuperBounded: true,
      );
      if (isWellBounded is NotWellBoundedTypeResult) {
        errorReporter.atToken(
          node.name,
          CompileTimeErrorCode.ENUM_INSTANTIATED_TO_BOUNDS_IS_NOT_WELL_BOUNDED,
        );
      }
    }
  }

  /// Check that if the visiting library is not system, then any given library
  /// should not be SDK internal library. The [exportElement] is the
  /// [LibraryExportElement] retrieved from the node, if the element in the node was
  /// `null`, then this method is not called.
  ///
  /// See [CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY].
  void _checkForExportInternalLibrary(
      ExportDirective directive, LibraryExportElement exportElement) {
    if (_isInSystemLibrary) {
      return;
    }

    var exportedLibrary = exportElement.exportedLibrary;
    if (exportedLibrary == null) {
      return;
    }

    // should be private
    var sdk = _currentLibrary.context.sourceFactory.dartSdk!;
    var uri = exportedLibrary.source.uri.toString();

    // We allow exporting `dart:_macros` from `package:macros`.
    if (uri == 'dart:_macros' &&
        _currentLibrary.source.uri.scheme == 'package' &&
        _currentLibrary.source.uri.pathSegments.first == 'macros') {
      return;
    }
    var sdkLibrary = sdk.getSdkLibrary(uri);
    if (sdkLibrary == null) {
      return;
    }
    if (!sdkLibrary.isInternal) {
      return;
    }

    // It is safe to assume that `directive.uri.stringValue` is non-`null`,
    // because the only time it is `null` is if the URI contains a string
    // interpolation, in which case the export would never have resolved in the
    // first place.
    errorReporter.atNode(
      directive,
      CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY,
      arguments: [directive.uri.stringValue!],
    );
  }

  /// Verify that the given extends [clause] does not extend a deferred class.
  ///
  /// See [CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS].
  void _checkForExtendsDeferredClass(NamedType? superclass) {
    if (superclass == null) {
      return;
    }
    _checkForExtendsOrImplementsDeferredClass(
        superclass, CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS);
  }

  /// Verify that the given extends [clause] does not extend classes such as
  /// 'num' or 'String'.
  ///
  /// See [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS].
  bool _checkForExtendsDisallowedClass(NamedType? superclass) {
    if (superclass == null) {
      return false;
    }
    return _checkForExtendsOrImplementsDisallowedClass(
        superclass, CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS);
  }

  /// Verify that the given [namedType] does not extend, implement or mixin
  /// classes that are deferred.
  ///
  /// See [_checkForExtendsDeferredClass],
  /// [_checkForExtendsDeferredClassInTypeAlias],
  /// [_checkForImplementsDeferredClass],
  /// [_checkForAllMixinErrorCodes],
  /// [CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS],
  /// [CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS], and
  /// [CompileTimeErrorCode.MIXIN_DEFERRED_CLASS].
  bool _checkForExtendsOrImplementsDeferredClass(
      NamedType namedType, ErrorCode errorCode) {
    if (namedType.isSynthetic) {
      return false;
    }
    if (namedType.isDeferred) {
      errorReporter.atNode(
        namedType,
        errorCode,
      );
      return true;
    }
    return false;
  }

  /// Verify that the given [namedType] does not extend, implement or mixin
  /// classes such as 'num' or 'String'.
  ///
  // TODO(scheglov): Remove this method, when all inheritance / override
  // is concentrated. We keep it for now only because we need to know when
  // inheritance is completely wrong, so that we don't need to check anything
  // else.
  bool _checkForExtendsOrImplementsDisallowedClass(
      NamedType namedType, ErrorCode errorCode) {
    if (namedType.isSynthetic) {
      return false;
    }
    // The SDK implementation may implement disallowed types. For example,
    // JSNumber in dart2js and _Smi in Dart VM both implement int.
    if (_currentLibrary.source.uri.isScheme('dart')) {
      return false;
    }
    var type = namedType.type;
    return type is InterfaceType &&
        _typeProvider.isNonSubtypableClass(type.element);
  }

  void _checkForExtensionDeclaresMemberOfObject(MethodDeclaration node) {
    if (_enclosingExtension != null) {
      if (node.hasObjectMemberName) {
        errorReporter.atToken(
          node.name,
          CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT,
        );
      }
    }

    if (_enclosingClass is ExtensionTypeElement) {
      if (node.hasObjectMemberName) {
        errorReporter.atToken(
          node.name,
          CompileTimeErrorCode.EXTENSION_TYPE_DECLARES_MEMBER_OF_OBJECT,
        );
      }
    }
  }

  void _checkForExtensionTypeConstructorWithSuperInvocation(
    SuperConstructorInvocation node,
  ) {
    if (_enclosingClass is ExtensionTypeElement) {
      errorReporter.atToken(
        node.superKeyword,
        CompileTimeErrorCode.EXTENSION_TYPE_CONSTRUCTOR_WITH_SUPER_INVOCATION,
      );
    }
  }

  void _checkForExtensionTypeDeclaresInstanceField(FieldDeclaration node) {
    if (_enclosingClass is! ExtensionTypeElement) {
      return;
    }

    if (node.isStatic || node.externalKeyword != null) {
      return;
    }

    for (var field in node.fields.variables) {
      errorReporter.atToken(
        field.name,
        CompileTimeErrorCode.EXTENSION_TYPE_DECLARES_INSTANCE_FIELD,
      );
    }
  }

  void _checkForExtensionTypeImplementsDeferred(
    ExtensionTypeDeclarationImpl node,
  ) {
    var clause = node.implementsClause;
    if (clause == null) {
      return;
    }

    for (var type in clause.interfaces) {
      _checkForExtendsOrImplementsDeferredClass(
        type,
        CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS,
      );
    }
  }

  void _checkForExtensionTypeImplementsItself(
    ExtensionTypeDeclarationImpl node,
    ExtensionTypeElementImpl element,
  ) {
    if (element.hasImplementsSelfReference) {
      errorReporter.atToken(
        node.name,
        CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_ITSELF,
      );
    }
  }

  void _checkForExtensionTypeMemberConflicts({
    required ExtensionTypeDeclaration node,
    required ExtensionTypeElement element,
  }) {
    void report(String memberName, List<ExecutableElement> candidates) {
      var contextMessages = candidates.map<DiagnosticMessage>((executable) {
        var nonSynthetic = executable.nonSynthetic;
        var container = executable.enclosingElement3 as InterfaceElement;
        return DiagnosticMessageImpl(
          filePath: executable.source.fullName,
          offset: nonSynthetic.nameOffset,
          length: nonSynthetic.nameLength,
          message: "Inherited from '${container.name}'",
          url: null,
        );
      }).toList();
      errorReporter.atToken(
        node.name,
        CompileTimeErrorCode.EXTENSION_TYPE_INHERITED_MEMBER_CONFLICT,
        arguments: [node.name.lexeme, memberName],
        contextMessages: contextMessages,
      );
    }

    var interface = _inheritanceManager.getInterface(element);
    for (var conflict in interface.conflicts) {
      switch (conflict) {
        case CandidatesConflict _:
          report(conflict.name.name, conflict.candidates);
        case HasNonExtensionAndExtensionMemberConflict _:
          report(conflict.name.name, [
            ...conflict.nonExtension,
            ...conflict.extension,
          ]);
        case NotUniqueExtensionMemberConflict _:
          report(conflict.name.name, conflict.candidates);
      }
    }
  }

  void _checkForExtensionTypeRepresentationDependsOnItself(
    ExtensionTypeDeclarationImpl node,
    ExtensionTypeElementImpl element,
  ) {
    if (element.hasRepresentationSelfReference) {
      errorReporter.atToken(
        node.name,
        CompileTimeErrorCode.EXTENSION_TYPE_REPRESENTATION_DEPENDS_ON_ITSELF,
      );
    }
  }

  void _checkForExtensionTypeRepresentationTypeBottom(
    ExtensionTypeDeclarationImpl node,
    ExtensionTypeElementImpl element,
  ) {
    var representationType = element.representation.type;
    if (representationType.isBottom) {
      errorReporter.atNode(
        node.representation.fieldType,
        CompileTimeErrorCode.EXTENSION_TYPE_REPRESENTATION_TYPE_BOTTOM,
      );
    }
  }

  void _checkForExtensionTypeWithAbstractMember(
    ExtensionTypeDeclarationImpl node,
  ) {
    for (var member in node.members) {
      if (member is MethodDeclarationImpl && !member.isStatic) {
        if (member.isAbstract) {
          errorReporter.atNode(
            member,
            CompileTimeErrorCode.EXTENSION_TYPE_WITH_ABSTRACT_MEMBER,
            arguments: [member.name.lexeme, node.name.lexeme],
          );
        }
      }
    }
  }

  /// Verify that the given field formal [parameter] is in a constructor
  /// declaration.
  ///
  /// See [CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR].
  void _checkForFieldInitializingFormalRedirectingConstructor(
      FieldFormalParameter parameter) {
    // prepare the node that should be a ConstructorDeclaration
    var formalParameterList = parameter.parent;
    if (formalParameterList is! FormalParameterList) {
      formalParameterList = formalParameterList?.parent;
    }
    var constructor = formalParameterList?.parent;
    // now check whether the node is actually a ConstructorDeclaration
    if (constructor is ConstructorDeclaration) {
      // constructor cannot be a factory
      if (constructor.factoryKeyword != null) {
        errorReporter.atNode(
          parameter,
          CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR,
        );
        return;
      }
      // constructor cannot have a redirection
      for (ConstructorInitializer initializer in constructor.initializers) {
        if (initializer is RedirectingConstructorInvocation) {
          errorReporter.atNode(
            parameter,
            CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR,
          );
          return;
        }
      }
    } else {
      errorReporter.atNode(
        parameter,
        CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
      );
    }
  }

  /// Verify that the given variable declaration [list] has only initialized
  /// variables if the list is final or const.
  ///
  /// See [CompileTimeErrorCode.CONST_NOT_INITIALIZED], and
  /// [CompileTimeErrorCode.FINAL_NOT_INITIALIZED].
  void _checkForFinalNotInitialized(VariableDeclarationList list) {
    if (_isInNativeClass || list.isSynthetic) {
      return;
    }

    // Handled during resolution, with flow analysis.
    if (list.isFinal && list.parent is VariableDeclarationStatement) {
      return;
    }

    bool isConst = list.isConst;
    if (!(isConst || list.isFinal)) {
      return;
    }
    NodeList<VariableDeclaration> variables = list.variables;
    for (VariableDeclaration variable in variables) {
      if (variable.initializer == null) {
        if (isConst) {
          errorReporter.atToken(
            variable.name,
            CompileTimeErrorCode.CONST_NOT_INITIALIZED,
            arguments: [variable.name.lexeme],
          );
        } else {
          var variableElement = variable.declaredElement;
          if (variableElement is FieldElement &&
              (variableElement.isAbstract || variableElement.isExternal)) {
            // Abstract and external fields can't be initialized, so no error.
          } else if (variableElement is TopLevelVariableElement &&
              variableElement.isExternal) {
            // External top level variables can't be initialized, so no error.
          } else if (!variable.isLate) {
            errorReporter.atToken(
              variable.name,
              CompileTimeErrorCode.FINAL_NOT_INITIALIZED,
              arguments: [variable.name.lexeme],
            );
          }
        }
      }
    }
  }

  /// If there are no constructors in the given [members], verify that all
  /// final fields are initialized.  Cases in which there is at least one
  /// constructor are handled in [_checkForAllFinalInitializedErrorCodes].
  ///
  /// See [CompileTimeErrorCode.CONST_NOT_INITIALIZED], and
  /// [CompileTimeErrorCode.FINAL_NOT_INITIALIZED].
  void _checkForFinalNotInitializedInClass(
    InstanceElementImpl container,
    List<ClassMember> members,
  ) {
    if (container is InterfaceElementImpl) {
      var augmented = container.augmented;
      for (var constructor in augmented.constructors) {
        if (constructor.isGenerative && !constructor.isSynthetic) {
          return;
        }
      }
    }

    for (ClassMember classMember in members) {
      if (classMember is FieldDeclaration) {
        var fields = classMember.fields;
        _checkForFinalNotInitialized(fields);
        _checkForNotInitializedNonNullableInstanceFields(classMember);
      }
    }
  }

  /// Check that if a direct supertype of a node is final, then it must be in
  /// the same library.
  ///
  /// See [CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY],
  /// [CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY],
  /// [CompileTimeErrorCode.
  /// FINAL_CLASS_USED_AS_MIXIN_CONSTRAINT_OUTSIDE_OF_LIBRARY].
  void _checkForFinalSupertypeOutsideOfLibrary(
    NamedType? superclass,
    WithClause? withClause,
    ImplementsClause? implementsClause,
    MixinOnClause? onClause,
  ) {
    if (superclass != null) {
      var type = superclass.type;
      if (type is InterfaceType) {
        var element = type.element;
        if (element is ClassElementImpl &&
            element.isFinal &&
            !element.isSealed &&
            element.library != _currentLibrary &&
            !_mayIgnoreClassModifiers(element.library)) {
          errorReporter.atNode(
            superclass,
            CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY,
            arguments: [element.name],
          );
        }
      }
    }
    if (implementsClause != null) {
      for (NamedType namedType in implementsClause.interfaces) {
        var type = namedType.type;
        if (type is InterfaceType) {
          var implementedInterfaces = [
            type,
            ...type.element.allSupertypes,
          ].map((e) => e.element).toList();
          for (var element in implementedInterfaces) {
            if (element is ClassElement &&
                element.isFinal &&
                !element.isSealed &&
                element.library != _currentLibrary &&
                !_mayIgnoreClassModifiers(element.library)) {
              // If the final interface is an indirect interface and is in a
              // different library that has class modifiers enabled, there is a
              // nearer declaration that would emit an error, if any.
              if (element != type.element &&
                  type.element.library.featureSet
                      .isEnabled(Feature.class_modifiers)) {
                continue;
              }

              errorReporter.atNode(
                namedType,
                CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY,
                arguments: [element.name],
              );
              break;
            }
          }
        }
      }
    }
    if (onClause != null) {
      for (NamedType namedType in onClause.superclassConstraints) {
        var type = namedType.type;
        if (type is InterfaceType) {
          var element = type.element;
          if (element is ClassElement &&
              element.isFinal &&
              !element.isSealed &&
              element.library != _currentLibrary &&
              !_mayIgnoreClassModifiers(element.library)) {
            errorReporter.atNode(
              namedType,
              CompileTimeErrorCode
                  .FINAL_CLASS_USED_AS_MIXIN_CONSTRAINT_OUTSIDE_OF_LIBRARY,
              arguments: [element.name],
            );
          }
        }
      }
    }
  }

  void _checkForGenericFunctionType(TypeAnnotation? node) {
    if (node == null) {
      return;
    }
    if (_featureSet?.isEnabled(Feature.generic_metadata) ?? false) {
      return;
    }
    DartType type = node.typeOrThrow;
    if (type is FunctionType && type.typeFormals.isNotEmpty) {
      errorReporter.atNode(
        node,
        CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND,
      );
    }
  }

  void _checkForIllegalLanguageOverride(CompilationUnit node) {
    var sourceLanguageConstraint =
        (options as AnalysisOptionsImpl).sourceLanguageConstraint;
    if (sourceLanguageConstraint == null) {
      return;
    }

    var languageVersion = _currentLibrary.languageVersion.effective;
    if (sourceLanguageConstraint.allows(languageVersion)) {
      return;
    }

    var languageVersionToken = node.languageVersionToken;
    if (languageVersionToken != null) {
      errorReporter.atToken(
        languageVersionToken,
        CompileTimeErrorCode.ILLEGAL_LANGUAGE_VERSION_OVERRIDE,
        arguments: ['$sourceLanguageConstraint'],
      );
    }
  }

  /// Verify that the given implements [clause] does not implement classes such
  /// as 'num' or 'String'.
  ///
  /// See [CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS],
  /// [CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS].
  bool _checkForImplementsClauseErrorCodes(ImplementsClause? clause) {
    if (clause == null) {
      return false;
    }
    bool foundError = false;
    for (NamedType type in clause.interfaces) {
      if (_checkForExtendsOrImplementsDisallowedClass(
          type, CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS)) {
        foundError = true;
      } else if (_checkForExtendsOrImplementsDeferredClass(
          type, CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS)) {
        foundError = true;
      }
    }
    return foundError;
  }

  /// Check that if the visiting library is not system, then any given library
  /// should not be SDK internal library. The [importElement] is the
  /// [LibraryImportElement] retrieved from the node, if the element in the node
  /// was `null`, then this method is not called.
  void _checkForImportInternalLibrary(
      ImportDirective directive, LibraryImportElement importElement) {
    if (_isInSystemLibrary || _isWasm(importElement)) {
      return;
    }

    var importedLibrary = importElement.importedLibrary;
    if (importedLibrary == null) {
      return;
    }

    // should be private
    var sdk = _currentLibrary.context.sourceFactory.dartSdk!;
    var uri = importedLibrary.source.uri.toString();
    var sdkLibrary = sdk.getSdkLibrary(uri);
    if (sdkLibrary == null || !sdkLibrary.isInternal) {
      return;
    }
    // The only way an import URI's `stringValue` can be `null` is if the string
    // contained interpolations, in which case the import would have failed to
    // resolve, and we would never reach here.  So it is safe to assume that
    // `directive.uri.stringValue` is non-`null`.
    errorReporter.atNode(
      directive.uri,
      CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY,
      arguments: [directive.uri.stringValue!],
    );
  }

  /// Check that the given [typeReference] is not a type reference and that then
  /// the [name] is reference to an instance member.
  ///
  /// See [CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER].
  void _checkForInstanceAccessToStaticMember(InterfaceElement? typeReference,
      Expression? target, SimpleIdentifier name) {
    if (_isInComment) {
      // OK, in comment
      return;
    }
    // prepare member Element
    var element = name.writeOrReadElement;
    if (element is ExecutableElement) {
      if (!element.isStatic) {
        // OK, instance member
        return;
      }
      Element enclosingElement = element.enclosingElement3;
      if (enclosingElement is ExtensionElement) {
        if (target is ExtensionOverride) {
          // OK, target is an extension override
          return;
        } else if (target is SimpleIdentifier &&
            target.staticElement is ExtensionElement) {
          return;
        } else if (target is PrefixedIdentifier &&
            target.staticElement is ExtensionElement) {
          return;
        }
      } else {
        if (typeReference != null) {
          // OK, target is a type
          return;
        }
        if (enclosingElement is! InterfaceElement) {
          // OK, top-level element
          return;
        }
      }
    }
  }

  /// Verify that if a class is extending an interface class or mixing in an
  /// interface mixin, it must be within the same library as that class or
  /// mixin.
  ///
  /// See
  /// [CompileTimeErrorCode.INTERFACE_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY].
  void _checkForInterfaceClassOrMixinSuperclassOutsideOfLibrary(
      NamedType? superclass, WithClause? withClause) {
    if (superclass != null) {
      var superclassType = superclass.type;
      if (superclassType is InterfaceType) {
        var superclassElement = superclassType.element;
        if (superclassElement is ClassElementImpl &&
            superclassElement.isInterface &&
            !superclassElement.isSealed &&
            superclassElement.library != _currentLibrary &&
            !_mayIgnoreClassModifiers(superclassElement.library)) {
          errorReporter.atNode(
            superclass,
            CompileTimeErrorCode.INTERFACE_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY,
            arguments: [superclassElement.name],
          );
        }
      }
    }
  }

  /// Verify that an 'int' can be assigned to the parameter corresponding to the
  /// given [argument]. This is used for prefix and postfix expressions where
  /// the argument value is implicit.
  ///
  /// See [CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
  void _checkForIntNotAssignable(Expression argument) {
    var staticParameterElement = argument.staticParameterElement;
    var staticParameterType = staticParameterElement?.type;
    if (staticParameterType != null) {
      checkForArgumentTypeNotAssignable(argument, staticParameterType, _intType,
          CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
    }
  }

  /// Verify that the given [annotation] isn't defined in a deferred library.
  ///
  /// See [CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY].
  void _checkForInvalidAnnotationFromDeferredLibrary(Annotation annotation) {
    Identifier nameIdentifier = annotation.name;
    if (nameIdentifier is PrefixedIdentifier && nameIdentifier.isDeferred) {
      errorReporter.atNode(
        annotation.name,
        CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY,
      );
    }
  }

  /// Check the given [initializer] to ensure that the field being initialized
  /// is a valid field. The [fieldName] is the field name from the
  /// [ConstructorFieldInitializer]. The [staticElement] is the static element
  /// from the name in the [ConstructorFieldInitializer].
  void _checkForInvalidField(ConstructorFieldInitializer initializer,
      SimpleIdentifier fieldName, Element? staticElement) {
    if (staticElement is FieldElement) {
      if (staticElement.isSynthetic) {
        errorReporter.atNode(
          initializer,
          CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD,
          arguments: [fieldName.name],
        );
      } else if (staticElement.isStatic) {
        errorReporter.atNode(
          initializer,
          CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD,
          arguments: [fieldName.name],
        );
      }
    } else {
      errorReporter.atNode(
        initializer,
        CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD,
        arguments: [fieldName.name],
      );
      return;
    }
  }

  void _checkForInvalidGenerativeConstructorReference(ConstructorName node) {
    var constructorElement = node.staticElement;
    if (constructorElement != null &&
        constructorElement.isGenerative &&
        constructorElement.enclosingElement3 is EnumElement) {
      if (_currentLibrary.featureSet.isEnabled(Feature.enhanced_enums)) {
        errorReporter.atNode(
          node,
          CompileTimeErrorCode.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR,
        );
      } else {
        errorReporter.atNode(
          node.type,
          CompileTimeErrorCode.INSTANTIATE_ENUM,
        );
      }
    }
  }

  /// Verify that if the given [identifier] is part of a constructor
  /// initializer, then it does not implicitly reference 'this' expression.
  ///
  /// See [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER],
  /// [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_FACTORY], and
  /// [CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC].
  void _checkForInvalidInstanceMemberAccess(SimpleIdentifier identifier) {
    if (_isInComment) {
      return;
    }
    if (!_isInConstructorInitializer &&
        !_enclosingExecutable.inStaticMethod &&
        !_enclosingExecutable.inFactoryConstructor &&
        !_isInInstanceNotLateVariableDeclaration &&
        !_isInStaticVariableDeclaration) {
      return;
    }
    // prepare element
    var element = identifier.writeOrReadElement;
    if (!(element is MethodElement || element is PropertyAccessorElement)) {
      return;
    }
    // static element
    ExecutableElement executableElement = element as ExecutableElement;
    if (executableElement.isStatic) {
      return;
    }
    // not a class member
    Element enclosingElement = element.enclosingElement3;
    if (enclosingElement is! InterfaceElement &&
        enclosingElement is! ExtensionElement) {
      return;
    }
    // qualified method invocation
    var parent = identifier.parent;
    if (parent is MethodInvocation) {
      if (identical(parent.methodName, identifier) &&
          parent.realTarget != null) {
        return;
      }
    }
    // qualified property access
    if (parent is PropertyAccess) {
      if (identical(parent.propertyName, identifier)) {
        return;
      }
    }
    if (parent is PrefixedIdentifier) {
      if (identical(parent.identifier, identifier)) {
        return;
      }
    }

    if (_enclosingExecutable.inStaticMethod) {
      errorReporter.atNode(
        identifier,
        CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC,
      );
    } else if (_enclosingExecutable.inFactoryConstructor) {
      errorReporter.atNode(
        identifier,
        CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_FACTORY,
      );
    } else {
      errorReporter.atNode(
        identifier,
        CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER,
        arguments: [identifier.name],
      );
    }
  }

  /// Check to see whether the given function [body] has a modifier associated
  /// with it, and report it as an error if it does.
  void _checkForInvalidModifierOnBody(
      FunctionBody body, CompileTimeErrorCode errorCode) {
    var keyword = body.keyword;
    if (keyword != null) {
      errorReporter.atToken(
        keyword,
        errorCode,
        arguments: [keyword.lexeme],
      );
    }
  }

  /// Verify that the usage of the given 'this' is valid.
  ///
  /// See [CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS].
  void _checkForInvalidReferenceToThis(ThisExpression expression) {
    if (!_hasAccessToThis) {
      errorReporter.atNode(
        expression,
        CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS,
      );
    }
  }

  void _checkForLateFinalFieldWithConstConstructor(FieldDeclaration node) {
    if (node.isStatic) return;

    var variableList = node.fields;
    if (!variableList.isFinal) return;

    var lateKeyword = variableList.lateKeyword;
    if (lateKeyword == null) return;

    var enclosingClass = _enclosingClass;
    if (enclosingClass == null) {
      // The field is in an extension and should be handled elsewhere.
      return;
    }

    var hasGenerativeConstConstructor =
        _enclosingClass!.constructors.any((c) => c.isConst && !c.isFactory);
    if (!hasGenerativeConstConstructor) return;

    errorReporter.atToken(
      lateKeyword,
      CompileTimeErrorCode.LATE_FINAL_FIELD_WITH_CONST_CONSTRUCTOR,
    );
  }

  /// Verify that the elements of the given list [literal] are subtypes of the
  /// list's static type.
  ///
  /// See [CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE].
  void _checkForListElementTypeNotAssignable(ListLiteral literal) {
    // Determine the list's element type. We base this on the static type and
    // not the literal's type arguments because in strong mode, the type
    // arguments may be inferred.
    DartType listType = literal.typeOrThrow;
    assert(listType is InterfaceTypeImpl);

    List<DartType> typeArguments =
        (listType as InterfaceTypeImpl).typeArguments;
    assert(typeArguments.length == 1);

    DartType listElementType = typeArguments[0];

    // Check every list element.
    var verifier = LiteralElementVerifier(
      _typeProvider,
      typeSystem,
      errorReporter,
      this,
      forList: true,
      elementType: listElementType,
      featureSet: _featureSet!,
    );
    for (CollectionElement element in literal.elements) {
      verifier.verify(element);
    }
  }

  void _checkForMainFunction1(Token nameToken, Element declaredElement) {
    // We should only check exported declarations, i.e. top-level.
    if (declaredElement.enclosingElement3 is! CompilationUnitElement) {
      return;
    }

    if (declaredElement.displayName != 'main') {
      return;
    }

    if (declaredElement is! FunctionElement) {
      errorReporter.atToken(
        nameToken,
        CompileTimeErrorCode.MAIN_IS_NOT_FUNCTION,
      );
    }
  }

  void _checkForMainFunction2(FunctionDeclaration functionDeclaration) {
    if (functionDeclaration.name.lexeme != 'main') {
      return;
    }

    if (functionDeclaration.parent is! CompilationUnit) {
      return;
    }

    var parameterList = functionDeclaration.functionExpression.parameters;
    if (parameterList == null) {
      return;
    }

    var parameters = parameterList.parameters;
    var positional = parameters.where((e) => e.isPositional).toList();
    var requiredPositional =
        parameters.where((e) => e.isRequiredPositional).toList();

    if (requiredPositional.length > 2) {
      errorReporter.atToken(
        functionDeclaration.name,
        CompileTimeErrorCode.MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS,
      );
    }

    if (parameters.any((e) => e.isRequiredNamed)) {
      errorReporter.atToken(
        functionDeclaration.name,
        CompileTimeErrorCode.MAIN_HAS_REQUIRED_NAMED_PARAMETERS,
      );
    }

    if (positional.isNotEmpty) {
      var first = positional.first;
      var type = first.declaredElement!.type;
      var listOfString = _typeProvider.listType(_typeProvider.stringType);
      if (!typeSystem.isSubtypeOf(listOfString, type)) {
        errorReporter.atNode(
          first.notDefault.typeOrSelf,
          CompileTimeErrorCode.MAIN_FIRST_POSITIONAL_PARAMETER_TYPE,
        );
      }
    }
  }

  void _checkForMapTypeNotAssignable(SetOrMapLiteral literal) {
    // Determine the map's key and value types. We base this on the static type
    // and not the literal's type arguments because in strong mode, the type
    // arguments may be inferred.
    DartType mapType = literal.typeOrThrow;
    assert(mapType is InterfaceTypeImpl);

    List<DartType> typeArguments = (mapType as InterfaceTypeImpl).typeArguments;
    // It is possible for the number of type arguments to be inconsistent when
    // the literal is ambiguous and a non-map type was selected.
    // TODO(brianwilkerson): Unify this and _checkForSetElementTypeNotAssignable3
    //  to better handle recovery situations.
    if (typeArguments.length == 2) {
      DartType keyType = typeArguments[0];
      DartType valueType = typeArguments[1];

      var verifier = LiteralElementVerifier(
        _typeProvider,
        typeSystem,
        errorReporter,
        this,
        forMap: true,
        mapKeyType: keyType,
        mapValueType: valueType,
        featureSet: _featureSet!,
      );
      for (CollectionElement element in literal.elements) {
        verifier.verify(element);
      }
    }
  }

  /// Check to make sure that the given switch [statement] whose static type is
  /// an enum type either have a default case or include all of the enum
  /// constants.
  void _checkForMissingEnumConstantInSwitch(SwitchStatement statement) {
    if (_currentLibrary.featureSet.isEnabled(Feature.patterns)) {
      // Exhaustiveness checking cover this warning.
      return;
    }

    // TODO(brianwilkerson): This needs to be checked after constant values have
    // been computed.
    var expressionType = statement.expression.staticType;

    var hasCaseNull = false;
    if (expressionType is InterfaceType) {
      var enumElement = expressionType.element;
      if (enumElement is EnumElement) {
        var constantNames = enumElement.fields
            .where((field) => field.isEnumConstant)
            .map((field) => field.name)
            .toSet();

        for (var member in statement.members) {
          Expression? caseConstant;
          if (member is SwitchCase) {
            caseConstant = member.expression;
          } else if (member is SwitchPatternCase) {
            var guardedPattern = member.guardedPattern;
            if (guardedPattern.whenClause == null) {
              var pattern = guardedPattern.pattern.unParenthesized;
              if (pattern is ConstantPattern) {
                caseConstant = pattern.expression;
              }
            }
          }
          if (caseConstant != null) {
            var expression = caseConstant.unParenthesized;
            if (expression is NullLiteral) {
              hasCaseNull = true;
            } else {
              var constantName = _getConstantName(expression);
              constantNames.remove(constantName);
            }
          }
          if (member is SwitchDefault) {
            return;
          }
        }

        for (var constantName in constantNames) {
          int offset = statement.offset;
          int end = statement.rightParenthesis.end;
          errorReporter.atOffset(
            offset: offset,
            length: end - offset,
            errorCode: StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH,
            arguments: [constantName],
          );
        }

        if (typeSystem.isNullable(expressionType) && !hasCaseNull) {
          int offset = statement.offset;
          int end = statement.rightParenthesis.end;
          errorReporter.atOffset(
            offset: offset,
            length: end - offset,
            errorCode: StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH,
            arguments: ['null'],
          );
        }
      }
    }
  }

  /// Verify that the given mixin does not have an explicitly declared
  /// constructor. The [mixinName] is the node to report problem on. The
  /// [mixinElement] is the mixing to evaluate.
  ///
  /// See [CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR].
  bool _checkForMixinClassDeclaresConstructor(
      NamedType mixinName, InterfaceElement mixinElement) {
    for (ConstructorElement constructor in mixinElement.constructors) {
      if (!constructor.isSynthetic && !constructor.isFactory) {
        errorReporter.atNode(
          mixinName,
          CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR,
          arguments: [mixinElement.name],
        );
        return true;
      }
    }
    return false;
  }

  /// Verify that mixin classes must have 'Object' as their superclass and that
  /// they do not have a constructor.
  ///
  /// See [CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR],
  /// [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT].
  void _checkForMixinClassErrorCodes(
      NamedCompilationUnitMember node,
      List<ClassMember> members,
      NamedType? superclass,
      WithClause? withClause) {
    var element = node.declaredElement;
    if (element is ClassElementImpl && element.isMixinClass) {
      // Check that the class does not have a constructor.
      for (ClassMember member in members) {
        if (member is ConstructorDeclarationImpl) {
          if (!member.isSynthetic && member.factoryKeyword == null) {
            // Report errors on non-trivial generative constructors on mixin
            // classes.
            if (!member.isTrivial) {
              errorReporter.atNode(
                member.returnType,
                CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR,
                arguments: [element.name],
              );
            }
          }
        }
      }
      // Check that the class has 'Object' as their superclass.
      if (superclass != null && !superclass.typeOrThrow.isDartCoreObject) {
        errorReporter.atNode(
          superclass,
          CompileTimeErrorCode.MIXIN_CLASS_DECLARATION_EXTENDS_NOT_OBJECT,
          arguments: [element.name],
        );
      } else if (withClause != null &&
          !(element.isMixinApplication && withClause.mixinTypes.length < 2)) {
        errorReporter.atNode(
          withClause,
          CompileTimeErrorCode.MIXIN_CLASS_DECLARATION_EXTENDS_NOT_OBJECT,
          arguments: [element.name],
        );
      }
    }
  }

  /// Verify that the given mixin has the 'Object' superclass.
  ///
  /// The [mixinName] is the node to report problem on. The [mixinElement] is
  /// the mixing to evaluate.
  ///
  /// See [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT].
  bool _checkForMixinInheritsNotFromObject(
      NamedType mixinName, InterfaceElement mixinElement) {
    if (mixinElement is! ClassElement) {
      return false;
    }

    var mixinSupertype = mixinElement.supertype;
    if (mixinSupertype == null || mixinSupertype.isDartCoreObject) {
      var mixins = mixinElement.mixins;
      if (mixins.isEmpty ||
          mixinElement.isMixinApplication && mixins.length < 2) {
        return false;
      }
    }

    errorReporter.atNode(
      mixinName,
      CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT,
      arguments: [mixinElement.name],
    );
    return true;
  }

  /// Check that superclass constrains for the mixin type of [mixinName] at
  /// the [mixinIndex] position in the mixins list are satisfied by the
  /// [_enclosingClass], or a previous mixin.
  bool _checkForMixinSuperclassConstraints(
      int mixinIndex, NamedType mixinName) {
    InterfaceType mixinType = mixinName.type as InterfaceType;
    for (var constraint in mixinType.superclassConstraints) {
      var superType = _enclosingClass!.supertype as InterfaceTypeImpl;
      superType = superType.withNullability(NullabilitySuffix.none);

      bool isSatisfied = typeSystem.isSubtypeOf(superType, constraint);
      if (!isSatisfied) {
        for (int i = 0; i < mixinIndex && !isSatisfied; i++) {
          isSatisfied =
              typeSystem.isSubtypeOf(_enclosingClass!.mixins[i], constraint);
        }
      }
      if (!isSatisfied) {
        // This error can only occur if [mixinName] resolved to an actual mixin,
        // so we can safely rely on `mixinName.type` being non-`null`.
        errorReporter.atToken(
          mixinName.name2,
          CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
          arguments: [
            mixinName.type!,
            superType,
            constraint,
          ],
        );
        return true;
      }
    }
    return false;
  }

  /// Check that the superclass of the given [mixinElement] at the given
  /// [mixinIndex] in the list of mixins of [_enclosingClass] has concrete
  /// implementations of all the super-invoked members of the [mixinElement].
  bool _checkForMixinSuperInvokedMembers(int mixinIndex, NamedType mixinName,
      InterfaceElement mixinElement, InterfaceType mixinType) {
    var mixinElementImpl = mixinElement as MixinElementImpl;
    if (mixinElementImpl.superInvokedNames.isEmpty) {
      return false;
    }

    Uri mixinLibraryUri = mixinElement.librarySource.uri;
    for (var name in mixinElementImpl.superInvokedNames) {
      var nameObject = Name(mixinLibraryUri, name);

      var superMember = _inheritanceManager.getMember2(
          _enclosingClass!, nameObject,
          forMixinIndex: mixinIndex, concrete: true, forSuper: true);

      if (superMember == null) {
        var isSetter = name.endsWith('=');

        var errorCode = isSetter
            ? CompileTimeErrorCode
                .MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_SETTER
            : CompileTimeErrorCode
                .MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER;

        if (isSetter) {
          name = name.substring(0, name.length - 1);
        }

        errorReporter.atNode(
          mixinName,
          errorCode,
          arguments: [name],
        );
        return true;
      }

      var mixinMember =
          _inheritanceManager.getMember(mixinType, nameObject, forSuper: true);

      if (mixinMember != null) {
        var isCorrect = CorrectOverrideHelper(
          typeSystem: typeSystem,
          thisMember: superMember,
        ).isCorrectOverrideOf(
          superMember: mixinMember,
        );
        if (!isCorrect) {
          errorReporter.atNode(
            mixinName,
            CompileTimeErrorCode
                .MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE,
            arguments: [name, mixinMember.type, superMember.type],
          );
          return true;
        }
      }
    }
    return false;
  }

  /// Check for the declaration of a mixin from a library other than the current
  /// library that defines a private member that conflicts with a private name
  /// from the same library but from a superclass or a different mixin.
  void _checkForMixinWithConflictingPrivateMember(
      WithClause? withClause, NamedType? superclassName) {
    if (withClause == null) {
      return;
    }
    var declaredSupertype = superclassName?.type ?? _typeProvider.objectType;
    if (declaredSupertype is! InterfaceType) {
      return;
    }
    Map<LibraryElement, Map<String, String>> mixedInNames =
        <LibraryElement, Map<String, String>>{};

    /// Report an error and return `true` if the given [name] is a private name
    /// (which is defined in the given [library]) and it conflicts with another
    /// definition of that name inherited from the superclass.
    bool isConflictingName(
        String name, LibraryElement library, NamedType namedType) {
      if (Identifier.isPrivateName(name)) {
        Map<String, String> names = mixedInNames.putIfAbsent(library, () => {});
        var conflictingName = names[name];
        if (conflictingName != null) {
          if (name.endsWith('=')) {
            name = name.substring(0, name.length - 1);
          }
          errorReporter.atNode(
            namedType,
            CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION,
            arguments: [name, namedType.name2.lexeme, conflictingName],
          );
          return true;
        }
        names[name] = namedType.name2.lexeme;
        var inheritedMember = _inheritanceManager.getMember2(
          declaredSupertype.element,
          Name(library.source.uri, name),
          concrete: true,
        );
        if (inheritedMember != null) {
          if (name.endsWith('=')) {
            name = name.substring(0, name.length - 1);
          }
          // Inherited members are always contained inside named elements, so we
          // can safely assume `inheritedMember.enclosingElement3.name` is
          // non-`null`.
          errorReporter.atNode(
            namedType,
            CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION,
            arguments: [
              name,
              namedType.name2.lexeme,
              inheritedMember.enclosingElement3.name!
            ],
          );
          return true;
        }
      }
      return false;
    }

    for (NamedType mixinType in withClause.mixinTypes) {
      DartType type = mixinType.typeOrThrow;
      if (type is InterfaceType) {
        LibraryElement library = type.element.library;
        if (library != _currentLibrary) {
          for (PropertyAccessorElement accessor in type.accessors) {
            if (accessor.isStatic) {
              continue;
            }
            if (isConflictingName(accessor.name, library, mixinType)) {
              return;
            }
          }
          for (MethodElement method in type.methods) {
            if (method.isStatic) {
              continue;
            }
            if (isConflictingName(method.name, library, mixinType)) {
              return;
            }
          }
        }
      }
    }
  }

  /// Checks to ensure that the given native function [body] is in SDK code.
  ///
  /// See [ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE].
  void _checkForNativeFunctionBodyInNonSdkCode(NativeFunctionBody body) {
    if (!_isInSystemLibrary) {
      errorReporter.atNode(
        body,
        ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE,
      );
    }
  }

  /// Verify that the given instance creation [expression] invokes an existing
  /// constructor. The [constructorName] is the constructor name.
  /// The [namedType] is the name of the type defining the constructor.
  ///
  /// This method assumes that the instance creation was tested to be 'new'
  /// before being called.
  ///
  /// See [CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR].
  void _checkForNewWithUndefinedConstructor(
      InstanceCreationExpression expression,
      ConstructorName constructorName,
      NamedType namedType) {
    // OK if resolved
    if (constructorName.staticElement != null) {
      return;
    }
    DartType type = namedType.typeOrThrow;
    if (type is InterfaceType) {
      var element = type.element;
      if (element is EnumElement || element is MixinElement) {
        // We have already reported the error.
        return;
      }
    }
    // report as named or default constructor absence
    var name = constructorName.name;
    if (name != null) {
      errorReporter.atNode(
        name,
        CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR,
        arguments: [namedType.qualifiedName, name.name],
      );
    } else {
      errorReporter.atNode(
        constructorName,
        CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT,
        arguments: [namedType.qualifiedName],
      );
    }
  }

  /// Check that if the given class [element] implicitly calls default
  /// constructor of its superclass, there should be such default constructor -
  /// implicit or explicit.
  ///
  /// See [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT].
  void _checkForNoDefaultSuperConstructorImplicit(
    ClassElementImpl element,
    AugmentedClassElement augmented,
  ) {
    // do nothing if there is explicit constructor
    var constructors = augmented.constructors;
    if (!constructors[0].isSynthetic) {
      return;
    }
    // prepare super
    var superType = element.supertype;
    if (superType == null) {
      return;
    }
    var superElement = superType.element;
    // try to find default generative super constructor
    var superUnnamedConstructor = superElement.unnamedConstructor;
    if (superUnnamedConstructor != null) {
      if (superUnnamedConstructor.isFactory) {
        errorReporter.atElement(
          element,
          CompileTimeErrorCode.NON_GENERATIVE_IMPLICIT_CONSTRUCTOR,
          arguments: [
            superElement.name,
            element.name,
            superUnnamedConstructor,
          ],
        );
        return;
      }
      if (superUnnamedConstructor.isDefaultConstructor) {
        return;
      }
    }

    if (!_typeProvider.isNonSubtypableClass(superType.element)) {
      // Don't report this diagnostic for non-subtypable classes because the
      // real problem was already reported.
      errorReporter.atElement(
        element,
        CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT,
        arguments: [superType, element.displayName],
      );
    }
  }

  bool _checkForNoGenerativeConstructorsInSuperclass(NamedType? superclass) {
    var superType = _enclosingClass!.supertype;
    if (superType == null) {
      return false;
    }
    if (_enclosingClass!.constructors
        .every((constructor) => constructor.isFactory)) {
      // A class with no generative constructors *can* be extended if the
      // subclass has only factory constructors.
      return false;
    }
    var superElement = superType.element;
    if (superElement.constructors.isEmpty) {
      // Exclude empty constructor set, which indicates other errors occurred.
      return false;
    }
    if (superElement.constructors
        .every((constructor) => constructor.isFactory)) {
      // For `E extends Exception`, etc., this will never work, because it has
      // no generative constructors. State this clearly to users.
      errorReporter.atNode(
        superclass!,
        CompileTimeErrorCode.NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS,
        arguments: [_enclosingClass!.name, superElement.name],
      );
      return true;
    }
    return false;
  }

  void _checkForNonConstGenerativeEnumConstructor(ConstructorDeclaration node) {
    if (_enclosingClass is EnumElement &&
        node.constKeyword == null &&
        node.factoryKeyword == null) {
      errorReporter.atConstructorDeclaration(
        node,
        CompileTimeErrorCode.NON_CONST_GENERATIVE_ENUM_CONSTRUCTOR,
      );
    }
  }

  /// Verify the given map [literal] either:
  /// * has `const modifier`
  /// * has explicit type arguments
  /// * is not start of the statement
  ///
  /// See [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT].
  void _checkForNonConstMapAsExpressionStatement3(SetOrMapLiteral literal) {
    // "const"
    if (literal.constKeyword != null) {
      return;
    }
    // has type arguments
    if (literal.typeArguments != null) {
      return;
    }
    // prepare statement
    var statement = literal.thisOrAncestorOfType<ExpressionStatement>();
    if (statement == null) {
      return;
    }
    // OK, statement does not start with map
    if (!identical(statement.beginToken, literal.beginToken)) {
      return;
    }

    // TODO(srawlins): Add any tests showing this is reported.
    errorReporter.atNode(
      literal,
      CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT,
    );
  }

  void _checkForNonCovariantTypeParameterPositionInRepresentationType(
    ExtensionTypeDeclaration node,
    ExtensionTypeElement element,
  ) {
    var typeParameters = node.typeParameters?.typeParameters;
    if (typeParameters == null) {
      return;
    }

    var representationType = element.representation.type;

    for (var typeParameterNode in typeParameters) {
      var typeParameterElement = typeParameterNode.declaredFragment!.element;
      var nonCovariant = representationType.accept(
        NonCovariantTypeParameterPositionVisitor(
          [typeParameterElement],
          initialVariance: Variance.covariant,
        ),
      );
      if (nonCovariant) {
        errorReporter.atNode(
          typeParameterNode,
          CompileTimeErrorCode
              .NON_COVARIANT_TYPE_PARAMETER_POSITION_IN_REPRESENTATION_TYPE,
        );
      }
    }
  }

  void _checkForNonFinalFieldInEnum(FieldDeclaration node) {
    if (node.isStatic) return;

    var variableList = node.fields;
    if (variableList.isFinal) return;

    var enclosingClass = _enclosingClass;
    if (enclosingClass == null || enclosingClass is! EnumElement) {
      return;
    }

    errorReporter.atToken(
      variableList.variables.first.name,
      CompileTimeErrorCode.NON_FINAL_FIELD_IN_ENUM,
    );
  }

  /// Verify that the given method [declaration] of operator `[]=`, has `void`
  /// return type.
  ///
  /// See [CompileTimeErrorCode.NON_VOID_RETURN_FOR_OPERATOR].
  void _checkForNonVoidReturnTypeForOperator(MethodDeclaration declaration) {
    // check that []= operator
    if (declaration.name.lexeme != "[]=") {
      return;
    }
    // check return type
    var annotation = declaration.returnType;
    if (annotation != null) {
      DartType type = annotation.typeOrThrow;
      if (type is! VoidType) {
        errorReporter.atNode(
          annotation,
          CompileTimeErrorCode.NON_VOID_RETURN_FOR_OPERATOR,
        );
      }
    }
  }

  /// Verify the [namedType], used as the return type of a setter, is valid
  /// (either `null` or the type 'void').
  ///
  /// See [CompileTimeErrorCode.NON_VOID_RETURN_FOR_SETTER].
  void _checkForNonVoidReturnTypeForSetter(TypeAnnotation? namedType) {
    if (namedType != null) {
      DartType type = namedType.typeOrThrow;
      if (type is! VoidType) {
        errorReporter.atNode(
          namedType,
          CompileTimeErrorCode.NON_VOID_RETURN_FOR_SETTER,
        );
      }
    }
  }

  void _checkForNotInitializedNonNullableInstanceFields(
    FieldDeclaration fieldDeclaration,
  ) {
    if (fieldDeclaration.isStatic) return;
    var fields = fieldDeclaration.fields;

    if (fields.isLate) return;
    if (fields.isFinal) return;

    if (_isEnclosingClassFfiStruct) return;
    if (_isEnclosingClassFfiUnion) return;

    for (var field in fields.variables) {
      var fieldElement = field.declaredElement as FieldElement;
      if (fieldElement.isAbstract || fieldElement.isExternal) continue;
      if (field.initializer != null) continue;

      var type = fieldElement.type;
      if (!typeSystem.isPotentiallyNonNullable(type)) continue;

      errorReporter.atNode(
        field,
        CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD,
        arguments: [field.name.lexeme],
      );
    }
  }

  void _checkForNotInitializedNonNullableStaticField(FieldDeclaration node) {
    if (!node.isStatic) {
      return;
    }
    _checkForNotInitializedNonNullableVariable(node.fields, false);
  }

  void _checkForNotInitializedNonNullableVariable(
    VariableDeclarationList node,
    bool topLevel,
  ) {
    // Checked separately.
    if (node.isConst || (topLevel && node.isFinal)) {
      return;
    }

    if (node.isLate) {
      return;
    }

    var parent = node.parent;
    if (parent is FieldDeclaration) {
      if (parent.externalKeyword != null) {
        return;
      }
    } else if (parent is TopLevelVariableDeclaration) {
      if (parent.externalKeyword != null) {
        return;
      }
    }

    if (node.type == null) {
      return;
    }
    var type = node.type!.typeOrThrow;

    if (!typeSystem.isPotentiallyNonNullable(type)) {
      return;
    }

    for (var variable in node.variables) {
      if (variable.initializer == null) {
        errorReporter.atToken(
          variable.name,
          CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_VARIABLE,
          arguments: [variable.name.lexeme],
        );
      }
    }
  }

  /// Verify that all classes of the given [onClause] are valid.
  ///
  /// See [CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS],
  /// [CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS].
  bool _checkForOnClauseErrorCodes(MixinOnClause? onClause) {
    if (onClause == null) {
      return false;
    }
    bool problemReported = false;
    for (NamedType namedType in onClause.superclassConstraints) {
      DartType type = namedType.typeOrThrow;
      if (type is InterfaceType) {
        if (_checkForExtendsOrImplementsDisallowedClass(
            namedType,
            CompileTimeErrorCode
                .MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS)) {
          problemReported = true;
        } else {
          if (_checkForExtendsOrImplementsDeferredClass(
              namedType,
              CompileTimeErrorCode
                  .MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS)) {
            problemReported = true;
          }
        }
      }
    }
    return problemReported;
  }

  /// Verify the given operator-method [declaration], does not have an optional
  /// parameter.
  ///
  /// This method assumes that the method declaration was tested to be an
  /// operator declaration before being called.
  ///
  /// See [CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR].
  void _checkForOptionalParameterInOperator(MethodDeclaration declaration) {
    var parameterList = declaration.parameters;
    if (parameterList == null) {
      return;
    }

    NodeList<FormalParameter> formalParameters = parameterList.parameters;
    for (FormalParameter formalParameter in formalParameters) {
      if (formalParameter.isOptional) {
        errorReporter.atNode(
          formalParameter,
          CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR,
        );
      }
    }
  }

  /// Via informal specification: dart-lang/language/issues/4
  ///
  /// If e is an integer literal which is not the operand of a unary minus
  /// operator, then:
  ///   - If the context type is double, it is a compile-time error if the
  ///   numerical value of e is not precisely representable by a double.
  ///   Otherwise the static type of e is double and the result of evaluating e
  ///   is a double instance representing that value.
  ///   - Otherwise (the current behavior of e, with a static type of int).
  ///
  /// and
  ///
  /// If e is -n and n is an integer literal, then
  ///   - If the context type is double, it is a compile-time error if the
  ///   numerical value of n is not precisely representable by a double.
  ///   Otherwise the static type of e is double and the result of evaluating e
  ///   is the result of calling the unary minus operator on a double instance
  ///   representing the numerical value of n.
  ///   - Otherwise (the current behavior of -n)
  void _checkForOutOfRange(IntegerLiteralImpl node) {
    var source = node.literal.lexeme;
    if (node.beginToken.type == TokenType.INT_WITH_SEPARATORS ||
        node.beginToken.type == TokenType.HEXADECIMAL_WITH_SEPARATORS) {
      source = shared.stripSeparators(source);
    }
    bool isNegated = node.immediatelyNegated;

    bool treatedAsDouble = node.staticType == _typeProvider.doubleType;
    bool valid = treatedAsDouble
        ? IntegerLiteralImpl.isValidAsDouble(source)
        : IntegerLiteralImpl.isValidAsInteger(source, isNegated);

    if (!valid) {
      var lexeme = node.literal.lexeme;
      var messageArguments = [
        isNegated ? '-$lexeme' : lexeme,
        if (treatedAsDouble)
          // Suggest the nearest valid double (as a BigInt, for printing).
          // TODO(srawlins): Insert digit separators at the same positions as
          // the input. This should be tested code, and a shared impl when we
          // have an assist that adds digit separators to a number literal.
          BigInt.from(IntegerLiteralImpl.nearestValidDouble(source)).toString(),
      ];

      errorReporter.atNode(
        node,
        treatedAsDouble
            ? CompileTimeErrorCode.INTEGER_LITERAL_IMPRECISE_AS_DOUBLE
            : CompileTimeErrorCode.INTEGER_LITERAL_OUT_OF_RANGE,
        arguments: messageArguments,
      );
    }
  }

  /// Check that the given named optional [parameter] does not begin with '_'.
  void _checkForPrivateOptionalParameter(FormalParameter parameter) {
    // should be named parameter
    if (!parameter.isNamed) {
      return;
    }
    // name should start with '_'
    var name = parameter.name;
    if (name == null || name.isSynthetic || !name.lexeme.startsWith('_')) {
      return;
    }

    errorReporter.atToken(
      name,
      CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER,
    );
  }

  /// Check whether the given constructor [declaration] is the redirecting
  /// generative constructor and references itself directly or indirectly. The
  /// [constructorElement] is the constructor element.
  ///
  /// See [CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT].
  void _checkForRecursiveConstructorRedirect(ConstructorDeclaration declaration,
      ConstructorElement constructorElement) {
    // we check generative constructor here
    if (declaration.factoryKeyword != null) {
      return;
    }
    // try to find redirecting constructor invocation and analyze it for
    // recursion
    for (ConstructorInitializer initializer in declaration.initializers) {
      if (initializer is RedirectingConstructorInvocation) {
        if (_hasRedirectingFactoryConstructorCycle(constructorElement)) {
          errorReporter.atNode(
            initializer,
            CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT,
          );
        }
        return;
      }
    }
  }

  /// Check whether the given constructor [declaration] has redirected
  /// constructor and references itself directly or indirectly. The
  /// constructor [element] is the element introduced by the declaration.
  ///
  /// See [CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT].
  bool _checkForRecursiveFactoryRedirect(
      ConstructorDeclaration declaration, ConstructorElement element) {
    // prepare redirected constructor
    var redirectedConstructorNode = declaration.redirectedConstructor;
    if (redirectedConstructorNode == null) {
      return false;
    }
    // OK if no cycle
    if (!_hasRedirectingFactoryConstructorCycle(element)) {
      return false;
    }
    // report error
    errorReporter.atNode(
      redirectedConstructorNode,
      CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT,
    );
    return true;
  }

  /// Check that the given constructor [declaration] has a valid redirected
  /// constructor.
  void _checkForRedirectingConstructorErrorCodes(
      ConstructorDeclaration declaration) {
    // Check for default values in the parameters.
    var redirectedConstructor = declaration.redirectedConstructor;
    if (redirectedConstructor == null) {
      return;
    }
    for (FormalParameter parameter in declaration.parameters.parameters) {
      if (parameter is DefaultFormalParameter &&
          parameter.defaultValue != null) {
        errorReporter.atToken(
          parameter.name!,
          CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR,
        );
      }
    }
    var redirectedElement = redirectedConstructor.staticElement;
    _checkForRedirectToNonConstConstructor(
      declaration.declaredElement!,
      redirectedElement,
      redirectedConstructor,
    );
    var redirectedClass = redirectedElement?.enclosingElement3;
    if (redirectedClass is ClassElement &&
        redirectedClass.isAbstract &&
        redirectedElement != null &&
        !redirectedElement.isFactory) {
      String enclosingNamedType = _enclosingClass!.displayName;
      String constructorStrName = enclosingNamedType;
      if (declaration.name != null) {
        constructorStrName += ".${declaration.name!.lexeme}";
      }
      errorReporter.atNode(
        redirectedConstructor,
        CompileTimeErrorCode.REDIRECT_TO_ABSTRACT_CLASS_CONSTRUCTOR,
        arguments: [constructorStrName, redirectedClass.name],
      );
    }
    _checkForInvalidGenerativeConstructorReference(redirectedConstructor);
  }

  /// Check whether the redirecting constructor, [element], is const, and
  /// [redirectedElement], its redirectee, is not const.
  ///
  /// See [CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR].
  void _checkForRedirectToNonConstConstructor(
    ConstructorElement element,
    ConstructorElement? redirectedElement,
    SyntacticEntity errorEntity,
  ) {
    // This constructor is const, but it redirects to a non-const constructor.
    if (redirectedElement != null &&
        element.isConst &&
        !redirectedElement.isConst) {
      errorReporter.atEntity(
        errorEntity,
        CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR,
      );
    }
  }

  void _checkForReferenceBeforeDeclaration({
    required Token nameToken,
    required Element? element,
  }) {
    if (element != null &&
        _hiddenElements != null &&
        _hiddenElements!.contains(element)) {
      errorReporter.reportError(
        DiagnosticFactory().referencedBeforeDeclaration(
          errorReporter.source,
          nameToken: nameToken,
          element: element,
        ),
      );
    }
  }

  void _checkForRepeatedType(
    Set<InstanceElement> accumulatedElements,
    List<NamedType>? namedTypes,
    ErrorCode errorCode,
  ) {
    if (namedTypes == null) {
      return;
    }

    for (var namedType in namedTypes) {
      var type = namedType.type;
      if (type is InterfaceType) {
        var element = type.element;
        var added = accumulatedElements.add(element);
        if (!added) {
          errorReporter.atNode(
            namedType,
            errorCode,
            arguments: [element.name],
          );
        }
      }
    }
  }

  /// Check that the given rethrow [expression] is inside of a catch clause.
  ///
  /// See [CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH].
  void _checkForRethrowOutsideCatch(RethrowExpression expression) {
    if (_enclosingExecutable.catchClauseLevel == 0) {
      errorReporter.atNode(
        expression,
        CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH,
      );
    }
  }

  /// Check that if the given constructor [declaration] is generative, then
  /// it does not have an expression function body.
  ///
  /// See [CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR].
  void _checkForReturnInGenerativeConstructor(
      ConstructorDeclaration declaration) {
    // ignore factory
    if (declaration.factoryKeyword != null) {
      return;
    }
    // block body (with possible return statement) is checked elsewhere
    FunctionBody body = declaration.body;
    if (body is! ExpressionFunctionBody) {
      return;
    }

    errorReporter.atNode(
      body,
      CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR,
    );
  }

  /// Check that if a direct supertype of a node is sealed, then it must be in
  /// the same library.
  ///
  /// See [CompileTimeErrorCode.SEALED_CLASS_SUBTYPE_OUTSIDE_OF_LIBRARY].
  void _checkForSealedSupertypeOutsideOfLibrary(
      NamedType? superclass,
      WithClause? withClause,
      ImplementsClause? implementsClause,
      MixinOnClause? onClause) {
    void reportErrorsForSealedClassesAndMixins(List<NamedType> namedTypes) {
      for (NamedType namedType in namedTypes) {
        var type = namedType.type;
        if (type is InterfaceType) {
          var element = type.element;
          if (element is ClassElement &&
              element.isSealed &&
              element.library != _currentLibrary) {
            errorReporter.atNode(
              namedType,
              CompileTimeErrorCode.SEALED_CLASS_SUBTYPE_OUTSIDE_OF_LIBRARY,
              arguments: [element.name],
            );
          }
        }
      }
    }

    if (superclass != null) {
      reportErrorsForSealedClassesAndMixins([superclass]);
    }
    if (withClause != null) {
      reportErrorsForSealedClassesAndMixins(withClause.mixinTypes);
    }
    if (implementsClause != null) {
      reportErrorsForSealedClassesAndMixins(implementsClause.interfaces);
    }
    if (onClause != null) {
      reportErrorsForSealedClassesAndMixins(onClause.superclassConstraints);
    }
  }

  /// Verify that the elements in the given set [literal] are subtypes of the
  /// set's static type.
  ///
  /// See [CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE].
  void _checkForSetElementTypeNotAssignable3(SetOrMapLiteral literal) {
    // Determine the set's element type. We base this on the static type and
    // not the literal's type arguments because in strong mode, the type
    // arguments may be inferred.
    DartType setType = literal.typeOrThrow;
    assert(setType is InterfaceTypeImpl);

    List<DartType> typeArguments = (setType as InterfaceTypeImpl).typeArguments;
    // It is possible for the number of type arguments to be inconsistent when
    // the literal is ambiguous and a non-set type was selected.
    // TODO(brianwilkerson): Unify this and _checkForMapTypeNotAssignable3 to
    //  better handle recovery situations.
    if (typeArguments.length == 1) {
      DartType setElementType = typeArguments[0];

      // Check every set element.
      var verifier = LiteralElementVerifier(
        _typeProvider,
        typeSystem,
        errorReporter,
        this,
        forSet: true,
        elementType: setElementType,
        featureSet: _featureSet!,
      );
      for (CollectionElement element in literal.elements) {
        verifier.verify(element);
      }
    }
  }

  /// Check the given [typeReference] and that the [name] is not a reference to
  /// an instance member.
  ///
  /// See [CompileTimeErrorCode.STATIC_ACCESS_TO_INSTANCE_MEMBER].
  void _checkForStaticAccessToInstanceMember(
      InterfaceElement? typeReference, SimpleIdentifier name) {
    // OK, in comment
    if (_isInComment) {
      return;
    }
    // OK, target is not a type
    if (typeReference == null) {
      return;
    }
    // prepare member Element
    var element = name.staticElement;
    if (element is ExecutableElement) {
      // OK, static
      if (element.isStatic || element is ConstructorElement) {
        return;
      }
      errorReporter.atNode(
        name,
        CompileTimeErrorCode.STATIC_ACCESS_TO_INSTANCE_MEMBER,
        arguments: [name.name],
      );
    }
  }

  void _checkForThrowOfInvalidType(ThrowExpression node) {
    var expression = node.expression;
    var type = node.expression.typeOrThrow;

    if (!typeSystem.isAssignableTo(type, typeSystem.objectNone,
        strictCasts: strictCasts)) {
      errorReporter.atNode(
        expression,
        CompileTimeErrorCode.THROW_OF_INVALID_TYPE,
        arguments: [type],
      );
    }
  }

  /// Verify that the given [element] does not reference itself directly.
  /// If it does, report the error on the [node].
  ///
  /// See [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF].
  void _checkForTypeAliasCannotReferenceItself(
    Token nameToken,
    TypeAliasElementImpl element,
  ) {
    if (element.hasSelfReference) {
      errorReporter.atToken(
        nameToken,
        CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
      );
    }
  }

  /// Verify that the [type] is not a deferred type.
  ///
  /// See [CompileTimeErrorCode.TYPE_ANNOTATION_DEFERRED_CLASS].
  void _checkForTypeAnnotationDeferredClass(TypeAnnotation? type) {
    if (type is NamedType && type.isDeferred) {
      errorReporter.atNode(
        type,
        CompileTimeErrorCode.TYPE_ANNOTATION_DEFERRED_CLASS,
        arguments: [type.qualifiedName],
      );
    }
  }

  /// Check that none of the type [parameters] references itself in its bound.
  ///
  /// See [CompileTimeErrorCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND].
  void _checkForTypeParameterBoundRecursion(List<TypeParameter> parameters) {
    Map<TypeParameterElement, TypeParameter>? elementToNode;
    for (var parameter in parameters) {
      if (parameter.bound != null) {
        if (elementToNode == null) {
          elementToNode = {};
          for (var parameter in parameters) {
            elementToNode[parameter.declaredElement!] = parameter;
          }
        }

        TypeParameter? current = parameter;
        for (var step = 0; current != null; step++) {
          var boundNode = current.bound;
          if (boundNode is NamedType) {
            var boundType = boundNode.typeOrThrow;
            boundType = boundType.extensionTypeErasure;
            current = elementToNode[boundType.element];
          } else {
            current = null;
          }
          if (step == parameters.length) {
            var element = parameter.declaredElement!;
            // This error can only occur if there is a bound, so we can safely
            // assume `element.bound` is non-`null`.
            errorReporter.atToken(
              parameter.name,
              CompileTimeErrorCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND,
              arguments: [element.displayName, element.bound!],
            );
            break;
          }
        }
      }
    }
  }

  void _checkForTypeParameterReferencedByStatic({
    required Token name,
    required Element? element,
  }) {
    if (_enclosingExecutable.inStaticMethod || _isInStaticVariableDeclaration) {
      if (element is TypeParameterElement &&
          element.enclosingElement3 is InstanceElement) {
        // The class's type parameters are not in scope for static methods.
        // However all other type parameters are legal (e.g. the static method's
        // type parameters, or a local function's type parameters).
        errorReporter.atToken(
          name,
          CompileTimeErrorCode.TYPE_PARAMETER_REFERENCED_BY_STATIC,
        );
      }
    }
  }

  /// Check that if the given generative [constructor] has neither an explicit
  /// super constructor invocation nor a redirecting constructor invocation,
  /// that the superclass has a default generative constructor.
  ///
  /// See [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT],
  /// [CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR], and
  /// [CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT].
  void _checkForUndefinedConstructorInInitializerImplicit(
      ConstructorDeclaration constructor) {
    if (_enclosingClass == null) {
      return;
    }

    // Ignore if the constructor is not generative.
    if (constructor.factoryKeyword != null) {
      return;
    }

    // Ignore if the constructor is external. See
    // https://github.com/dart-lang/language/issues/869.
    if (constructor.externalKeyword != null) {
      return;
    }

    // Ignore if the constructor has either an implicit super constructor
    // invocation or a redirecting constructor invocation.
    for (ConstructorInitializer constructorInitializer
        in constructor.initializers) {
      if (constructorInitializer is SuperConstructorInvocation ||
          constructorInitializer is RedirectingConstructorInvocation) {
        return;
      }
    }

    // Check to see whether the superclass has a non-factory unnamed
    // constructor.
    var superType = _enclosingClass!.supertype;
    if (superType == null) {
      return;
    }
    var superElement = superType.element;

    if (superElement.constructors
        .every((constructor) => constructor.isFactory)) {
      // Already reported [NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS].
      return;
    }

    var superUnnamedConstructor = superElement.unnamedConstructor;
    if (superUnnamedConstructor == null) {
      errorReporter.atNode(
        constructor.returnType,
        CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
        arguments: [superElement.name],
      );
      return;
    }

    if (superUnnamedConstructor.isFactory) {
      errorReporter.atNode(
        constructor.returnType,
        CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR,
        arguments: [superUnnamedConstructor],
      );
      return;
    }

    var requiredPositionalParameterCount = superUnnamedConstructor.parameters
        .where((parameter) => parameter.isRequiredPositional)
        .length;
    var requiredNamedParameters = superUnnamedConstructor.parameters
        .where((parameter) => parameter.isRequiredNamed)
        .map((parameter) => parameter.name)
        .toSet();

    void reportError(ErrorCode errorCode, List<Object> arguments) {
      Identifier returnType = constructor.returnType;
      var name = constructor.name;
      int offset = returnType.offset;
      int length = (name != null ? name.end : returnType.end) - offset;
      errorReporter.atOffset(
        offset: offset,
        length: length,
        errorCode: errorCode,
        arguments: arguments,
      );
    }

    if (!_currentLibrary.featureSet.isEnabled(Feature.super_parameters)) {
      if (requiredPositionalParameterCount != 0 ||
          requiredNamedParameters.isNotEmpty) {
        reportError(
          CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT,
          [superType],
        );
      }
      return;
    }

    var superParametersResult = verifySuperFormalParameters(
      constructor: constructor,
      errorReporter: errorReporter,
    );
    requiredNamedParameters.removeAll(
      superParametersResult.namedArgumentNames,
    );

    if (requiredPositionalParameterCount >
            superParametersResult.positionalArgumentCount ||
        requiredNamedParameters.isNotEmpty) {
      reportError(
        CompileTimeErrorCode.IMPLICIT_SUPER_INITIALIZER_MISSING_ARGUMENTS,
        [superType],
      );
    }
  }

  void _checkForUnnecessaryNullAware(Expression target, Token operator,
      {_NullAwareElementOrMapEntryKind? nullAwareElementOrMapEntryKind}) {
    if (target is SuperExpression) {
      return;
    }

    ErrorCode errorCode;
    Token endToken = operator;
    List<Object> arguments = const [];
    if (operator.type == TokenType.QUESTION) {
      if (nullAwareElementOrMapEntryKind == null) {
        errorCode = StaticWarningCode.INVALID_NULL_AWARE_OPERATOR;
        endToken = operator.next!;
        arguments = ['?[', '['];
      } else {
        switch (nullAwareElementOrMapEntryKind) {
          case _NullAwareElementOrMapEntryKind.element:
            errorCode = StaticWarningCode.INVALID_NULL_AWARE_ELEMENT;
          case _NullAwareElementOrMapEntryKind.mapEntryKey:
            errorCode = StaticWarningCode.INVALID_NULL_AWARE_MAP_ENTRY_KEY;
          case _NullAwareElementOrMapEntryKind.mapEntryValue:
            errorCode = StaticWarningCode.INVALID_NULL_AWARE_MAP_ENTRY_VALUE;
        }
      }
    } else if (operator.type == TokenType.QUESTION_PERIOD) {
      errorCode = StaticWarningCode.INVALID_NULL_AWARE_OPERATOR;
      arguments = [operator.lexeme, '.'];
    } else if (operator.type == TokenType.QUESTION_PERIOD_PERIOD) {
      errorCode = StaticWarningCode.INVALID_NULL_AWARE_OPERATOR;
      arguments = [operator.lexeme, '..'];
    } else if (operator.type == TokenType.PERIOD_PERIOD_PERIOD_QUESTION) {
      errorCode = StaticWarningCode.INVALID_NULL_AWARE_OPERATOR;
      arguments = [operator.lexeme, '...'];
    } else if (operator.type == TokenType.BANG) {
      errorCode = StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION;
    } else {
      return;
    }

    /// If the operator is not valid because the target already makes use of a
    /// null aware operator, return the null aware operator from the target.
    Token? previousShortCircuitingOperator(Expression? target) {
      if (target is PropertyAccess) {
        var operator = target.operator;
        var type = operator.type;
        if (type == TokenType.QUESTION_PERIOD) {
          var realTarget = target.realTarget;
          return previousShortCircuitingOperator(realTarget) ?? operator;
        }
      } else if (target is IndexExpression) {
        if (target.question != null) {
          var realTarget = target.realTarget;
          return previousShortCircuitingOperator(realTarget) ?? target.question;
        }
      } else if (target is MethodInvocation) {
        var operator = target.operator;
        var type = operator?.type;
        if (type == TokenType.QUESTION_PERIOD) {
          var realTarget = target.realTarget;
          return previousShortCircuitingOperator(realTarget) ?? operator;
        }
      }
      return null;
    }

    var targetType = target.staticType;
    if (target is ExtensionOverride) {
      var arguments = target.argumentList.arguments;
      if (arguments.length == 1) {
        targetType = arguments[0].typeOrThrow;
      } else {
        return;
      }
    } else if (targetType == null) {
      if (target is Identifier) {
        var targetElement = target.staticElement;
        if (targetElement is InterfaceElement ||
            targetElement is ExtensionElement ||
            targetElement is TypeAliasElement) {
          errorReporter.atOffset(
            offset: operator.offset,
            length: endToken.end - operator.offset,
            errorCode: errorCode,
            arguments: arguments,
          );
        }
      }
      return;
    }

    if (typeSystem.isStrictlyNonNullable(targetType)) {
      if (errorCode == StaticWarningCode.INVALID_NULL_AWARE_OPERATOR) {
        var previousOperator = previousShortCircuitingOperator(target);
        if (previousOperator != null) {
          errorReporter.reportError(DiagnosticFactory()
              .invalidNullAwareAfterShortCircuit(
                  errorReporter.source,
                  operator.offset,
                  endToken.end - operator.offset,
                  arguments,
                  previousOperator));
          return;
        }
      }
      errorReporter.atOffset(
        offset: operator.offset,
        length: endToken.end - operator.offset,
        errorCode: errorCode,
        arguments: arguments,
      );
    }
  }

  /// Check that if the given [name] is a reference to a static member it is
  /// defined in the enclosing class rather than in a superclass.
  ///
  /// See
  /// [CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER].
  void _checkForUnqualifiedReferenceToNonLocalStaticMember(
      SimpleIdentifier name) {
    var element = name.writeOrReadElement;
    if (element == null || element is TypeParameterElement) {
      return;
    }

    var enclosingElement = element.enclosingElement3;
    if (enclosingElement == null) {
      return;
    }

    if (identical(enclosingElement.augmentedDeclaration, _enclosingClass)) {
      return;
    }
    if (enclosingElement is! InterfaceElement) {
      return;
    }
    if (element is ExecutableElement && !element.isStatic) {
      return;
    }
    if (element is MethodElement) {
      // Invalid methods are reported in
      // [MethodInvocationResolver._resolveReceiverNull].
      return;
    }
    if (_enclosingExtension != null) {
      errorReporter.atNode(
        name,
        CompileTimeErrorCode
            .UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
        arguments: [enclosingElement.displayName],
      );
    } else {
      errorReporter.atNode(
        name,
        CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
        arguments: [enclosingElement.displayName],
      );
    }
  }

  void _checkForValidField(FieldFormalParameter parameter) {
    var parent2 = parameter.parent?.parent;
    if (parent2 is! ConstructorDeclaration &&
        parent2?.parent is! ConstructorDeclaration) {
      return;
    }
    ParameterElement element = parameter.declaredElement!;
    if (element is FieldFormalParameterElement) {
      var fieldElement = element.field;
      if (fieldElement == null || fieldElement.isSynthetic) {
        errorReporter.atNode(
          parameter,
          CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD,
          arguments: [parameter.name.lexeme],
        );
      } else {
        var parameterElement = parameter.declaredElement!;
        if (parameterElement is FieldFormalParameterElementImpl) {
          DartType declaredType = parameterElement.type;
          DartType fieldType = fieldElement.type;
          if (fieldElement.isSynthetic) {
            errorReporter.atNode(
              parameter,
              CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD,
              arguments: [parameter.name.lexeme],
            );
          } else if (fieldElement.isStatic) {
            errorReporter.atNode(
              parameter,
              CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD,
              arguments: [parameter.name.lexeme],
            );
          } else if (!typeSystem.isSubtypeOf(declaredType, fieldType)) {
            errorReporter.atNode(
              parameter,
              CompileTimeErrorCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE,
              arguments: [declaredType, fieldType],
            );
          }
        } else {
          if (fieldElement.isSynthetic) {
            errorReporter.atNode(
              parameter,
              CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD,
              arguments: [parameter.name.lexeme],
            );
          } else if (fieldElement.isStatic) {
            errorReporter.atNode(
              parameter,
              CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD,
              arguments: [parameter.name.lexeme],
            );
          }
        }
      }
    }
//        else {
// TODO(jwren): Report error, constructor initializer variable is a top level element
// (Either here or in ErrorVerifier.checkForAllFinalInitializedErrorCodes)
//        }
  }

  /// Verify the given operator-method [declaration], has correct number of
  /// parameters.
  ///
  /// This method assumes that the method declaration was tested to be an
  /// operator declaration before being called.
  ///
  /// See [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR].
  bool _checkForWrongNumberOfParametersForOperator(
      MethodDeclaration declaration) {
    // prepare number of parameters
    var parameterList = declaration.parameters;
    if (parameterList == null) {
      return false;
    }
    int numParameters = parameterList.parameters.length;
    // prepare operator name
    var nameToken = declaration.name;
    var name = nameToken.lexeme;
    // check for exact number of parameters
    int expected = -1;
    if ("[]=" == name) {
      expected = 2;
    } else if ("<" == name ||
        ">" == name ||
        "<=" == name ||
        ">=" == name ||
        "==" == name ||
        "+" == name ||
        "/" == name ||
        "~/" == name ||
        "*" == name ||
        "%" == name ||
        "|" == name ||
        "^" == name ||
        "&" == name ||
        "<<" == name ||
        ">>" == name ||
        ">>>" == name ||
        "[]" == name) {
      expected = 1;
    } else if ("~" == name) {
      expected = 0;
    }
    if (expected != -1 && numParameters != expected) {
      errorReporter.atToken(
        nameToken,
        CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR,
        arguments: [name, expected, numParameters],
      );
      return true;
    } else if ("-" == name && numParameters > 1) {
      errorReporter.atToken(
        nameToken,
        CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS,
        arguments: [numParameters],
      );
      return true;
    }
    return false;
  }

  /// Verify that the given setter [parameterList] has only one required
  /// parameter. The [setterName] is the name of the setter to report problems
  /// on.
  ///
  /// This method assumes that the method declaration was tested to be a setter
  /// before being called.
  ///
  /// See [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER].
  void _checkForWrongNumberOfParametersForSetter(
      Token setterName, FormalParameterList? parameterList) {
    if (parameterList == null) {
      return;
    }

    NodeList<FormalParameter> parameters = parameterList.parameters;
    if (parameters.length != 1 || !parameters[0].isRequiredPositional) {
      errorReporter.atToken(
        setterName,
        CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER,
      );
    }
  }

  void _checkForWrongTypeParameterVarianceInField(FieldDeclaration node) {
    if (_enclosingClass != null) {
      for (var typeParameter in _enclosingClass!.typeParameters) {
        // TODO(kallentu): : Clean up TypeParameterElementImpl casting once
        // variance is added to the interface.
        if (!(typeParameter as TypeParameterElementImpl).isLegacyCovariant) {
          var fields = node.fields;
          var fieldElement = fields.variables.first.declaredElement!;
          var fieldName = fields.variables.first.name;
          Variance fieldVariance =
              typeParameter.computeVarianceInType(fieldElement.type);

          _checkForWrongVariancePosition(
              fieldVariance, typeParameter, fieldName);
          if (!fields.isFinal && node.covariantKeyword == null) {
            _checkForWrongVariancePosition(
                Variance.contravariant.combine(fieldVariance),
                typeParameter,
                fieldName);
          }
        }
      }
    }
  }

  void _checkForWrongTypeParameterVarianceInMethod(MethodDeclaration method) {
    // Only need to report errors for parameters with explicitly defined type
    // parameters in classes or mixins.
    if (_enclosingClass == null) {
      return;
    }

    for (var typeParameter in _enclosingClass!.typeParameters) {
      // TODO(kallentu): : Clean up TypeParameterElementImpl casting once
      // variance is added to the interface.
      if ((typeParameter as TypeParameterElementImpl).isLegacyCovariant) {
        continue;
      }

      var methodTypeParameters = method.typeParameters?.typeParameters;
      if (methodTypeParameters != null) {
        for (var methodTypeParameter in methodTypeParameters) {
          if (methodTypeParameter.bound == null) {
            continue;
          }
          var methodTypeParameterVariance = Variance.invariant.combine(
            typeParameter
                .computeVarianceInType(methodTypeParameter.bound!.typeOrThrow),
          );
          _checkForWrongVariancePosition(
              methodTypeParameterVariance, typeParameter, methodTypeParameter);
        }
      }

      var methodParameters = method.parameters?.parameters;
      if (methodParameters != null) {
        for (var methodParameter in methodParameters) {
          var methodParameterElement = methodParameter.declaredElement!;
          if (methodParameterElement.isCovariant) {
            continue;
          }
          var methodParameterVariance = Variance.contravariant.combine(
            typeParameter.computeVarianceInType(methodParameterElement.type),
          );
          _checkForWrongVariancePosition(
              methodParameterVariance, typeParameter, methodParameter);
        }
      }

      var returnType = method.returnType;
      if (returnType != null) {
        var methodReturnTypeVariance =
            typeParameter.computeVarianceInType(returnType.typeOrThrow);
        _checkForWrongVariancePosition(
            methodReturnTypeVariance, typeParameter, returnType);
      }
    }
  }

  void _checkForWrongTypeParameterVarianceInSuperinterfaces() {
    void checkOne(DartType? superInterface) {
      if (superInterface != null) {
        for (var typeParameter in _enclosingClass!.typeParameters) {
          // TODO(kallentu): : Clean up TypeParameterElementImpl casting once
          // variance is added to the interface.
          var typeParameterElementImpl =
              typeParameter as TypeParameterElementImpl;
          var superVariance =
              typeParameterElementImpl.computeVarianceInType(superInterface);
          // Let `D` be a class or mixin declaration, let `S` be a direct
          // superinterface of `D`, and let `X` be a type parameter declared by
          // `D`.
          // If `X` is an `out` type parameter, it can only occur in `S` in an
          // covariant or unrelated position.
          // If `X` is an `in` type parameter, it can only occur in `S` in an
          // contravariant or unrelated position.
          // If `X` is an `inout` type parameter, it can occur in `S` in any
          // position.
          if (!superVariance
              .greaterThanOrEqual(typeParameterElementImpl.variance)) {
            if (!typeParameterElementImpl.isLegacyCovariant) {
              errorReporter.atElement(
                typeParameter,
                CompileTimeErrorCode
                    .WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
                arguments: [
                  typeParameter.name,
                  typeParameterElementImpl.variance.keyword,
                  superVariance.keyword,
                  superInterface,
                ],
              );
            } else {
              errorReporter.atElement(
                typeParameter,
                CompileTimeErrorCode
                    .WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
                arguments: [typeParameter.name, superInterface],
              );
            }
          }
        }
      }
    }

    checkOne(_enclosingClass!.supertype);
    _enclosingClass!.interfaces.forEach(checkOne);
    _enclosingClass!.mixins.forEach(checkOne);

    var enclosingClass = _enclosingClass;
    if (enclosingClass is MixinElement) {
      enclosingClass.superclassConstraints.forEach(checkOne);
    }
  }

  /// Check for invalid variance positions in members of a class or mixin.
  ///
  /// Let `C` be a class or mixin declaration with type parameter `T`.
  /// If `T` is an `out` type parameter then `T` can only appear in covariant
  /// positions within the accessors and methods of `C`.
  /// If `T` is an `in` type parameter then `T` can only appear in contravariant
  /// positions within the accessors and methods of `C`.
  /// If `T` is an `inout` type parameter or a type parameter with no explicit
  /// variance modifier then `T` can appear in any variant position within the
  /// accessors and methods of `C`.
  ///
  /// Errors should only be reported in classes and mixins since those are the
  /// only components that allow explicit variance modifiers.
  void _checkForWrongVariancePosition(Variance variance,
      TypeParameterElement typeParameter, SyntacticEntity errorTarget) {
    TypeParameterElementImpl typeParameterImpl =
        typeParameter as TypeParameterElementImpl;
    if (!variance.greaterThanOrEqual(typeParameterImpl.variance)) {
      errorReporter.atEntity(
        errorTarget,
        CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_POSITION,
        arguments: [
          typeParameterImpl.variance.keyword,
          typeParameterImpl.name,
          variance.keyword
        ],
      );
    }
  }

  /// Verify that the current class does not have the same class in the
  /// 'extends' and 'implements' clauses.
  ///
  /// See [CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS].
  void _checkImplementsSuperClass(ImplementsClause? implementsClause) {
    if (implementsClause == null) {
      return;
    }

    var superElement = _enclosingClass!.supertype?.element;
    if (superElement == null) {
      return;
    }

    for (var interfaceNode in implementsClause.interfaces) {
      var type = interfaceNode.type;
      if (type is InterfaceType && type.element == superElement) {
        errorReporter.atNode(
          interfaceNode,
          CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS,
          arguments: [superElement],
        );
      }
    }
  }

  void _checkMixinAugmentationModifiers({
    required Token? augmentKeyword,
    required MixinDeclarationImpl augmentationNode,
    required MixinElementImpl augmentationElement,
  }) {
    if (augmentKeyword == null) {
      return;
    }

    var target = augmentationElement.augmentationTarget;
    if (target == null) {
      return;
    }

    var declaration = target.augmented.firstFragment;

    void singleModifier({
      required String modifierName,
      required bool declarationFlag,
      required Token? augmentationModifier,
    }) {
      if (declarationFlag) {
        if (augmentationModifier == null) {
          errorReporter.atToken(
            augmentKeyword,
            CompileTimeErrorCode.AUGMENTATION_MODIFIER_MISSING,
            arguments: [modifierName],
          );
        }
      } else {
        if (augmentationModifier != null) {
          errorReporter.atToken(
            augmentationModifier,
            CompileTimeErrorCode.AUGMENTATION_MODIFIER_EXTRA,
            arguments: [modifierName],
          );
        }
      }
    }

    singleModifier(
      modifierName: 'base',
      declarationFlag: declaration.isBase,
      augmentationModifier: augmentationNode.baseKeyword,
    );
  }

  /// Checks the class for problems with the superclass, mixins, or implemented
  /// interfaces.
  void _checkMixinInheritance(
      MixinElementImpl declarationElement,
      MixinDeclaration node,
      MixinOnClause? onClause,
      ImplementsClause? implementsClause) {
    // Only check for all of the inheritance logic around clauses if there
    // isn't an error code such as "Cannot implement double" already.
    if (!_checkForOnClauseErrorCodes(onClause) &&
        !_checkForImplementsClauseErrorCodes(implementsClause)) {
//      _checkForImplicitDynamicType(superclass);
      _checkForRepeatedType(
        libraryContext.setOfOn(declarationElement),
        onClause?.superclassConstraints,
        CompileTimeErrorCode.ON_REPEATED,
      );
      _checkForRepeatedType(
        libraryContext.setOfImplements(declarationElement),
        implementsClause?.interfaces,
        CompileTimeErrorCode.IMPLEMENTS_REPEATED,
      );
      _checkForConflictingGenerics(node);
      _checkForBaseClassOrMixinImplementedOutsideOfLibrary(implementsClause);
      _checkForFinalSupertypeOutsideOfLibrary(
          null, null, implementsClause, onClause);
      _checkForSealedSupertypeOutsideOfLibrary(
          null, null, implementsClause, onClause);
    }
  }

  /// Verify that the current class does not have the same class in the
  /// 'extends' and 'with' clauses.
  ///
  /// See [CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS].
  void _checkMixinsSuperClass(WithClause? withClause) {
    if (withClause == null) {
      return;
    }

    var superElement = _enclosingClass!.supertype?.element;
    if (superElement == null) {
      return;
    }

    for (var mixinNode in withClause.mixinTypes) {
      var type = mixinNode.type;
      if (type is InterfaceType && type.element == superElement) {
        errorReporter.atNode(
          mixinNode,
          CompileTimeErrorCode.MIXINS_SUPER_CLASS,
          arguments: [superElement],
        );
      }
    }
  }

  void _checkUseOfCovariantInParameters(FormalParameterList node) {
    var parent = node.parent;
    if (_enclosingClass != null && parent is MethodDeclaration) {
      // Either [parent] is a static method, in which case `EXTRANEOUS_MODIFIER`
      // is reported by the parser, or [parent] is an instance method, in which
      // case any use of `covariant` is legal.
      return;
    }

    if (_enclosingExtension != null) {
      // `INVALID_USE_OF_COVARIANT_IN_EXTENSION` is reported by the parser.
      return;
    }

    if (parent is FunctionExpression) {
      var parent2 = parent.parent;
      if (parent2 is FunctionDeclaration && parent2.parent is CompilationUnit) {
        // `EXTRANEOUS_MODIFIER` is reported by the parser, for library-level
        // functions.
        return;
      }
    }

    NodeList<FormalParameter> parameters = node.parameters;
    int length = parameters.length;
    for (int i = 0; i < length; i++) {
      var parameter = parameters[i].notDefault;
      var keyword = parameter.covariantKeyword;
      if (keyword != null) {
        errorReporter.atToken(
          keyword,
          CompileTimeErrorCode.INVALID_USE_OF_COVARIANT,
        );
      }
    }
  }

  void _checkUseOfDefaultValuesInParameters(FormalParameterList node) {
    var defaultValuesAreExpected = () {
      var parent = node.parent;
      if (parent is ConstructorDeclaration) {
        if (parent.externalKeyword != null) {
          return false;
        } else if (parent.factoryKeyword != null &&
            parent.redirectedConstructor != null) {
          return false;
        }
        return true;
      } else if (parent is FunctionExpression) {
        var parent2 = parent.parent;
        if (parent2 is FunctionDeclaration && parent2.externalKeyword != null) {
          return false;
        } else if (parent.body is NativeFunctionBody) {
          return false;
        }
        return true;
      } else if (parent is MethodDeclaration) {
        if (parent.isAbstract) {
          return false;
        } else if (parent.externalKeyword != null) {
          return false;
        } else if (parent.body is NativeFunctionBody) {
          return false;
        }
        return true;
      }
      return false;
    }();

    for (var parameter in node.parameters) {
      if (parameter is DefaultFormalParameter) {
        if (parameter.isRequiredNamed) {
          if (parameter.defaultValue != null) {
            var errorTarget = _parameterName(parameter) ?? parameter;
            errorReporter.atEntity(
              errorTarget,
              CompileTimeErrorCode.DEFAULT_VALUE_ON_REQUIRED_PARAMETER,
            );
          }
        } else if (defaultValuesAreExpected) {
          var parameterElement = parameter.declaredElement!;
          if (!parameterElement.hasDefaultValue) {
            var type = parameterElement.type;
            if (typeSystem.isPotentiallyNonNullable(type)) {
              var parameterName = _parameterName(parameter);
              var errorTarget = parameterName ?? parameter;
              if (parameterElement.hasRequired) {
                errorReporter.atEntity(
                  errorTarget,
                  CompileTimeErrorCode
                      .MISSING_DEFAULT_VALUE_FOR_PARAMETER_WITH_ANNOTATION,
                );
              } else {
                if (!_isWildcardSuperFormalPositionalParameter(parameter)) {
                  errorReporter.atEntity(
                    errorTarget,
                    parameterElement.isPositional
                        ? CompileTimeErrorCode
                            .MISSING_DEFAULT_VALUE_FOR_PARAMETER_POSITIONAL
                        : CompileTimeErrorCode
                            .MISSING_DEFAULT_VALUE_FOR_PARAMETER,
                    arguments: [parameterName?.lexeme ?? '?'],
                  );
                }
              }
            }
          }
        }
      }
    }
  }

  bool _computeThisAccessForFunctionBody(FunctionBody node) =>
      switch (node.parent) {
        ConstructorDeclaration(:var factoryKeyword) => factoryKeyword == null,
        MethodDeclaration(:var isStatic) => !isStatic,
        _ => _hasAccessToThis
      };

  /// Given an [expression] in a switch case whose value is expected to be an
  /// enum constant, return the name of the constant.
  String? _getConstantName(Expression expression) {
    // TODO(brianwilkerson): Convert this to return the element representing the
    // constant.
    if (expression is SimpleIdentifier) {
      return expression.name;
    } else if (expression is PrefixedIdentifier) {
      return expression.identifier.name;
    } else if (expression is PropertyAccess) {
      return expression.propertyName.name;
    }
    return null;
  }

  /// Return the name of the library that defines given [element].
  String _getLibraryName(Element? element) {
    if (element == null) {
      return '';
    }
    var library = element.library;
    if (library == null) {
      return '';
    }
    var name = element.name;
    if (name == null) {
      return '';
    }
    var imports = _currentUnit.withEnclosing
        .expand((fragment) => fragment.libraryImports)
        .toList();
    int count = imports.length;
    for (int i = 0; i < count; i++) {
      if (identical(imports[i].importedLibrary, library)) {
        return library.definingCompilationUnit.source.uri.toString();
      }
    }
    List<String> indirectSources = <String>[];
    for (var import in imports) {
      var importedLibrary = import.importedLibrary;
      if (importedLibrary != null) {
        if (import.namespace.get(name) == element) {
          indirectSources.add(
              importedLibrary.definingCompilationUnit.source.uri.toString());
        }
      }
    }
    int indirectCount = indirectSources.length;
    StringBuffer buffer = StringBuffer();
    buffer.write(library.definingCompilationUnit.source.uri.toString());
    if (indirectCount > 0) {
      buffer.write(" (via ");
      if (indirectCount > 1) {
        indirectSources.sort();
        buffer.write(indirectSources.quotedAndCommaSeparatedWithAnd);
      } else {
        buffer.write(indirectSources[0]);
      }
      buffer.write(")");
    }
    return buffer.toString();
  }

  /// Return `true` if the given [constructor] redirects to itself, directly or
  /// indirectly.
  bool _hasRedirectingFactoryConstructorCycle(ConstructorElement constructor) {
    Set<ConstructorElement> constructors = HashSet<ConstructorElement>();
    ConstructorElement? current = constructor;
    while (current != null) {
      if (constructors.contains(current)) {
        return identical(current, constructor);
      }
      constructors.add(current);
      current = current.redirectedConstructor?.declaration;
    }
    return false;
  }

  /// Returns `true` if the given [library] is the `dart:ffi` library.
  bool _isDartFfiLibrary(LibraryElement library) => library.name == 'dart.ffi';

  /// Return `true` if the given [identifier] is in a location where it is
  /// allowed to resolve to a static member of a supertype.
  bool _isUnqualifiedReferenceToNonLocalStaticMemberAllowed(
      SimpleIdentifier identifier) {
    if (identifier.inDeclarationContext()) {
      return true;
    }
    var parent = identifier.parent;
    if (parent is Annotation) {
      return identical(parent.constructorName, identifier);
    }
    if (parent is CommentReference) {
      return true;
    }
    if (parent is ConstructorName) {
      return identical(parent.name, identifier);
    }
    if (parent is MethodInvocation) {
      return identical(parent.methodName, identifier);
    }
    if (parent is PrefixedIdentifier) {
      return identical(parent.identifier, identifier);
    }
    if (parent is PropertyAccess) {
      return identical(parent.propertyName, identifier);
    }
    if (parent is SuperConstructorInvocation) {
      return identical(parent.constructorName, identifier);
    }
    return false;
  }

  /// Return `true` if the [importElement] is the internal library `dart:_wasm`
  /// and the current library is either `package:js/js.dart` or is in
  /// `package:ui`.
  bool _isWasm(LibraryImportElement importElement) {
    var importedUri = importElement.importedLibrary?.source.uri.toString();
    if (importedUri != 'dart:_wasm') {
      return false;
    }
    var importingUri = _currentLibrary.source.uri.toString();
    if (importingUri == 'package:js/js.dart') {
      return true;
    } else if (importingUri.startsWith('package:ui/')) {
      return true;
    }
    return false;
  }

  bool _isWildcardSuperFormalPositionalParameter(
          DefaultFormalParameter parameter) =>
      parameter.parameter is SuperFormalParameter &&
      parameter.isPositional &&
      parameter.name?.lexeme == '_' &&
      _currentLibrary.featureSet.isEnabled(Feature.wildcard_variables);

  /// Checks whether a `final`, `base` or `interface` modifier can be ignored.
  ///
  /// Checks whether a subclass in the current library
  /// can ignore a class modifier of a declaration in [superLibrary].
  ///
  /// Only true if the supertype library is a platform library, and
  /// either the current library is also a platform library,
  /// or the current library has a language version which predates
  /// class modifiers
  bool _mayIgnoreClassModifiers(LibraryElement superLibrary) {
    // Only modifiers in platform libraries can be ignored.
    if (!superLibrary.isInSdk) return false;

    // Modifiers in 'dart:ffi' can't be ignored in pre-feature code.
    if (_isDartFfiLibrary(superLibrary)) {
      return false;
    }

    // Other platform libraries can ignore modifiers.
    if (_currentLibrary.isInSdk) return true;

    // Libraries predating class modifiers can ignore platform modifiers.
    return !_currentLibrary.featureSet.isEnabled(Feature.class_modifiers);
  }

  /// Return the name of the [parameter], or `null` if the parameter does not
  /// have a name.
  Token? _parameterName(FormalParameter parameter) {
    if (parameter is NormalFormalParameter) {
      return parameter.name;
    } else if (parameter is DefaultFormalParameter) {
      return parameter.parameter.name;
    }
    return null;
  }

  void _reportMacroDiagnostics(MacroTargetElement element) {
    _MacroDiagnosticsReporter(
      libraryContext: libraryContext,
      errorReporter: errorReporter,
      element: element,
    ).report();
  }

  void _withEnclosingExecutable(
    ExecutableElement element,
    void Function() operation,
  ) {
    var current = _enclosingExecutable;
    try {
      _enclosingExecutable = EnclosingExecutableContext(element);
      _returnTypeVerifier.enclosingExecutable = _enclosingExecutable;
      operation();
    } finally {
      _enclosingExecutable = current;
      _returnTypeVerifier.enclosingExecutable = _enclosingExecutable;
    }
  }

  void _withHiddenElements(List<Statement> statements, void Function() f) {
    _hiddenElements = HiddenElements(_hiddenElements, statements);
    try {
      f();
    } finally {
      _hiddenElements = _hiddenElements!.outerElements;
    }
  }

  void _withHiddenElementsGuardedPattern(
      GuardedPatternImpl guardedPattern, void Function() f) {
    _hiddenElements =
        HiddenElements.forGuardedPattern(_hiddenElements, guardedPattern);
    try {
      f();
    } finally {
      _hiddenElements = _hiddenElements!.outerElements;
    }
  }

  /// Return [FieldElement]s that are declared in the [ClassDeclaration] with
  /// the given [constructor], but are not initialized.
  static List<FieldElement> computeNotInitializedFields(
      ConstructorDeclaration constructor) {
    Set<FieldElement> fields = <FieldElement>{};
    var classDeclaration = constructor.parent as ClassDeclaration;
    for (ClassMember fieldDeclaration in classDeclaration.members) {
      if (fieldDeclaration is FieldDeclaration) {
        for (VariableDeclaration field in fieldDeclaration.fields.variables) {
          if (field.initializer == null) {
            fields.add(field.declaredElement as FieldElement);
          }
        }
      }
    }

    List<FormalParameter> parameters = constructor.parameters.parameters;
    for (FormalParameter parameter in parameters) {
      parameter = parameter.notDefault;
      if (parameter is FieldFormalParameter) {
        var element = parameter.declaredElement as FieldFormalParameterElement;
        fields.remove(element.field);
      }
    }

    for (ConstructorInitializer initializer in constructor.initializers) {
      if (initializer is ConstructorFieldInitializer) {
        fields.remove(initializer.fieldName.staticElement);
      }
    }

    return fields.toList();
  }

  /// Return [FieldElement]s that are declared in the [ClassDeclaration] with
  /// the given [constructor], but are not initialized.
  static List<FieldElement2> computeNotInitializedFields2(
      ConstructorDeclaration constructor) {
    var fields = <FieldElement2>{};
    var classDeclaration = constructor.parent as ClassDeclaration;
    for (ClassMember fieldDeclaration in classDeclaration.members) {
      if (fieldDeclaration is FieldDeclaration) {
        for (VariableDeclaration field in fieldDeclaration.fields.variables) {
          if (field.initializer == null) {
            fields.add((field.declaredFragment as FieldFragment).element);
          }
        }
      }
    }

    List<FormalParameter> parameters = constructor.parameters.parameters;
    for (FormalParameter parameter in parameters) {
      parameter = parameter.notDefault;
      if (parameter is FieldFormalParameter) {
        var element =
            (parameter.declaredFragment as FieldFormalParameterFragment)
                .element;
        fields.remove(element.field2);
      }
    }

    for (ConstructorInitializer initializer in constructor.initializers) {
      if (initializer is ConstructorFieldInitializer) {
        fields.remove(initializer.fieldName.element);
      }
    }

    return fields.toList();
  }
}

/// A record of the elements that will be declared in some scope (block), but
/// are not yet declared.
class HiddenElements {
  /// The elements hidden in outer scopes, or `null` if this is the outermost
  /// scope.
  final HiddenElements? outerElements;

  /// A set containing the elements that will be declared in this scope, but are
  /// not yet declared.
  final Set<Element> _elements = HashSet<Element>();

  /// Initialize a newly created set of hidden elements to include all of the
  /// elements defined in the set of [outerElements] and all of the elements
  /// declared in the given [statements].
  HiddenElements(this.outerElements, List<Statement> statements) {
    _initializeElements(statements);
  }

  /// Initialize a newly created set of hidden elements to include all of the
  /// elements defined in the set of [outerElements] and all of the elements
  /// declared in the given [guardedPattern].
  HiddenElements.forGuardedPattern(
    this.outerElements,
    GuardedPatternImpl guardedPattern,
  ) {
    _elements.addAll(guardedPattern.variables.values.map((e) => e.asElement!));
  }

  /// Return `true` if this set of elements contains the given [element].
  bool contains(Element element) {
    if (_elements.contains(element)) {
      return true;
    } else if (outerElements != null) {
      return outerElements!.contains(element);
    }
    return false;
  }

  /// Record that the given [element] has been declared, so it is no longer
  /// hidden.
  void declare(Element element) {
    _elements.remove(element);
  }

  /// Initialize the list of elements that are not yet declared to be all of the
  /// elements declared somewhere in the given [statements].
  void _initializeElements(List<Statement> statements) {
    _elements.addAll(BlockScope.elementsInStatements(statements));
  }
}

/// Information to pass from from the defining unit to augmentations.
class LibraryVerificationContext {
  final duplicationDefinitionContext = DuplicationDefinitionContext();
  final LibraryFileKind libraryKind;
  final ConstructorFieldsVerifier constructorFieldsVerifier;
  final Map<FileState, FileAnalysis> files;

  /// A table mapping names to the exported elements.
  final Map<String, Element> _exportedElements = {};

  /// Elements referenced in `implements` clauses.
  /// Key: the declaration element.
  final Map<InstanceElement, Set<InstanceElement>> _setOfImplementsMap =
      Map.identity();

  /// Elements referenced in `on` clauses.
  /// Key: the declaration element.
  final Map<MixinElement, Set<InterfaceElement>> _setOfOnMaps = Map.identity();

  LibraryVerificationContext({
    required this.libraryKind,
    required this.constructorFieldsVerifier,
    required this.files,
  });

  _MacroSyntacticTypeAnnotationLocation? declarationByElement(Element element) {
    var unitElement = element.thisOrAncestorOfType<CompilationUnitElement>();
    if (unitElement == null) {
      return null;
    }

    var uri = unitElement.source.uri;
    var fileAnalysis = files.entries.firstWhereOrNull((entry) {
      return entry.key.uri == uri;
    })?.value;
    if (fileAnalysis == null) {
      return null;
    }

    var locator = DeclarationByElementLocator(element);
    fileAnalysis.unit.accept(locator);

    var node = locator.result;
    if (node == null) {
      return null;
    }

    return _MacroSyntacticTypeAnnotationLocation(
      fileAnalysis: fileAnalysis,
      entity: node,
    );
  }

  bool libraryCycleContains(Uri uri) {
    return libraryKind.libraryCycle.libraryUris.contains(uri);
  }

  Set<InstanceElement> setOfImplements(InstanceElement declaration) {
    return _setOfImplementsMap[declaration] ??= Set.identity();
  }

  Set<InterfaceElement> setOfOn(MixinElement declaration) {
    return _setOfOnMaps[declaration] ??= Set.identity();
  }
}

class _MacroDiagnosticsReporter {
  final LibraryVerificationContext libraryContext;
  final ErrorReporter errorReporter;
  final MacroTargetElement element;

  _MacroDiagnosticsReporter({
    required this.libraryContext,
    required this.errorReporter,
    required this.element,
  });

  void report() {
    _reportApplicationFromSameLibraryCycle();

    for (var diagnostic in element.macroDiagnostics) {
      switch (diagnostic) {
        case ArgumentMacroDiagnostic():
          _reportArgument(diagnostic);
        case DeclarationsIntrospectionCycleDiagnostic():
          _reportIntrospectionCycle(diagnostic);
        case ExceptionMacroDiagnostic():
          _reportException(diagnostic);
        case InvalidMacroTargetDiagnostic():
          _reportInvalidTarget(diagnostic);
        case MacroDiagnostic():
          _reportCustom(diagnostic);
        case NotAllowedDeclarationDiagnostic():
          _reportNotAllowedDeclaration(diagnostic);
      }
    }
  }

  DiagnosticMessage _convertMessage(MacroDiagnosticMessage object) {
    var target = object.target;
    switch (target) {
      case ApplicationMacroDiagnosticTarget():
        var node = element.annotationAst(target.annotationIndex);
        return DiagnosticMessageImpl(
          filePath: element.source!.fullName,
          length: node.length,
          message: object.message,
          offset: node.offset,
          url: null,
        );
      case ElementMacroDiagnosticTarget():
        var element = target.element;
        return DiagnosticMessageImpl(
          filePath: element.source!.fullName,
          length: element.nameLength,
          message: object.message,
          offset: element.nameOffset,
          url: null,
        );
      case TypeAnnotationMacroDiagnosticTarget():
        // TODO(scheglov): Handle this case.
        throw UnimplementedError();
      case ElementAnnotationMacroDiagnosticTarget():
        // TODO(scheglov): Handle this case.
        throw UnimplementedError();
    }
  }

  void _reportApplicationFromSameLibraryCycle() {
    for (var annotation in element.metadata) {
      var element = annotation.element;
      if (element is! ConstructorElementImpl) continue;

      var macroElement = element.enclosingElement3;
      if (macroElement is! ClassElementImpl) continue;
      if (!macroElement.isMacro) continue;

      var macroUri = macroElement.library.source.uri;
      if (!libraryContext.libraryCycleContains(macroUri)) continue;

      errorReporter.atNode(
        _annotationNameIdentifier(annotation),
        CompileTimeErrorCode.MACRO_DEFINITION_APPLICATION_SAME_LIBRARY_CYCLE,
        arguments: [
          macroElement.name,
        ],
      );
    }
  }

  void _reportArgument(ArgumentMacroDiagnostic diagnostic) {
    var annotation = element.annotationAst(diagnostic.annotationIndex);
    var arguments = annotation.arguments!.arguments;
    errorReporter.atNode(
      arguments[diagnostic.argumentIndex],
      CompileTimeErrorCode.MACRO_APPLICATION_ARGUMENT_ERROR,
      arguments: [diagnostic.message],
    );
  }

  void _reportCustom(MacroDiagnostic diagnostic) {
    var errorCode = switch (diagnostic.severity) {
      macro.Severity.info => HintCode.MACRO_INFO,
      macro.Severity.warning => WarningCode.MACRO_WARNING,
      macro.Severity.error => CompileTimeErrorCode.MACRO_ERROR,
    };

    var contextMessages =
        diagnostic.contextMessages.map(_convertMessage).toList();

    var target = diagnostic.message.target;
    switch (target) {
      case ApplicationMacroDiagnosticTarget():
        var node = element.annotationAst(target.annotationIndex);
        errorReporter.reportError(
          AnalysisError.forValues(
            source: element.source!,
            offset: node.offset,
            length: node.length,
            errorCode: errorCode,
            message: diagnostic.message.message,
            correctionMessage: diagnostic.correctionMessage,
            contextMessages: contextMessages,
          ),
        );
      case ElementMacroDiagnosticTarget():
        errorReporter.reportError(
          AnalysisError.forValues(
            source: target.element.source!,
            offset: target.element.nameOffset,
            length: target.element.nameLength,
            errorCode: errorCode,
            message: diagnostic.message.message,
            correctionMessage: diagnostic.correctionMessage,
            contextMessages: contextMessages,
          ),
        );
      case ElementAnnotationMacroDiagnosticTarget():
        var location = libraryContext.declarationByElement(
          target.element,
        );
        if (location == null) {
          return;
        }
        var node = target.element.annotationAst(target.annotationIndex);
        location.fileAnalysis.errorReporter.reportError(
          AnalysisError.forValues(
            source: target.element.source!,
            offset: node.offset,
            length: node.length,
            errorCode: errorCode,
            message: diagnostic.message.message,
            correctionMessage: diagnostic.correctionMessage,
            contextMessages: contextMessages,
          ),
        );
      case TypeAnnotationMacroDiagnosticTarget():
        var nodeLocation = _MacroTypeAnnotationLocationConverter(
          libraryVerificationContext: libraryContext,
        ).convert(target.location);
        var fileAnalysis = nodeLocation?.fileAnalysis;
        var errorEntity = nodeLocation?.entity;
        if (fileAnalysis != null && errorEntity != null) {
          fileAnalysis.errorReporter.reportError(
            AnalysisError.forValues(
              source: fileAnalysis.element.source,
              offset: errorEntity.offset,
              length: errorEntity.length,
              errorCode: errorCode,
              message: diagnostic.message.message,
              correctionMessage: diagnostic.correctionMessage,
              contextMessages: contextMessages,
            ),
          );
        }
    }
  }

  void _reportException(ExceptionMacroDiagnostic diagnostic) {
    errorReporter.atNode(
      element.annotationAst(diagnostic.annotationIndex),
      CompileTimeErrorCode.MACRO_INTERNAL_EXCEPTION,
      arguments: [
        diagnostic.message,
        diagnostic.stackTrace,
      ],
    );
  }

  void _reportIntrospectionCycle(
    DeclarationsIntrospectionCycleDiagnostic diagnostic,
  ) {
    var messages = diagnostic.components.map<DiagnosticMessage>(
      (component) {
        var target = _macroAnnotationNameIdentifier(
          element: component.element,
          annotationIndex: component.annotationIndex,
        );
        var introspectedName = component.introspectedElement.name;
        return DiagnosticMessageImpl(
          filePath: component.element.source!.fullName,
          length: target.length,
          message: "The macro application introspects '$introspectedName'.",
          offset: target.offset,
          url: null,
        );
      },
    ).toList();

    errorReporter.atNode(
      _macroAnnotationNameIdentifier(
        element: element,
        annotationIndex: diagnostic.annotationIndex,
      ),
      CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE,
      arguments: [diagnostic.introspectedElement.name!],
      contextMessages: messages,
    );
  }

  void _reportInvalidTarget(InvalidMacroTargetDiagnostic diagnostic) {
    errorReporter.atNode(
      element.annotationAst(diagnostic.annotationIndex),
      CompileTimeErrorCode.INVALID_MACRO_APPLICATION_TARGET,
      arguments: [
        diagnostic.supportedKinds.commaSeparatedWithOr,
      ],
    );
  }

  void _reportNotAllowedDeclaration(
    NotAllowedDeclarationDiagnostic diagnostic,
  ) {
    errorReporter.atNode(
      element.annotationAst(diagnostic.annotationIndex),
      CompileTimeErrorCode.MACRO_NOT_ALLOWED_DECLARATION,
      arguments: [
        diagnostic.phase.name,
        diagnostic.nodeRanges
            .map((r) => '(${r.offset}, ${r.length})')
            .join(' '),
        diagnostic.code.trimRight(),
      ],
    );
  }

  static SimpleIdentifier _annotationNameIdentifier(
    ElementAnnotationImpl annotation,
  ) {
    var fullName = annotation.annotationAst.name;
    if (fullName is PrefixedIdentifierImpl) {
      return fullName.identifier;
    } else {
      return fullName as SimpleIdentifierImpl;
    }
  }

  static SimpleIdentifier _macroAnnotationNameIdentifier({
    required ElementImpl element,
    required int annotationIndex,
  }) {
    var annotationNode = element.annotationAst(annotationIndex);
    var fullName = annotationNode.name;
    if (fullName is PrefixedIdentifierImpl) {
      return fullName.identifier;
    } else {
      return fullName as SimpleIdentifierImpl;
    }
  }
}

class _MacroSyntacticTypeAnnotationLocation {
  final FileAnalysis fileAnalysis;

  /// Usually a [AstNode], sometimes [Token] if the type is omitted.
  final SyntacticEntity entity;

  _MacroSyntacticTypeAnnotationLocation({
    required this.fileAnalysis,
    required this.entity,
  });

  _MacroSyntacticTypeAnnotationLocation next(SyntacticEntity entity) {
    return _MacroSyntacticTypeAnnotationLocation(
      fileAnalysis: fileAnalysis,
      entity: entity,
    );
  }
}

class _MacroTypeAnnotationLocationConverter {
  final LibraryVerificationContext libraryVerificationContext;

  _MacroTypeAnnotationLocationConverter({
    required this.libraryVerificationContext,
  });

  /// Returns the syntactic location for the offset independent [location];
  _MacroSyntacticTypeAnnotationLocation? convert(
    TypeAnnotationLocation location,
  ) {
    switch (location) {
      case AliasedTypeLocation():
        return _aliasedType(location);
      case ElementTypeLocation():
        var element = location.element;
        return libraryVerificationContext.declarationByElement(element);
      case ExtendsClauseTypeLocation():
        return _extendsClause(location);
      case FormalParameterTypeLocation():
        return _formalParameter(location);
      case ListIndexTypeLocation():
        return _listIndex(location);
      case RecordNamedFieldTypeLocation():
        return _recordNamedField(location);
      case RecordPositionalFieldTypeLocation():
        return _recordPositionalField(location);
      case ReturnTypeLocation():
        return _returnType(location);
      case VariableTypeLocation():
        return _variableType(location);
      default:
        throw UnimplementedError('${location.runtimeType}');
    }
  }

  _MacroSyntacticTypeAnnotationLocation? _aliasedType(
    AliasedTypeLocation location,
  ) {
    var nodeLocation = convert(location.parent);
    if (nodeLocation == null) {
      return null;
    }
    var node = nodeLocation.entity;
    switch (node) {
      case GenericTypeAlias():
        return nodeLocation.next(node.type);
      default:
        throw UnimplementedError('${node.runtimeType}');
    }
  }

  _MacroSyntacticTypeAnnotationLocation? _extendsClause(
    ExtendsClauseTypeLocation location,
  ) {
    var nodeLocation = convert(location.parent);
    if (nodeLocation == null) {
      return null;
    }
    var node = nodeLocation.entity;
    switch (node) {
      case ClassDeclaration():
        var next = node.extendsClause!.superclass;
        return nodeLocation.next(next);
      default:
        throw UnimplementedError('${node.runtimeType}');
    }
  }

  _MacroSyntacticTypeAnnotationLocation? _formalParameter(
    FormalParameterTypeLocation location,
  ) {
    var nodeLocation = convert(location.parent);
    if (nodeLocation == null) {
      return null;
    }
    var node = nodeLocation.entity;
    switch (node) {
      case ConstructorDeclaration():
        var parameterList = node.parameters;
        var next = parameterList.parameters[location.index];
        return nodeLocation.next(next);
      case FunctionDeclaration():
        var parameterList = node.functionExpression.parameters;
        var next = parameterList!.parameters[location.index];
        return nodeLocation.next(next);
      case GenericFunctionType():
        var parameterList = node.parameters;
        var parameter = parameterList.parameters[location.index];
        parameter = parameter.notDefault;
        return nodeLocation.next(parameter.typeOrSelf);
      case MethodDeclaration():
        var parameterList = node.parameters;
        var next = parameterList!.parameters[location.index];
        return nodeLocation.next(next);
      default:
        throw UnimplementedError('${node.runtimeType}');
    }
  }

  _MacroSyntacticTypeAnnotationLocation? _listIndex(
    ListIndexTypeLocation location,
  ) {
    var nodeLocation = convert(location.parent);
    if (nodeLocation == null) {
      return null;
    }
    var node = nodeLocation.entity;
    switch (node) {
      case NamedType():
        var argument = node.typeArguments?.arguments[location.index];
        if (argument == null) {
          return null;
        }
        return nodeLocation.next(argument);
      default:
        throw UnimplementedError('${node.runtimeType}');
    }
  }

  _MacroSyntacticTypeAnnotationLocation? _recordNamedField(
    RecordNamedFieldTypeLocation location,
  ) {
    var nodeLocation = convert(location.parent);
    if (nodeLocation == null) {
      return null;
    }
    var node = nodeLocation.entity;
    switch (node) {
      case RecordTypeAnnotation():
        var field = node.namedFields?.fields[location.index].type;
        if (field == null) {
          return null;
        }
        return nodeLocation.next(field);
      default:
        throw UnimplementedError('${node.runtimeType}');
    }
  }

  _MacroSyntacticTypeAnnotationLocation? _recordPositionalField(
    RecordPositionalFieldTypeLocation location,
  ) {
    var nodeLocation = convert(location.parent);
    if (nodeLocation == null) {
      return null;
    }
    var node = nodeLocation.entity;
    switch (node) {
      case RecordTypeAnnotation():
        var field = node.positionalFields[location.index];
        return nodeLocation.next(field);
      default:
        throw UnimplementedError('${node.runtimeType}');
    }
  }

  _MacroSyntacticTypeAnnotationLocation? _returnType(
    ReturnTypeLocation location,
  ) {
    var nodeLocation = convert(location.parent);
    if (nodeLocation == null) {
      return null;
    }
    var node = nodeLocation.entity;
    switch (node) {
      case FunctionDeclaration():
        var next = node.returnType ?? node.name;
        return nodeLocation.next(next);
      case GenericFunctionType():
        var next = node.returnType ?? node;
        return nodeLocation.next(next);
      case MethodDeclaration():
        var next = node.returnType ?? node.name;
        return nodeLocation.next(next);
      default:
        throw UnimplementedError('${node.runtimeType}');
    }
  }

  _MacroSyntacticTypeAnnotationLocation? _variableType(
    VariableTypeLocation location,
  ) {
    var nodeLocation = convert(location.parent);
    if (nodeLocation == null) {
      return null;
    }
    var node = nodeLocation.entity;
    if (node is DefaultFormalParameter) {
      node = node.parameter;
    }
    var parent = node.ifTypeOrNull<AstNode>()?.parent;
    switch (node) {
      case FieldFormalParameter():
        var next = node.type ?? node.name;
        return nodeLocation.next(next);
      case SimpleFormalParameter():
        var next = node.type ?? node.name;
        if (next == null) {
          return null;
        }
        return nodeLocation.next(next);
      case SuperFormalParameter():
        var next = node.type ?? node.name;
        return nodeLocation.next(next);
      case VariableDeclaration():
        if (parent is VariableDeclarationList) {
          var next = parent.type ?? node.name;
          return nodeLocation.next(next);
        }
    }
    throw UnimplementedError(
      '${node.runtimeType} ${parent.runtimeType}',
    );
  }
}

/// Signals the kind of the null-aware element or entry observed in list, set,
/// or map literals.
enum _NullAwareElementOrMapEntryKind { element, mapEntryKey, mapEntryValue }

/// Recursively visits a type annotation, looking uninstantiated bounds.
class _UninstantiatedBoundChecker extends RecursiveAstVisitor<void> {
  final ErrorReporter _errorReporter;

  _UninstantiatedBoundChecker(this._errorReporter);

  @override
  void visitNamedType(NamedType node) {
    var typeArgs = node.typeArguments;
    if (typeArgs != null) {
      typeArgs.accept(this);
      return;
    }

    var element = node.element;
    if (element is TypeParameterizedElement && !element.isSimplyBounded) {
      // TODO(srawlins): Don't report this if TYPE_ALIAS_CANNOT_REFERENCE_ITSELF
      //  has been reported.
      _errorReporter.atNode(
        node,
        CompileTimeErrorCode.NOT_INSTANTIATED_BOUND,
      );
    }
  }
}
