// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library kernel.checks;

import 'ast.dart';
import 'target/targets.dart';
import 'transformations/flags.dart';
import 'type_environment.dart' show StatefulStaticTypeContext, TypeEnvironment;

/// Stages at which verification can occur.
///
/// These can be used to enforce different invariants during different stages
/// of the compilation.
enum VerificationStage {
  /// Verification after the outline compilation.
  outline,

  /// Verification after the body, aka full, compilation, but before pre-
  /// constant evaluation transformations have been performed.
  beforePreConstantEvaluationTransformations,

  /// Verification after pre- constant evaluation transformations have been
  /// performed but before constant evaluation.
  beforeConstantEvaluation,

  /// Verification after constant evaluation but before modular transformations
  /// have been performed.
  afterConstantEvaluation,

  /// Verification after modular transformations have been performed.
  ///
  /// This is final stage of a normal compilation.
  afterModularTransformations,

  /// Verification after global transformations have been performed.
  ///
  /// The global transformation is an additional step performed by some
  /// backends which is not triggered by the front end compilation itself.
  afterGlobalTransformations,
  ;

  bool operator <(VerificationStage other) => index < other.index;
  bool operator <=(VerificationStage other) => index <= other.index;
  bool operator >(VerificationStage other) => index > other.index;
  bool operator >=(VerificationStage other) => index >= other.index;
}

/// Interface that defines how the AST is verified.
class Verification {
  const Verification();

  /// Returns `true` if [node] is allowed to have no file offset.
  bool allowNoFileOffset(VerificationStage stage, TreeNode node) {
    return node is Library;
  }

  /// Returns `true` if [node] is allowed to have location with a file offset
  /// that is not in the range of the enclosing file.
  bool allowInvalidLocation(VerificationStage stage, TreeNode node) {
    return false;
  }
}

void verifyComponent(
    Target target, VerificationStage stage, Component component,
    {bool skipPlatform = false,
    bool Function(Library library)? librarySkipFilter}) {
  VerifyingVisitor.check(target, stage, component,
      skipPlatform: skipPlatform, librarySkipFilter: librarySkipFilter);
}

class VerificationErrorListener {
  const VerificationErrorListener();

  void reportError(String details,
      {required TreeNode? node,
      required Uri? problemUri,
      required int? problemOffset,
      required TreeNode? context,
      required TreeNode? origin}) {
    throw new VerificationError(context, node, details);
  }
}

class VerificationError {
  final TreeNode? context;

  final TreeNode? node;

  final String details;

  VerificationError(this.context, this.node, this.details);

  @override
  String toString() {
    Location? location;
    try {
      location = node?.location ?? context?.location;
    } catch (_) {
      // TODO(ahe): Fix the compiler instead.
    }
    if (location != null) {
      String file = location.file.toString();
      return "$file:${location.line}:${location.column}: Verification error:"
          " $details";
    } else {
      return "Verification error: $details\n"
          "Context: '$context'.\n"
          "Node: '$node'.";
    }
  }
}

enum TypedefState { Done, BeingChecked }

/// Checks that a kernel component is well-formed.
///
/// This does not include any kind of type checking.
class VerifyingVisitor extends RecursiveResultVisitor<void> {
  final Target target;

  Uri? fileUri;

  final VerificationErrorListener listener;

  final List<TreeNode> treeNodeStack = <TreeNode>[];
  final bool skipPlatform;
  final bool Function(Library library)? librarySkipFilter;

  final Set<Class> classes = new Set<Class>();
  final Set<Typedef> typedefs = new Set<Typedef>();
  Set<TypeParameter> typeParametersInScope = new Set<TypeParameter>();
  Set<StructuralParameter> structuralParametersInScope =
      new Set<StructuralParameter>();
  Set<ExpressionVariable> variableDeclarationsInScope =
      new Set<ExpressionVariable>();
  final List<ExpressionVariable> variableStack = <ExpressionVariable>[];
  final Map<Typedef, TypedefState> typedefState = <Typedef, TypedefState>{};
  final Set<Constant> seenConstants = <Constant>{};

  Map<Reference, ExtensionMemberDescriptor>? _extensionsMembers;
  Map<Reference, ExtensionTypeMemberDescriptor>? _extensionTypeMembers;

  bool classTypeParametersAreInScope = false;

  /// The compilation stage at which this verification is performed.
  final VerificationStage stage;

  AsyncMarker currentAsyncMarker = AsyncMarker.Sync;

  bool inCatchBlock = false;

  bool inUnevaluatedConstant = false;

  bool inConstant = false;

  Library? currentLibrary;

  Member? currentMember;

  Class? currentClass;

  Extension? currentExtension;

  ExtensionTypeDeclaration? currentExtensionTypeDeclaration;

  TreeNode? currentParent;

  TreeNode? get currentClassOrExtensionOrMember =>
      currentMember ??
      currentClass ??
      currentExtension ??
      currentExtensionTypeDeclaration;

  static void check(Target target, VerificationStage stage, Component component,
      {required bool skipPlatform,
      bool Function(Library library)? librarySkipFilter}) {
    component.accept(new VerifyingVisitor(target, stage,
        skipPlatform: skipPlatform, librarySkipFilter: librarySkipFilter));
  }

  VerifyingVisitor(this.target, this.stage,
      {required this.skipPlatform,
      required this.librarySkipFilter,
      VerificationErrorListener this.listener =
          const VerificationErrorListener()});

  /// If true, relax certain checks for *outline* mode. For example, don't
  /// attempt to validate constructor initializers.
  bool get isOutline => stage == VerificationStage.outline;

  /// If true, assume that constant evaluation has been performed (with a
  /// target that did not opt out of any of the constant inlining) and report
  /// a verification error for anything that should have been removed by it.
  bool get afterConst => stage >= VerificationStage.afterConstantEvaluation;

  /// If true, constant fields and local variables are expected to be inlined.
  bool get constantsAreAlwaysInlined =>
      target.constantsBackend.alwaysInlineConstants;

  /// If true, constant local variables are expected to have been removed.
  bool get constantLocalsShouldBeRemoved => !target.constantsBackend.keepLocals;

  @override
  void defaultTreeNode(TreeNode node) {
    enterTreeNode(node);
    visitChildren(node);
    exitTreeNode(node);
  }

  @override
  void defaultConstantReference(Constant constant) {
    if (seenConstants.add(constant)) {
      constant.accept(this);
    }
  }

  @override
  void defaultConstant(Constant constant) {
    constant.visitChildren(this);
  }

  void problem(TreeNode? node, String details,
      {TreeNode? context, TreeNode? origin}) {
    TreeNode? problemNode = node ?? context ?? currentClassOrExtensionOrMember;
    int offset = problemNode?.fileOffset ?? -1;
    Location? location = problemNode != null
        ? _getLocation(problemNode, allowInvalidLocation: true)
        : null;
    Uri? file = location?.file ?? fileUri;
    Uri? uri = file == null ? null : file;
    String verifierState = 'Target=${target.name}, $stage: ';
    listener.reportError('$verifierState$details',
        problemUri: uri,
        problemOffset: offset,
        node: node,
        context: context ?? currentClassOrExtensionOrMember,
        origin: origin);
  }

  TreeNode? enterParent(TreeNode node) {
    if (!identical(node.parent, currentParent)) {
      problem(
          node,
          "Incorrect parent pointer on ${node}:"
          " expected ${currentParent},"
          " but found: ${node.parent}.",
          context: currentParent);
    }
    TreeNode? oldParent = currentParent;
    currentParent = node;
    return oldParent;
  }

  void exitParent(TreeNode? oldParent) {
    currentParent = oldParent;
  }

  int enterLocalScope() => variableStack.length;

  void exitLocalScope(int stackHeight) {
    for (int i = stackHeight; i < variableStack.length; ++i) {
      undeclareVariable(variableStack[i]);
    }
    variableStack.length = stackHeight;
  }

  /// Calls [f] with [node] set up as the parent node.
  void inTreeNode(TreeNode node, void Function() f) {
    TreeNode? oldParent = enterParent(node);
    f();
    exitParent(oldParent);
  }

  void visitChildren(TreeNode node) {
    inTreeNode(node, () => node.visitChildren(this));
  }

  void visitWithLocalScope(TreeNode node) {
    enterTreeNode(node);
    int stackHeight = enterLocalScope();
    visitChildren(node);
    exitLocalScope(stackHeight);
    exitTreeNode(node);
  }

  void declareVariable(ExpressionVariable variable) {
    if (variableDeclarationsInScope.contains(variable)) {
      problem(variable, "Variable '$variable' declared more than once.");
    }
    variableDeclarationsInScope.add(variable);
    variableStack.add(variable);
  }

  void undeclareVariable(ExpressionVariable variable) {
    variableDeclarationsInScope.remove(variable);
  }

  void declareTypeParameters(List<TypeParameter> parameters) {
    for (int i = 0; i < parameters.length; ++i) {
      TypeParameter parameter = parameters[i];
      if (identical(parameter.bound, TypeParameter.unsetBoundSentinel)) {
        problem(
            currentParent, "Missing bound for type parameter '$parameter'.");
      }
      if (identical(
          parameter.defaultType, TypeParameter.unsetDefaultTypeSentinel)) {
        problem(currentParent,
            "Missing default type for type parameter '$parameter'.");
      }
      if (!typeParametersInScope.add(parameter)) {
        problem(parameter, "Type parameter '$parameter' redeclared.");
      }
    }
  }

  void declareStructuralParameters(List<StructuralParameter> parameters) {
    for (int i = 0; i < parameters.length; ++i) {
      StructuralParameter parameter = parameters[i];
      if (identical(parameter.bound, StructuralParameter.unsetBoundSentinel)) {
        problem(
            currentParent, "Missing bound for type parameter '$parameter'.");
      }
      if (identical(parameter.defaultType,
          StructuralParameter.unsetDefaultTypeSentinel)) {
        problem(currentParent,
            "Missing default type for type parameter '$parameter'.");
      }
      if (!structuralParametersInScope.add(parameter)) {
        problem(currentParent, "Type parameter '$parameter' redeclared.");
      }
    }
  }

  void undeclareTypeParameters(List<TypeParameter> parameters) {
    typeParametersInScope.removeAll(parameters);
  }

  void undeclareStructuralParameters(List<StructuralParameter> parameters) {
    structuralParametersInScope.removeAll(parameters);
  }

  void checkVariableInScope(ExpressionVariable variable, TreeNode where) {
    if (!variableDeclarationsInScope.contains(variable)) {
      problem(where, "Variable '$variable' used out of scope.");
    }
  }

  @override
  void visitComponent(Component component) {
    void declareMember(Member member) {
      if (member.transformerFlags & TransformerFlag.seenByVerifier != 0) {
        problem(member.function,
            "Member '$member' has been declared more than once.");
      }
      member.transformerFlags |= TransformerFlag.seenByVerifier;
    }

    void undeclareMember(Member member) {
      member.transformerFlags &= ~TransformerFlag.seenByVerifier;
    }

    try {
      for (Library library in component.libraries) {
        for (Class class_ in library.classes) {
          if (!classes.add(class_)) {
            problem(class_, "Class '$class_' declared more than once.");
          }
        }
        for (Typedef typedef_ in library.typedefs) {
          if (!typedefs.add(typedef_)) {
            problem(typedef_, "Typedef '$typedef_' declared more than once.");
          }
        }

        library.forEachMember(declareMember);
        for (Class class_ in library.classes) {
          class_.forEachMember(declareMember);
        }
        for (ExtensionTypeDeclaration extensionTypeDeclaration
            in library.extensionTypeDeclarations) {
          extensionTypeDeclaration.procedures.forEach(declareMember);
        }
      }
      visitChildren(component);
    } finally {
      for (Library library in component.libraries) {
        library.forEachMember(undeclareMember);
        for (Class class_ in library.classes) {
          class_.forEachMember(undeclareMember);
        }

        for (ExtensionTypeDeclaration extensionTypeDeclaration
            in library.extensionTypeDeclarations) {
          extensionTypeDeclaration.procedures.forEach(undeclareMember);
        }
      }
      variableStack.forEach(undeclareVariable);
    }
  }

  @override
  void visitLibrary(Library node) {
    if (skipPlatform &&
        node.importUri.isScheme('dart') &&
        // 'dart:test' is used in the unit tests and isn't an actual part of the
        // platform so we don't skip its verification.
        node.importUri.path != 'test') {
      return;
    }
    if (librarySkipFilter != null && librarySkipFilter!(node)) {
      return;
    }

    enterTreeNode(node);
    fileUri = checkLocation(node, node.name, node.fileUri);
    currentLibrary = node;
    TreeNode? oldParent = enterParent(node);
    _visitAnnotations(node.annotations);
    visitList(node.dependencies, this);
    visitList(node.parts, this);
    visitList(node.typedefs, this);
    visitList(node.classes, this);
    visitList(node.extensions, this);
    visitList(node.extensionTypeDeclarations, this);
    visitList(node.procedures, this);
    visitList(node.fields, this);
    exitParent(oldParent);
    currentLibrary = null;
    exitTreeNode(node);
    _extensionsMembers = null;
    _extensionTypeMembers = null;
  }

  Map<Reference, ExtensionMemberDescriptor> _computeExtensionMembers(
      Library library) {
    if (_extensionsMembers == null) {
      Map<Reference, ExtensionMemberDescriptor> map = _extensionsMembers = {};
      for (Extension extension in library.extensions) {
        for (ExtensionMemberDescriptor descriptor
            in extension.memberDescriptors) {
          Reference? memberReference = descriptor.memberReference;
          if (memberReference != null) {
            map[memberReference] = descriptor;
            Member member = memberReference.asMember;
            if (!member.isExtensionMember) {
              problem(
                  member,
                  "Member $member (${descriptor}) from $extension is not "
                  " marked as an extension member.");
            }
          }
          Reference? tearOffReference = descriptor.tearOffReference;
          if (tearOffReference != null) {
            map[tearOffReference] = descriptor;
            Member tearOff = tearOffReference.asMember;
            if (!tearOff.isExtensionMember) {
              problem(
                  tearOff,
                  "Tear-off $tearOff (${descriptor}) from $extension is not "
                  "marked as an extension member.");
            }
          }
          if (memberReference == null && tearOffReference == null) {
            problem(
                extension,
                "Both member and tear-off references are null in "
                "the descriptor $descriptor from $extension.");
          }
        }
      }
    }
    return _extensionsMembers!;
  }

  @override
  void visitLibraryPart(LibraryPart node) {
    enterTreeNode(node);
    TreeNode? oldParent = enterParent(node);
    _visitAnnotations(node.annotations);
    exitParent(oldParent);
    exitTreeNode(node);
  }

  @override
  void visitLibraryDependency(LibraryDependency node) {
    enterTreeNode(node);
    TreeNode? oldParent = enterParent(node);
    _visitAnnotations(node.annotations);
    visitList(node.combinators, this);
    exitParent(oldParent);
    exitTreeNode(node);
  }

  Map<Reference, ExtensionTypeMemberDescriptor> _computeExtensionTypeMembers(
      Library library) {
    if (_extensionTypeMembers == null) {
      Map<Reference, ExtensionTypeMemberDescriptor> map =
          _extensionTypeMembers = {};
      for (ExtensionTypeDeclaration extensionTypeDeclaration
          in library.extensionTypeDeclarations) {
        for (ExtensionTypeMemberDescriptor descriptor
            in extensionTypeDeclaration.memberDescriptors) {
          Reference? memberReference = descriptor.memberReference;
          if (memberReference != null) {
            map[memberReference] = descriptor;
            Member member = memberReference.asMember;
            if (!member.isExtensionTypeMember) {
              problem(
                  member,
                  "Member $member (${descriptor}) from "
                  "$extensionTypeDeclaration is not marked as an extension "
                  "type member.");
            }
          }
          Reference? tearOffReference = descriptor.tearOffReference;
          if (tearOffReference != null) {
            map[tearOffReference] = descriptor;
            Member tearOff = tearOffReference.asMember;
            if (!tearOff.isExtensionTypeMember) {
              problem(
                  tearOff,
                  "Tear-off $tearOff (${descriptor}) from "
                  "$extensionTypeDeclaration is not marked as an extension "
                  "type member.");
            }
          }
          if (memberReference == null && tearOffReference == null) {
            problem(
                extensionTypeDeclaration,
                "Both member and tear-off references are null in "
                "the descriptor $descriptor from $extensionTypeDeclaration.");
          }
        }
      }
    }
    return _extensionTypeMembers!;
  }

  @override
  void visitExtension(Extension node) {
    enterTreeNode(node);
    fileUri = checkLocation(node, node.name, node.fileUri);
    currentExtension = node;
    _computeExtensionMembers(node.enclosingLibrary);
    declareTypeParameters(node.typeParameters);
    final TreeNode? oldParent = enterParent(node);
    _visitAnnotations(node.annotations);
    visitList(node.typeParameters, this);
    node.onType.accept(this);
    exitParent(oldParent);
    undeclareTypeParameters(node.typeParameters);
    currentExtension = null;
    exitTreeNode(node);
  }

  @override
  void visitExtensionTypeDeclaration(ExtensionTypeDeclaration node) {
    enterTreeNode(node);
    fileUri = checkLocation(node, node.name, node.fileUri);
    currentExtensionTypeDeclaration = node;
    _computeExtensionTypeMembers(node.enclosingLibrary);
    declareTypeParameters(node.typeParameters);
    final TreeNode? oldParent = enterParent(node);
    for (DartType type in node.implements) {
      if (!(type is ExtensionType || type is InterfaceType)) {
        problem(
            node,
            "Extension type can only implement extension types and interface "
            "types. Found $type.");
      } else if (type is ExtensionType &&
              type.nullability == Nullability.nullable ||
          type is! ExtensionType && type.isPotentiallyNullable) {
        problem(
            node,
            "Extension type can only implement non-nullable types. "
            "Found $type.");
      }
    }
    _visitAnnotations(node.annotations);
    visitList(node.typeParameters, this);
    node.declaredRepresentationType.accept(this);
    visitList(node.procedures, this);
    exitParent(oldParent);
    undeclareTypeParameters(node.typeParameters);
    currentExtensionTypeDeclaration = null;
    exitTreeNode(node);
  }

  void checkTypedef(Typedef node) {
    TypedefState? state = typedefState[node];
    if (state == TypedefState.Done) return;
    if (state == TypedefState.BeingChecked) {
      problem(node, "The typedef '$node' refers to itself", context: node);
    }
    assert(state == null);
    enterTreeNode(node);
    typedefState[node] = TypedefState.BeingChecked;
    Set<TypeParameter> savedTypeParameters = typeParametersInScope;
    typeParametersInScope = node.typeParameters.toSet();
    TreeNode? savedParent = currentParent;
    currentParent = node;
    // Visit children without checking the parent pointer on the typedef itself
    // since this can be called from a context other than its true parent.
    _visitAnnotations(node.annotations);
    visitList(node.typeParameters, this);
    node.type?.accept(this);
    currentParent = savedParent;
    typeParametersInScope = savedTypeParameters;
    typedefState[node] = TypedefState.Done;
    exitTreeNode(node);
  }

  @override
  void visitTypedef(Typedef node) {
    enterTreeNode(node);
    fileUri = checkLocation(node, node.name, node.fileUri);
    checkTypedef(node);
    // Enter and exit the node to check the parent pointer on the typedef node.
    exitParent(enterParent(node));
    exitTreeNode(node);
  }

  void _findExtensionMember(Member node) {
    assert(node.isExtensionMember);
    Map<Reference, ExtensionMemberDescriptor> extensionMembers =
        _computeExtensionMembers(node.enclosingLibrary);
    if (!extensionMembers.containsKey(node.reference)) {
      problem(
          node,
          "Extension member $node is not found in any extension of the "
          "enclosing library.");
    }
  }

  void _findExtensionTypeMember(Member node) {
    assert(node.isExtensionTypeMember);
    Map<Reference, ExtensionTypeMemberDescriptor> extensionTypeMembers =
        _computeExtensionTypeMembers(node.enclosingLibrary);
    if (node is Procedure &&
        node.stubKind == ProcedureStubKind.RepresentationField) {
      if (extensionTypeMembers.containsKey(node.reference)) {
        problem(
            node,
            "Extension type representation field $node is found amongst the "
            "lowered extension type members of the enclosing library.");
      }
    } else {
      if (!extensionTypeMembers.containsKey(node.reference)) {
        problem(
            node,
            "Extension type member $node is not found in any extension type "
            "declaration of the enclosing library.");
      }
    }
  }

  @override
  void visitField(Field node) {
    enterTreeNode(node);
    fileUri = checkLocation(node, node.name.text, node.fileUri);
    currentMember = node;
    TreeNode? oldParent = enterParent(node);
    bool isTopLevel = node.parent == currentLibrary;
    if (isTopLevel && !node.isStatic) {
      problem(node, "The top-level field '${node.name.text}' should be static",
          context: node);
    }
    if (node.isConst && !node.isStatic) {
      problem(node, "The const field '${node.name.text}' should be static",
          context: node);
    }
    bool isImmutable = node.isLate
        ? (node.isFinal && node.initializer != null)
        : (node.isFinal || node.isConst);
    if (isImmutable == node.hasSetter) {
      if (node.hasSetter) {
        problem(node,
            "The immutable field '${node.name.text}' has a setter reference",
            context: node);
      } else {
        if (isOutline && node.isLate) {
          // TODO(johnniwinther): Should we add a flag on Field for having
          // a declared initializer?
          // The initializer is not included in the outline so we can't tell
          // whether it has an initializer or not.
        } else {
          problem(node,
              "The mutable field '${node.name.text}' has no setter reference",
              context: node);
        }
      }
    }
    if (node.isExtensionMember) {
      _findExtensionMember(node);
    }
    if (node.isExtensionTypeMember) {
      _findExtensionTypeMember(node);
    }
    classTypeParametersAreInScope = !node.isStatic;
    node.initializer?.accept(this);
    node.type.accept(this);
    classTypeParametersAreInScope = false;
    _visitAnnotations(node.annotations);
    exitParent(oldParent);
    currentMember = null;
    exitTreeNode(node);
  }

  void _visitAnnotations(List<Expression> annotations) {
    for (Expression annotation in annotations) {
      if (stage >= VerificationStage.afterConstantEvaluation) {
        if (!(annotation is ConstantExpression ||
            annotation is InvalidExpression)) {
          problem(
              annotation,
              "Unexpected annotation $annotation (${annotation.runtimeType}). "
              "Expected a ConstantExpression or InvalidExpression.");
        }
      }
      annotation.accept(this);
    }
  }

  @override
  void visitProcedure(Procedure node) {
    enterTreeNode(node);
    fileUri = checkLocation(node, node.name.text, node.fileUri);
    if (node.isExtensionMember) {
      _findExtensionMember(node);
    }
    if (node.isExtensionTypeMember) {
      _findExtensionTypeMember(node);
    }

    if (node.isRedirectingFactory &&
        node.function.redirectingFactoryTarget == null) {
      problem(
          node,
          "Procedure '${node.name}' doesn't have a redirecting "
          "factory target, but has the 'isRedirectingFactory' bit set.");
    } else if (!node.isRedirectingFactory &&
        node.function.redirectingFactoryTarget != null) {
      problem(
          node,
          "Procedure '${node.name}' has redirecting factory target, but "
          "doesn't have the 'isRedirectingFactory' bit set.");
    }

    currentMember = node;
    TreeNode? oldParent = enterParent(node);
    classTypeParametersAreInScope = !node.isStatic;
    if (node.isAbstract && node.isExternal) {
      problem(node, "Procedure cannot be both abstract and external.");
    }
    if (node.isMemberSignature && node.isForwardingStub) {
      problem(
          node,
          "Procedure cannot be both a member signature and a forwarding stub: "
          "$node.");
    }
    if (node.isMemberSignature && node.isForwardingSemiStub) {
      problem(
          node,
          "Procedure cannot be both a member signature and a forwarding semi "
          "stub $node.");
    }
    if (node.isMemberSignature && node.isNoSuchMethodForwarder) {
      problem(
          node,
          "Procedure cannot be both a member signature and a noSuchMethod "
          "forwarder $node.");
    }
    if (node.isMemberSignature && node.memberSignatureOrigin == null) {
      problem(
          node, "Member signature must have a member signature origin $node.");
    }
    if (node.abstractForwardingStubTarget != null &&
        !(node.isForwardingStub || node.isForwardingSemiStub)) {
      problem(
          node,
          "Only forwarding stubs can have a forwarding stub interface target "
          "$node.");
    }
    if (node.concreteForwardingStubTarget != null &&
        !(node.isForwardingStub || node.isForwardingSemiStub)) {
      problem(
          node,
          "Only forwarding stubs can have a forwarding stub super target "
          "$node.");
    }
    node.function.accept(this);
    classTypeParametersAreInScope = false;
    _visitAnnotations(node.annotations);
    exitParent(oldParent);
    // TODO(johnniwinther): Enable this invariant. Possibly by removing bodies
    // from external procedures declared with a body or by removing the external
    // flag from such procedures.
    /*if (node.isExternal) {
      if (node.function.body != null) {
        problem(node, "External procedure has non-null body.");
      }
    } else if (node.isAbstract) {
      if (node.function.body != null) {
        problem(node, "Abstract procedure has non-null body.");
      }
    } else {
      if (node.function.body == null) {
        problem(node, "Non-external/abstract procedure has no body.");
      }
    }*/
    currentMember = null;
    exitTreeNode(node);
  }

  @override
  void visitConstructor(Constructor node) {
    enterTreeNode(node);
    fileUri = checkLocation(node, node.name.text, node.fileUri);
    currentMember = node;
    classTypeParametersAreInScope = true;
    if (node.isExtensionMember) {
      _findExtensionMember(node);
    }
    if (node.isExtensionTypeMember) {
      _findExtensionTypeMember(node);
    }

    // The constructor member needs special treatment due to parameters being
    // in scope in the initializer list.
    TreeNode? oldParent = enterParent(node);
    int stackHeight = enterLocalScope();
    visitChildren(node.function);
    visitList(node.initializers, this);
    if (!isOutline) {
      checkInitializers(node);
    }
    exitLocalScope(stackHeight);
    classTypeParametersAreInScope = false;
    _visitAnnotations(node.annotations);
    exitParent(oldParent);
    // TODO(johnniwinther): Enable this invariant. Possibly by removing bodies
    // from external constructors declared with a body or by removing the
    // external flag from such constructors.
    /*if (node.isExternal) {
      if (node.function.body != null) {
        problem(node, "External constructor has non-null body.");
      }
    } else {
      if (node.function.body == null) {
        problem(node, "Non-external constructor has no body.");
      }
    }*/
    classTypeParametersAreInScope = false;
    currentMember = null;
    exitTreeNode(node);
  }

  @override
  void visitClass(Class node) {
    enterTreeNode(node);
    fileUri = checkLocation(node, node.name, node.fileUri);
    currentClass = node;
    declareTypeParameters(node.typeParameters);
    TreeNode? oldParent = enterParent(node);
    classTypeParametersAreInScope = false;
    _visitAnnotations(node.annotations);
    classTypeParametersAreInScope = true;
    visitList(node.typeParameters, this);
    visitList(node.fields, this);
    visitList(node.constructors, this);
    visitList(node.procedures, this);
    exitParent(oldParent);
    undeclareTypeParameters(node.typeParameters);
    currentClass = null;
    exitTreeNode(node);
  }

  @override
  void visitFunctionNode(FunctionNode node) {
    enterTreeNode(node);
    declareTypeParameters(node.typeParameters);
    bool savedInCatchBlock = inCatchBlock;
    AsyncMarker savedAsyncMarker = currentAsyncMarker;
    currentAsyncMarker = node.asyncMarker;
    if (!isOutline) {
      if (node.asyncMarker == AsyncMarker.Async &&
          node.emittedValueType == null) {
        problem(node,
            "No future value type set for async function in opt-in library.");
      }

      TreeNode? parent = node.parent;
      if (parent is! Procedure ||
          !parent.isAbstract &&
              !parent.isSynthetic &&
              !parent.isSyntheticForwarder) {
        for (int positionalIndex = 0;
            positionalIndex < node.positionalParameters.length;
            positionalIndex++) {
          if (positionalIndex >= node.requiredParameterCount) {
            VariableDeclaration positionalParameter =
                node.positionalParameters[positionalIndex];
            if (positionalParameter.initializer == null) {
              problem(
                  positionalParameter,
                  "An optional positional parameter is expected to have a "
                  "default value initializer, defined or synthesized.");
            }
          }
        }
        for (VariableDeclaration namedParameter in node.namedParameters) {
          if (!namedParameter.isRequired &&
              namedParameter.initializer == null) {
            problem(
                namedParameter,
                "An optional named parameter is expected to have a default "
                "value initializer, defined or synthesized.");
          }
        }
      }
    }
    inCatchBlock = false;
    visitWithLocalScope(node);
    inCatchBlock = savedInCatchBlock;
    currentAsyncMarker = savedAsyncMarker;
    undeclareTypeParameters(node.typeParameters);
    exitTreeNode(node);
  }

  @override
  void visitFunctionType(FunctionType node) {
    for (int i = 1; i < node.namedParameters.length; ++i) {
      if (node.namedParameters[i - 1].compareTo(node.namedParameters[i]) >= 0) {
        problem(currentParent,
            "Named parameters are not sorted on function type ($node).");
      }
    }
    declareStructuralParameters(node.typeParameters);
    visitList(node.positionalParameters, this);
    visitList(node.namedParameters, this);
    node.returnType.accept(this);
    undeclareStructuralParameters(node.typeParameters);
  }

  @override
  void visitBlock(Block node) {
    visitWithLocalScope(node);
  }

  @override
  void visitForStatement(ForStatement node) {
    visitWithLocalScope(node);
  }

  @override
  void visitLet(Let node) {
    if (_isCompileTimeErrorEncoding(node)) return;
    visitWithLocalScope(node);
  }

  @override
  void visitInvalidExpression(InvalidExpression node) {
    return;
  }

  @override
  void visitBlockExpression(BlockExpression node) {
    enterTreeNode(node);
    int stackHeight = enterLocalScope();
    // Do not visit the block directly because the value expression needs to
    // be in its scope.
    TreeNode? oldParent = enterParent(node);
    enterParent(node.body);
    for (int i = 0; i < node.body.statements.length; ++i) {
      node.body.statements[i].accept(this);
    }
    exitParent(node);
    node.value.accept(this);
    exitParent(oldParent);
    exitLocalScope(stackHeight);
    exitTreeNode(node);
  }

  @override
  void visitCatch(Catch node) {
    bool savedInCatchBlock = inCatchBlock;
    inCatchBlock = true;
    visitWithLocalScope(node);
    inCatchBlock = savedInCatchBlock;
  }

  @override
  void visitReturnStatement(ReturnStatement node) {
    switch (currentAsyncMarker) {
      case AsyncMarker.Sync:
      case AsyncMarker.Async:
        // ok
        break;
      case AsyncMarker.SyncStar:
      case AsyncMarker.AsyncStar:
        if (node.expression != null) {
          problem(
              node,
              "Return statement in function with async marker: "
              "$currentAsyncMarker");
        }
        break;
    }
    super.visitReturnStatement(node);
  }

  @override
  void visitYieldStatement(YieldStatement node) {
    switch (currentAsyncMarker) {
      case AsyncMarker.Sync:
      case AsyncMarker.Async:
        problem(
            node,
            "Yield statement in function with async marker: "
            "$currentAsyncMarker");
        break;
      case AsyncMarker.SyncStar:
      case AsyncMarker.AsyncStar:
        // ok
        break;
    }
    super.visitYieldStatement(node);
  }

  @override
  void visitRethrow(Rethrow node) {
    if (!inCatchBlock) {
      problem(node, "Rethrow must be inside a Catch block.");
    }
  }

  @override
  void visitVariableDeclaration(VariableDeclaration node) {
    return _verifyVariableInitialization(node);
  }

  @override
  void visitVariableInitialization(VariableInitialization node) {
    return _verifyVariableInitialization(node);
  }

  void _verifyVariableInitialization(VariableInitialization node) {
    enterTreeNode(node);
    TreeNode? parent = node.parent;
    if (parent is! Block &&
        !(parent is Catch && parent.body != node) &&
        !(parent is FunctionNode && parent.body != node) &&
        parent is! FunctionDeclaration &&
        !(parent is ForStatement && parent.body != node) &&
        !(parent is ForInStatement && parent.body != node) &&
        parent is! Let &&
        parent is! LocalInitializer &&
        parent is! Typedef) {
      problem(
          node,
          "VariableDeclaration must be a direct child of a Block, "
          "not ${parent.runtimeType}.");
    }
    TreeNode? oldParent = enterParent(node);
    _visitAnnotations(node.annotations);
    node.initializer?.accept(this);
    exitParent(oldParent);
    declareVariable(node.variable);
    if (afterConst && node.isConst && constantLocalsShouldBeRemoved) {
      Expression? initializer = node.initializer;
      if (!(initializer is InvalidExpression ||
          initializer is ConstantExpression &&
              initializer.constant is UnevaluatedConstant)) {
        problem(node, "Constant VariableDeclaration");
      }
    }
    exitTreeNode(node);
  }

  @override
  void visitLocalVariable(LocalVariable node) {
    declareVariable(node);
  }

  @override
  void visitVariableGet(VariableGet node) {
    enterTreeNode(node);
    checkVariableInScope(node.expressionVariable, node);
    visitChildren(node);
    if (constantsAreAlwaysInlined &&
        afterConst &&
        node.expressionVariable.isConst &&
        !inUnevaluatedConstant) {
      problem(
          node, "VariableGet of const variable '${node.expressionVariable}'.");
    }
    exitTreeNode(node);
  }

  @override
  void visitVariableSet(VariableSet node) {
    enterTreeNode(node);
    checkVariableInScope(node.expressionVariable, node);
    visitChildren(node);
    exitTreeNode(node);
  }

  @override
  void visitStaticGet(StaticGet node) {
    enterTreeNode(node);
    visitChildren(node);
    // TODO(johnniwinther): Can this be deleted now?
    // Currently Constructor.hasGetter returns `false` even though the CFE uses
    // it as a getter for internal purposes:
    //
    // CFE is letting all call site of a redirecting constructor be resolved
    // to the real target.  In order to resolve it, it seems to add a body into
    // the redirecting-factory constructor which caches the target constructor.
    // That cache is via a `StaticGet(real-constructor)` node, which we make
    // here pass the verifier.
    if (!node.target.hasGetter && node.target is! Constructor) {
      problem(node, "StaticGet of '${node.target}' without getter.");
    }
    if (node.target.isInstanceMember) {
      problem(node, "StaticGet of '${node.target}' that's an instance member.");
    }
    if (constantsAreAlwaysInlined &&
        afterConst &&
        node.target is Field &&
        node.target.isConst) {
      problem(node, "StaticGet of const field '${node.target}'.");
    }
    exitTreeNode(node);
  }

  @override
  void visitStaticSet(StaticSet node) {
    enterTreeNode(node);
    visitChildren(node);
    if (!node.target.hasSetter) {
      problem(node, "StaticSet to '${node.target}' without setter.");
    }
    if (node.target.isInstanceMember) {
      problem(node, "StaticSet to '${node.target}' that's an instance member.");
    }
    exitTreeNode(node);
  }

  @override
  void visitStaticInvocation(StaticInvocation node) {
    enterTreeNode(node);
    checkTargetedInvocation(node.target, node);
    if (node.target.isInstanceMember) {
      problem(node,
          "StaticInvocation of '${node.target}' that's an instance member.");
    }
    if (node.isConst &&
        !(node.target.isConst &&
            node.target.isExternal &&
            node.target.kind == ProcedureKind.Factory) &&
        !(node.target.isConst && node.target.isExtensionTypeMember)) {
      problem(
          node,
          "Constant StaticInvocation of '${node.target}' that isn't"
          " a const external factory or a const extension type constructor.");
    }
    if (afterConst && node.isConst && !inUnevaluatedConstant) {
      problem(node, "Constant StaticInvocation.");
    }
    exitTreeNode(node);
  }

  @override
  void visitTypedefTearOff(TypedefTearOff node) {
    _checkTypedefTearOff(node);
    declareStructuralParameters(node.structuralParameters);
    super.visitTypedefTearOff(node);
    undeclareStructuralParameters(node.structuralParameters);
  }

  void checkTargetedInvocation(Member target, InvocationExpression node) {
    visitChildren(node);
    if (target.function == null) {
      problem(node, "${node.runtimeType} without function.");
    }
    if (!areArgumentsCompatible(node.arguments, target.function!)) {
      problem(node,
          "${node.runtimeType} with incompatible arguments for '${target}'.");
    }
    int expectedTypeParameters = target is Constructor
        ? target.enclosingClass.typeParameters.length
        : target.function!.typeParameters.length;
    if (node.arguments.types.length != expectedTypeParameters) {
      problem(
          node,
          "${node.runtimeType} with wrong number of type arguments"
          " for '${target}'.");
    }
  }

  @override
  void visitConstructorInvocation(ConstructorInvocation node) {
    enterTreeNode(node);
    checkTargetedInvocation(node.target, node);
    if (node.target.enclosingClass.isAbstract) {
      problem(node, "$node of abstract class ${node.target.enclosingClass}.");
    }
    if (node.isConst && !node.target.isConst) {
      problem(
          node,
          "Constant ConstructorInvocation fo '${node.target}' that"
          " isn't const.");
    }
    if (afterConst && node.isConst && !inUnevaluatedConstant) {
      problem(node, "Invocation of const constructor '${node.target}'.");
    }
    exitTreeNode(node);
  }

  bool areArgumentsCompatible(Arguments arguments, FunctionNode function) {
    if (arguments.positional.length < function.requiredParameterCount) {
      return false;
    }
    if (arguments.positional.length > function.positionalParameters.length) {
      return false;
    }
    namedLoop:
    for (int i = 0; i < arguments.named.length; ++i) {
      NamedExpression argument = arguments.named[i];
      String name = argument.name;
      for (int j = 0; j < function.namedParameters.length; ++j) {
        if (function.namedParameters[j].name == name) continue namedLoop;
      }
      return false;
    }
    return true;
  }

  @override
  void visitListLiteral(ListLiteral node) {
    enterTreeNode(node);
    visitChildren(node);
    if (afterConst && node.isConst && !inUnevaluatedConstant) {
      problem(node, "Constant list literal.");
    }
    exitTreeNode(node);
  }

  @override
  void visitSetLiteral(SetLiteral node) {
    enterTreeNode(node);
    visitChildren(node);
    if (afterConst && node.isConst && !inUnevaluatedConstant) {
      problem(node, "Constant set literal.");
    }
    exitTreeNode(node);
  }

  @override
  void visitMapLiteral(MapLiteral node) {
    enterTreeNode(node);
    visitChildren(node);
    if (afterConst && node.isConst && !inUnevaluatedConstant) {
      problem(node, "Constant map literal.");
    }
    exitTreeNode(node);
  }

  @override
  void visitSymbolLiteral(SymbolLiteral node) {
    enterTreeNode(node);
    if (afterConst && !inUnevaluatedConstant) {
      problem(node, "Symbol literal.");
    }
    exitTreeNode(node);
  }

  @override
  void visitContinueSwitchStatement(ContinueSwitchStatement node) {
    enterTreeNode(node);
    if (node.target.parent == null) {
      problem(node, "Target has no parent.");
    } else {
      SwitchStatement statement = node.target.parent as SwitchStatement;
      for (SwitchCase switchCase in statement.cases) {
        if (switchCase == node.target) {
          exitTreeNode(node);
          return;
        }
      }
      problem(node, "Switch case isn't child of parent.");
    }
    exitTreeNode(node);
  }

  @override
  void visitInstanceConstant(InstanceConstant constant) {
    constant.visitChildren(this);
    if (constant.typeArguments.length !=
        constant.classNode.typeParameters.length) {
      problem(
          currentParent,
          "Constant $constant provides ${constant.typeArguments.length}"
          " type arguments, but the class declares"
          " ${constant.classNode.typeParameters.length} parameters.");
    }
    Set<Class> superClasses = <Class>{};
    int fieldCount = 0;
    for (Class? cls = constant.classNode; cls != null; cls = cls.superclass) {
      superClasses.add(cls);
      for (Field f in cls.fields) {
        if (!f.isStatic && !f.isConst) fieldCount++;
      }
    }
    if (constant.fieldValues.length != fieldCount) {
      problem(
          currentParent,
          "Constant $constant provides ${constant.fieldValues.length}"
          " field values, but the class declares"
          " $fieldCount fields.");
    }
    for (Reference fieldRef in constant.fieldValues.keys) {
      Field field = fieldRef.asField;
      if (!superClasses.contains(field.enclosingClass)) {
        problem(
            currentParent,
            "Constant $constant refers to field $field,"
            " which does not belong to the right class.");
      }
    }
  }

  @override
  void visitUnevaluatedConstant(UnevaluatedConstant constant) {
    bool savedInUnevaluatedConstant = inUnevaluatedConstant;
    inUnevaluatedConstant = true;
    TreeNode? oldParent = currentParent;
    currentParent = null;
    constant.expression.accept(this);
    currentParent = oldParent;
    inUnevaluatedConstant = savedInUnevaluatedConstant;
  }

  @override
  void defaultMemberReference(Member node) {
    if (node.transformerFlags & TransformerFlag.seenByVerifier == 0) {
      problem(
          node, "Dangling reference to '$node', parent is: '${node.parent}'.");
    }
  }

  @override
  void visitClassReference(Class node) {
    if (!classes.contains(node)) {
      problem(
          node, "Dangling reference to '$node', parent is: '${node.parent}'.");
    }
  }

  @override
  void visitTypedefReference(Typedef node) {
    if (!typedefs.contains(node)) {
      problem(
          node, "Dangling reference to '$node', parent is: '${node.parent}'");
    }
  }

  @override
  void visitTypeParameterType(TypeParameterType node) {
    TypeParameter parameter = node.parameter;
    GenericDeclaration? declaration = parameter.declaration;
    if (!typeParametersInScope.contains(parameter)) {
      problem(
          currentParent,
          "Type parameter '$parameter' referenced out of"
          " scope, declaration is: '${declaration}'.");
    }
    if (declaration is Class && !classTypeParametersAreInScope) {
      problem(
          currentParent,
          "Type parameter '$parameter' referenced from"
          " static context, declaration is: '${declaration}'.");
    }
    defaultDartType(node);
  }

  @override
  void visitInterfaceType(InterfaceType node) {
    if (isNullType(node) && node.nullability != Nullability.nullable) {
      problem(localContext, "Found a not nullable Null type: ${node}");
    }
    defaultDartType(node);
    if (node.typeArguments.length != node.classNode.typeParameters.length) {
      problem(
          currentParent,
          "Type $node provides ${node.typeArguments.length}"
          " type arguments, but the class declares"
          " ${node.classNode.typeParameters.length} parameters.");
    }
    if (node.classNode.isAnonymousMixin) {
      bool isOk = false;
      if (currentParent is FunctionNode) {
        TreeNode? functionNodeParent = currentParent!.parent;
        if (functionNodeParent is Constructor) {
          if (functionNodeParent.parent == node.classNode) {
            // We only allow references to anonymous mixins in types as the
            // return type of its own constructor.
            isOk = true;
          }
        }
      }
      if (!isOk) {
        problem(
            currentParent, "Type $node references an anonymous mixin class.");
      }
    }
  }

  @override
  void visitTypedefType(TypedefType node) {
    checkTypedef(node.typedefNode);
    defaultDartType(node);
    if (node.typeArguments.length != node.typedefNode.typeParameters.length) {
      problem(
          currentParent,
          "The typedef type $node provides ${node.typeArguments.length}"
          " type arguments, but the typedef declares"
          " ${node.typedefNode.typeParameters.length} parameters.");
    }
  }

  @override
  void visitConstantExpression(ConstantExpression node) {
    enterTreeNode(node);
    inTreeNode(node, () {
      bool oldInConstant = inConstant;
      node.type.accept(this);
      // Only visit the [Constant] in constant context.
      inConstant = true;
      node.constant.accept(this);
      inConstant = oldInConstant;
    });
    exitTreeNode(node);
  }

  @override
  void visitTypeParameter(TypeParameter node) {
    if (identical(node.bound, TypeParameter.unsetBoundSentinel)) {
      problem(node, "Unset bound on type parameter $node");
    }
    if (identical(node.defaultType, TypeParameter.unsetDefaultTypeSentinel)) {
      problem(node, "Unset default type on type parameter $node");
    }
    // ignore: deprecated_member_use_from_same_package
    if (node.parent == null) {
      // TODO(johnniwinther): Enable this check.
      // problem(node, "Type parameter without parent: $node");
      node.visitChildren(this);
    } else {
      visitChildren(node);
    }
  }

  @override
  void visitTypedefTearOffConstant(TypedefTearOffConstant node) {
    _checkTypedefTearOff(node);
    declareStructuralParameters(node.parameters);
    super.visitTypedefTearOffConstant(node);
    undeclareStructuralParameters(node.parameters);
  }

  void _checkInterfaceTarget(Expression node, Member interfaceTarget) {
    if (!interfaceTarget.isInstanceMember) {
      problem(
          node, "Interface target $interfaceTarget is not an instance member.");
    }
    if (interfaceTarget is Procedure &&
        interfaceTarget.stubKind == ProcedureStubKind.RepresentationField) {
      problem(node,
          "Representation field used as interface target: $interfaceTarget.");
    }
    if (interfaceTarget.enclosingClass == null) {
      problem(
          node,
          "Interface target $interfaceTarget does not have an "
          "enclosing class.");
    }
  }

  @override
  void visitInstanceInvocation(InstanceInvocation node) {
    if (node.name != node.interfaceTarget.name) {
      problem(
          node,
          "Instance invocation with name '${node.name}' has a "
          "target with name '${node.interfaceTarget.name}'.");
    }
    _checkInterfaceTarget(node, node.interfaceTarget);
    super.visitInstanceInvocation(node);
  }

  @override
  void visitInstanceGet(InstanceGet node) {
    if (node.name != node.interfaceTarget.name) {
      problem(
          node,
          "Instance get with name '${node.name}' has a "
          "target with name '${node.interfaceTarget.name}'.");
    }
    _checkInterfaceTarget(node, node.interfaceTarget);
    super.visitInstanceGet(node);
  }

  @override
  void visitInstanceTearOff(InstanceTearOff node) {
    if (node.name != node.interfaceTarget.name) {
      problem(
          node,
          "Instance tear-off with name '${node.name}' has a "
          "target with name '${node.interfaceTarget.name}'.");
    }
    _checkInterfaceTarget(node, node.interfaceTarget);
    super.visitInstanceTearOff(node);
  }

  @override
  void visitInstanceSet(InstanceSet node) {
    if (node.name != node.interfaceTarget.name) {
      problem(
          node,
          "Instance set with name '${node.name}' has a "
          "target with name '${node.interfaceTarget.name}'.");
    }
    _checkInterfaceTarget(node, node.interfaceTarget);
    super.visitInstanceSet(node);
  }

  /// Invoked by all visit methods if the visited node is a [TreeNode].
  // TODO(johnniwinther): Merge this with enter/exitParent.
  void enterTreeNode(TreeNode node) {
    treeNodeStack.add(node);
    testLocation(node);
  }

  /// Invoked by all visit methods if the visited node is a [TreeNode].
  void exitTreeNode(TreeNode node) {
    if (treeNodeStack.isEmpty) {
      throw new StateError("Attempting to exit tree node '${node}' "
          "when the tree node stack is empty.");
    }
    if (!identical(treeNodeStack.last, node)) {
      throw new StateError("Attempting to exit tree node '${node}' "
          "when another node '${treeNodeStack.last}' is active.");
    }
    treeNodeStack.removeLast();
  }

  TreeNode? getLastSeenTreeNode({bool withLocation = false}) {
    assert(treeNodeStack.isNotEmpty);
    for (int i = treeNodeStack.length - 1; i >= 0; --i) {
      TreeNode node = treeNodeStack[i];
      if (withLocation && !_hasLocation(_getLocation(node), node)) continue;
      return node;
    }
    return null;
  }

  TreeNode? getSameLibraryLastSeenTreeNode({bool withLocation = false}) {
    if (treeNodeStack.isEmpty) return null;
    if (currentLibrary == null) return null;

    for (int i = treeNodeStack.length - 1; i >= 0; --i) {
      TreeNode node = treeNodeStack[i];
      Location? location = _getLocation(node);
      if (withLocation && !_hasLocation(location, node)) continue;
      if (location != null && location.file == currentLibrary!.fileUri) {
        return node;
      }
    }
    return null;
  }

  /// Returns the `TreeNode.location` while handling [RangeError]s caused by
  /// file offsets not within the range of the enclosing file.
  Location? _getLocation(TreeNode node, {bool allowInvalidLocation = false}) {
    try {
      return node.location;
    } on RangeError catch (e) {
      if (allowInvalidLocation ||
          target.verification.allowInvalidLocation(stage, node)) {
        return null;
      }
      problem(
          node,
          "Invalid location with target '${target.name}' on "
          "${node} (${node.runtimeType}): $e");
    }
    return null;
  }

  bool _hasLocation(Location? location, TreeNode node) {
    return location != null && node.fileOffset != TreeNode.noOffset;
  }

  bool _isInSameLibrary(Library? library, TreeNode node) {
    if (library == null) return false;
    Location? location = _getLocation(node);
    if (location == null) return false;
    return library.fileUri == location.file;
  }

  TreeNode? get localContext {
    TreeNode? result = getSameLibraryLastSeenTreeNode(withLocation: true);
    if (result == null &&
        currentClassOrExtensionOrMember != null &&
        _isInSameLibrary(currentLibrary, currentClassOrExtensionOrMember!)) {
      result = currentClassOrExtensionOrMember;
    }
    return result;
  }

  TreeNode? get remoteContext {
    TreeNode? result = getLastSeenTreeNode(withLocation: true);
    if (result != null && _isInSameLibrary(currentLibrary, result)) {
      result = null;
    }
    return result;
  }

  // We disable the location test for now, at least these tests currently fail:
  //  outline/dartdevc/factory_patch/main
  //  outline/general/constructor_patch/main
  //  outline/general/factory_patch/main
  //  outline/general/mixin_from_patch/main
  //  outline/general/multiple_class_patches/main
  //  outline/general/patch_extends_implements/main
  //  outline/nnbd/platform_optional_parameters/main
  //  pkg/front_end/test/macros/application/macro_application_test.dart -p \
  //    subtypes.dart
  static const bool doTestLocation = false;

  void testLocation(TreeNode node) {
    if (!doTestLocation) return;
    // When these comes from patching (and in the future from augmentation) they
    // don't point correctly.
    if (node is LibraryDependency || node is LibraryPart) return;
    try {
      if (node.fileOffset != TreeNode.noOffset) {
        node.location;
      }
    } catch (e) {
      problem(
          node, "${node.runtimeType} crashes when  asked for location: '$e'",
          context: node);
    }
  }

  Uri checkLocation(TreeNode node, String? name, Uri fileUri) {
    if (name == null || name.contains("#")) {
      // TODO(ahe): Investigate if these checks can be enabled:
      // if (node.fileUri != null && node is! Library) {
      //   problem(node, "A synthetic node shouldn't have a fileUri",
      //       context: node);
      // }
      // if (node.fileOffset != -1) {
      //   problem(node, "A synthetic node shouldn't have a fileOffset",
      //       context: node);
      // }
      return fileUri;
    } else {
      if (node.fileOffset == TreeNode.noOffset &&
          !target.verification.allowNoFileOffset(stage, node)) {
        problem(node, "'$name' has no fileOffset", context: node);
      }
      return fileUri;
    }
  }

  void checkSuperInvocation(TreeNode node) {
    Member? containingMember = getContainingMember(node);
    if (containingMember == null) {
      problem(node, 'Super call outside of any member');
    } else {
      if (!containingMember.containsSuperCalls) {
        problem(
            node, 'Super call in a member lacking TransformerFlag.superCalls');
      }
    }
  }

  Member? getContainingMember(TreeNode? node) {
    while (node != null) {
      if (node is Member) return node;
      node = node.parent;
    }
    return null;
  }

  @override
  void visitAsExpression(AsExpression node) {
    enterTreeNode(node);
    super.visitAsExpression(node);
    if (node.fileOffset == TreeNode.noOffset &&
        !node.isUnchecked &&
        !target.verification.allowNoFileOffset(stage, node)) {
      TreeNode? parent = node.parent;
      while (parent != null) {
        if (parent.fileOffset != TreeNode.noOffset) break;
        parent = parent.parent;
      }
      problem(parent, "No offset for $node", context: node);
    }
    exitTreeNode(node);
  }

  @override
  void visitExpressionStatement(ExpressionStatement node) {
    // Bypass verification of the [StaticGet] in [RedirectingFactoryBody] as
    // this is a static get without a getter.
    enterTreeNode(node);
    super.visitExpressionStatement(node);
    exitTreeNode(node);
  }

  bool isNullType(DartType node) => node is NullType;

  bool isObjectClass(Class c) {
    return c.name == "Object" &&
        c.enclosingLibrary.importUri.isScheme("dart") &&
        c.enclosingLibrary.importUri.path == "core";
  }

  bool isTopType(DartType node) {
    return node is DynamicType ||
        node is VoidType ||
        node is InterfaceType &&
            isObjectClass(node.classNode) &&
            node.nullability == Nullability.nullable ||
        node is FutureOrType && isTopType(node.typeArgument);
  }

  bool isFutureOrNull(DartType node) {
    return isNullType(node) ||
        node is FutureOrType && isFutureOrNull(node.typeArgument);
  }

  @override
  void defaultDartType(DartType node) {
    if (!AllowedTypes.isAllowed(node, inConstant: inConstant)) {
      final TreeNode? localContext = this.localContext;
      final TreeNode? remoteContext = this.remoteContext;
      problem(
          localContext,
          "Unexpected appearance of the disallowed type $node"
          "${inConstant ? " inside a constant" : ""}.",
          origin: remoteContext);
    }
    super.defaultDartType(node);
  }

  @override
  void visitSuperMethodInvocation(SuperMethodInvocation node) {
    enterTreeNode(node);
    checkSuperInvocation(node);
    super.visitSuperMethodInvocation(node);
    exitTreeNode(node);
  }

  @override
  void visitSuperPropertyGet(SuperPropertyGet node) {
    enterTreeNode(node);
    checkSuperInvocation(node);
    super.visitSuperPropertyGet(node);
    exitTreeNode(node);
  }

  @override
  void visitSuperPropertySet(SuperPropertySet node) {
    enterTreeNode(node);
    checkSuperInvocation(node);
    super.visitSuperPropertySet(node);
    exitTreeNode(node);
  }

  void _checkConstructorTearOff(Node node, Member tearOffTarget) {
    if (tearOffTarget.enclosingLibrary.importUri.isScheme('dart')) {
      // Platform libraries are not compilation with test flags and might
      // contain tear-offs not expected when testing lowerings.
      return;
    }
    if (tearOffTarget is Constructor &&
        target.isConstructorTearOffLoweringEnabled) {
      problem(
          node is TreeNode ? node : getLastSeenTreeNode(),
          '${node.runtimeType} nodes for generative constructors should be '
          'lowered for target "${target.name}".');
    }
    if (tearOffTarget is Procedure &&
        tearOffTarget.isFactory &&
        target.isFactoryTearOffLoweringEnabled) {
      problem(
          node is TreeNode ? node : getLastSeenTreeNode(),
          '${node.runtimeType} nodes for factory constructors should be '
          'lowered for target "${target.name}".');
    }
  }

  @override
  void visitConstructorTearOff(ConstructorTearOff node) {
    _checkConstructorTearOff(node, node.target);
    super.visitConstructorTearOff(node);
  }

  @override
  void visitConstructorTearOffConstant(ConstructorTearOffConstant node) {
    _checkConstructorTearOff(node, node.target);
    super.visitConstructorTearOffConstant(node);
  }

  void _checkTypedefTearOff(Node node) {
    if (target.isTypedefTearOffLoweringEnabled) {
      problem(
          node is TreeNode ? node : getLastSeenTreeNode(),
          '${node.runtimeType} nodes for typedefs should be '
          'lowered for target "${target.name}".');
    }
  }

  void _checkRedirectingFactoryTearOff(Node node) {
    if (target.isRedirectingFactoryTearOffLoweringEnabled) {
      problem(
          node is TreeNode ? node : getLastSeenTreeNode(),
          'ConstructorTearOff nodes for redirecting factories should be '
          'lowered for target "${target.name}".');
    }
  }

  @override
  void visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
    _checkRedirectingFactoryTearOff(node);
    super.visitRedirectingFactoryTearOff(node);
  }

  @override
  void visitRedirectingFactoryTearOffConstant(
      RedirectingFactoryTearOffConstant node) {
    _checkRedirectingFactoryTearOff(node);
    super.visitRedirectingFactoryTearOffConstant(node);
  }

  @override
  void visitSwitchStatement(SwitchStatement node) {
    if (node.expressionTypeInternal == null) {
      problem(node, 'SwitchStatement.expressionType has not been set.');
    }
    super.visitSwitchStatement(node);
  }

  @override
  void visitListConcatenation(ListConcatenation node) {
    if (stage >= VerificationStage.afterConstantEvaluation) {
      if (!inUnevaluatedConstant) {
        problem(node, "Unexpected internal node $node.");
      }
    }
  }

  @override
  void visitSetConcatenation(SetConcatenation node) {
    if (stage >= VerificationStage.afterConstantEvaluation) {
      if (!inUnevaluatedConstant) {
        problem(node, "Unexpected internal node $node.");
      }
    }
  }

  @override
  void visitMapConcatenation(MapConcatenation node) {
    if (stage >= VerificationStage.afterConstantEvaluation) {
      if (!inUnevaluatedConstant) {
        problem(node, "Unexpected internal node $node.");
      }
    }
  }

  @override
  void visitInstanceCreation(InstanceCreation node) {
    if (stage >= VerificationStage.afterConstantEvaluation) {
      if (!inUnevaluatedConstant) {
        problem(node, "Unexpected internal node $node.");
      }
    }
  }

  @override
  void visitFileUriExpression(FileUriExpression node) {
    if (!target.supportsFileUriExpression) {
      if (stage >= VerificationStage.afterConstantEvaluation) {
        if (!inUnevaluatedConstant) {
          problem(node, "Unexpected internal node $node.");
        }
      }
    }
  }

  @override
  void visitPatternAssignment(PatternAssignment node) {
    if (stage >= VerificationStage.afterConstantEvaluation) {
      problem(node, "Unexpected internal node $node.");
    }
  }

  @override
  void visitPatternVariableDeclaration(PatternVariableDeclaration node) {
    if (stage >= VerificationStage.afterConstantEvaluation) {
      problem(node, "Unexpected internal node $node.");
    }
  }

  @override
  void visitIfCaseStatement(IfCaseStatement node) {
    if (stage >= VerificationStage.afterConstantEvaluation) {
      problem(node, "Unexpected internal node $node.");
    }
  }

  @override
  void visitPatternSwitchStatement(PatternSwitchStatement node) {
    if (stage >= VerificationStage.afterConstantEvaluation) {
      problem(node, "Unexpected internal node $node.");
    }
  }

  @override
  void defaultPattern(Pattern node) {
    if (stage >= VerificationStage.afterConstantEvaluation) {
      problem(node, "Unexpected internal node $node.");
    }
  }

  @override
  void visitSwitchExpression(SwitchExpression node) {
    if (stage >= VerificationStage.afterConstantEvaluation) {
      problem(node, "Unexpected internal node $node.");
    }
  }

  @override
  void visitSwitchExpressionCase(SwitchExpressionCase node) {
    if (stage >= VerificationStage.afterConstantEvaluation) {
      problem(node, "Unexpected internal node $node.");
    }
  }

  @override
  void visitPatternGuard(PatternGuard node) {
    if (stage >= VerificationStage.afterConstantEvaluation) {
      problem(node, "Unexpected internal node $node.");
    }
  }

  @override
  void visitPatternSwitchCase(PatternSwitchCase node) {
    if (stage >= VerificationStage.afterConstantEvaluation) {
      problem(node, "Unexpected internal node $node.");
    }
  }
}

class VerifyGetStaticType extends RecursiveVisitor {
  final TypeEnvironment env;
  Member? currentMember;
  final StatefulStaticTypeContext _staticTypeContext;

  VerifyGetStaticType(this.env)
      : _staticTypeContext = new StatefulStaticTypeContext.stacked(env);

  @override
  void visitLibrary(Library node) {
    _staticTypeContext.enterLibrary(node);
    super.visitLibrary(node);
    _staticTypeContext.leaveLibrary(node);
  }

  @override
  void visitField(Field node) {
    currentMember = node;
    _staticTypeContext.enterMember(node);
    super.visitField(node);
    _staticTypeContext.leaveMember(node);
    currentMember = node;
  }

  @override
  void visitProcedure(Procedure node) {
    currentMember = node;
    _staticTypeContext.enterMember(node);
    super.visitProcedure(node);
    _staticTypeContext.leaveMember(node);
    currentMember = node;
  }

  @override
  void visitConstructor(Constructor node) {
    currentMember = node;
    _staticTypeContext.enterMember(node);
    super.visitConstructor(node);
    _staticTypeContext.leaveMember(node);
    currentMember = null;
  }

  @override
  void visitLet(Let node) {
    if (_isCompileTimeErrorEncoding(node)) return;
    super.visitLet(node);
  }

  @override
  void visitInvalidExpression(InvalidExpression node) {
    return;
  }

  @override
  void defaultExpression(Expression node) {
    try {
      node.getStaticType(_staticTypeContext);
    } catch (_) {
      print('Error in $currentMember in ${currentMember?.fileUri}: '
          '$node (${node.runtimeType})');
      rethrow;
    }
    super.defaultExpression(node);
  }
}

void checkInitializers(Constructor constructor) {
  // TODO(ahe): I'll add more here in other CLs.
}

bool _isCompileTimeErrorEncoding(TreeNode? node) {
  return node is Let && node.variable.initializer is InvalidExpression;
}

class AllowedTypes implements DartTypeVisitor<bool> {
  static bool isAllowed(DartType type, {required bool inConstant}) {
    return type.accept(inConstant
        ? const AllowedTypes(inConstant: true)
        : const AllowedTypes(inConstant: false));
  }

  final bool inConstant;

  const AllowedTypes({required this.inConstant});

  @override
  bool visitAuxiliaryType(AuxiliaryType node) => false;

  @override
  bool visitDynamicType(DynamicType node) => true;

  @override
  bool visitFunctionType(FunctionType node) => true;

  @override
  bool visitFutureOrType(FutureOrType node) => true;

  @override
  bool visitExtensionType(ExtensionType node) => !inConstant;

  @override
  bool visitInterfaceType(InterfaceType node) => true;

  @override
  bool visitIntersectionType(IntersectionType node) => true;

  @override
  bool visitInvalidType(InvalidType node) => true;

  @override
  bool visitNeverType(NeverType node) => true;

  @override
  bool visitNullType(NullType node) => true;

  @override
  bool visitRecordType(RecordType node) => true;

  @override
  bool visitTypeParameterType(TypeParameterType node) => true;

  @override
  bool visitStructuralParameterType(StructuralParameterType node) => true;

  @override
  bool visitTypedefType(TypedefType node) => true;

  @override
  bool visitVoidType(VoidType node) => true;

  @override
  bool visitFunctionTypeParameterType(FunctionTypeParameterType node) {
    // TODO(cstefantsova): Implement visitFunctionTypeParameterType.
    throw new UnimplementedError(
        "Unimplemented support for $node (${node.runtimeType}).");
  }

  @override
  bool visitClassTypeParameterType(ClassTypeParameterType node) {
    // TODO(cstefantsova): Implement visitClassTypeParameterType.
    throw new UnimplementedError(
        "Unimplemented support for $node (${node.runtimeType}).");
  }
}
