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

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:nnbd_migration/src/decorated_type.dart';
import 'package:nnbd_migration/src/edit_plan.dart';
import 'package:nnbd_migration/src/hint_action.dart';
import 'package:nnbd_migration/src/nullability_node.dart';
import 'package:nnbd_migration/src/nullability_node_target.dart';
import 'package:nnbd_migration/src/utilities/completeness_tracker.dart';
import 'package:nnbd_migration/src/utilities/hint_utils.dart';
import 'package:nnbd_migration/src/utilities/permissive_mode.dart';
import 'package:nnbd_migration/src/utilities/resolution_utils.dart';
import 'package:nnbd_migration/src/variables.dart';

import 'edge_origin.dart';

/// Visitor that builds nullability nodes based on visiting code to be migrated.
///
/// The return type of each `visit...` method is a [DecoratedType] indicating
/// the static type of the element declared by the visited node, along with the
/// constraint variables that will determine its nullability.  For `visit...`
/// methods that don't visit declarations, `null` will be returned.
class NodeBuilder extends GeneralizingAstVisitor<DecoratedType>
    with
        PermissiveModeVisitor<DecoratedType>,
        CompletenessTracker<DecoratedType> {
  /// Constraint variables and decorated types are stored here.
  final Variables? _variables;

  @override
  final Source? source;

  final LineInfo Function(String) _getLineInfo;

  /// If the parameters of a function or method are being visited, the
  /// [DecoratedType]s of the function's named parameters that have been seen so
  /// far.  Otherwise `null`.
  Map<String, DecoratedType?>? _namedParameters;

  /// If the parameters of a function or method are being visited, the
  /// [DecoratedType]s of the function's positional parameters that have been
  /// seen so far.  Otherwise `null`.
  List<DecoratedType?>? _positionalParameters;

  /// If the child types of a node are being visited, the
  /// [NullabilityNodeTarget] that should be used in [visitTypeAnnotation].
  /// Otherwise `null`.
  NullabilityNodeTarget? _target;

  final NullabilityMigrationListener? listener;

  final NullabilityMigrationInstrumentation? instrumentation;

  final NullabilityGraph _graph;

  final TypeProvider _typeProvider;

  /// Indicates whether the declaration currently being visited is marked
  /// `external`.
  bool _visitingExternalDeclaration = false;

  NodeBuilder(this._variables, this.source, this.listener, this._graph,
      this._typeProvider, this._getLineInfo,
      {this.instrumentation});

  NullabilityNodeTarget get safeTarget {
    var target = _target;
    if (target != null) return target;
    assert(false, 'Unknown nullability node target');
    return NullabilityNodeTarget.text('unknown');
  }

  @override
  DecoratedType? visitAsExpression(AsExpression node) {
    node.expression.accept(this);
    _pushNullabilityNodeTarget(
        NullabilityNodeTarget.text('cast type'), () => node.type.accept(this));
    return null;
  }

  @override
  DecoratedType? visitCatchClause(CatchClause node) {
    var exceptionElement = node.exceptionParameter?.staticElement;
    var target = exceptionElement == null
        ? NullabilityNodeTarget.text('exception type')
        : NullabilityNodeTarget.element(exceptionElement, _getLineInfo);
    DecoratedType? exceptionType = _pushNullabilityNodeTarget(
        target, () => node.exceptionType?.accept(this));
    if (node.exceptionParameter != null) {
      // If there is no `on Type` part of the catch clause, the type is dynamic.
      if (exceptionType == null) {
        exceptionType = DecoratedType.forImplicitType(_typeProvider,
            _typeProvider.dynamicType, _graph, target.withCodeRef(node));
        instrumentation?.implicitType(
            source, node.exceptionParameter, exceptionType);
      }
      _variables!.recordDecoratedElementType(
          node.exceptionParameter!.staticElement, exceptionType);
    }
    if (node.stackTraceParameter != null) {
      // The type of stack traces is always StackTrace (non-nullable).
      var target = NullabilityNodeTarget.text('stack trace').withCodeRef(node);
      var nullabilityNode = NullabilityNode.forInferredType(target);
      _graph.makeNonNullableUnion(nullabilityNode,
          StackTraceTypeOrigin(source, node.stackTraceParameter));
      var stackTraceType =
          DecoratedType(_typeProvider.stackTraceType, nullabilityNode);
      _variables!.recordDecoratedElementType(
          node.stackTraceParameter!.staticElement, stackTraceType);
      instrumentation?.implicitType(
          source, node.stackTraceParameter, stackTraceType);
    }
    node.stackTraceParameter?.accept(this);
    node.body.accept(this);
    return null;
  }

  @override
  DecoratedType? visitClassDeclaration(ClassDeclaration node) {
    node.metadata.accept(this);
    node.name.accept(this);
    node.typeParameters?.accept(this);
    node.nativeClause?.accept(this);
    node.members.accept(this);
    var classElement = node.declaredElement!;
    _handleSupertypeClauses(node, classElement, node.extendsClause?.superclass2,
        node.withClause, node.implementsClause, null);
    var constructors = classElement.constructors;
    if (constructors.length == 1) {
      var constructorElement = constructors[0];
      if (constructorElement.isSynthetic) {
        // Need to create a decorated type for the default constructor.
        var decoratedReturnType =
            _createDecoratedTypeForClass(classElement, node);
        var functionType = DecoratedType(constructorElement.type, _graph.never,
            returnType: decoratedReturnType,
            positionalParameters: const [],
            namedParameters: {});
        _variables!
            .recordDecoratedElementType(constructorElement, functionType);
      }
    }
    return null;
  }

  @override
  DecoratedType? visitClassTypeAlias(ClassTypeAlias node) {
    node.metadata.accept(this);
    node.name.accept(this);
    node.typeParameters?.accept(this);
    var classElement = node.declaredElement!;
    _handleSupertypeClauses(node, classElement, node.superclass2,
        node.withClause, node.implementsClause, null);
    for (var constructorElement in classElement.constructors) {
      assert(constructorElement.isSynthetic);
      var decoratedReturnType =
          _createDecoratedTypeForClass(classElement, node);
      var target =
          NullabilityNodeTarget.element(constructorElement, _getLineInfo);
      var functionType = DecoratedType.forImplicitFunction(
          _typeProvider, constructorElement.type, _graph.never, _graph, target,
          returnType: decoratedReturnType);
      _variables!.recordDecoratedElementType(constructorElement, functionType);
      for (var parameter in constructorElement.parameters) {
        var parameterType = DecoratedType.forImplicitType(
            _typeProvider, parameter.type, _graph, target);
        _variables!.recordDecoratedElementType(parameter, parameterType);
      }
    }
    return null;
  }

  @override
  DecoratedType? visitCompilationUnit(CompilationUnit node) {
    _graph.migrating(node.declaredElement!.library.source);
    _graph.migrating(node.declaredElement!.source);
    return super.visitCompilationUnit(node);
  }

  @override
  DecoratedType? visitConstructorDeclaration(ConstructorDeclaration node) {
    _handleExecutableDeclaration(
        node,
        node.declaredElement!,
        node.metadata,
        null,
        null,
        node.parameters,
        node.initializers,
        node.body,
        node.redirectedConstructor,
        isExternal: node.externalKeyword != null);
    return null;
  }

  @override
  DecoratedType? visitConstructorName(ConstructorName node) {
    _pushNullabilityNodeTarget(NullabilityNodeTarget.text('constructed type'),
        () => node.type2.accept(this));
    node.name?.accept(this);
    return null;
  }

  @override
  DecoratedType? visitDeclaredIdentifier(DeclaredIdentifier node) {
    node.metadata.accept(this);
    var declaredElement = node.declaredElement!;
    var target = NullabilityNodeTarget.element(declaredElement, _getLineInfo);
    DecoratedType? type =
        _pushNullabilityNodeTarget(target, () => node.type?.accept(this));
    if (type == null) {
      type = DecoratedType.forImplicitType(
          _typeProvider, declaredElement.type, _graph, target);
      instrumentation?.implicitType(source, node, type);
    }
    _variables!.recordDecoratedElementType(node.identifier.staticElement, type);
    return type;
  }

  @override
  DecoratedType? visitDefaultFormalParameter(DefaultFormalParameter node) {
    var decoratedType = node.parameter.accept(this);
    var hint = getPrefixHint(node.firstTokenAfterCommentAndMetadata!);
    if (node.defaultValue != null) {
      node.defaultValue!.accept(this);
      return null;
    } else if (node.declaredElement!.hasRequired) {
      return null;
    } else if (hint != null && hint.kind == HintCommentKind.required) {
      _variables!.recordRequiredHint(source, node, hint);
      return null;
    }
    if (decoratedType == null) {
      throw StateError('No type computed for ${node.parameter.runtimeType} '
          '(${node.parent!.parent!.toSource()}) offset=${node.offset}');
    }
    decoratedType.node!.trackPossiblyOptional();
    return null;
  }

  @override
  DecoratedType? visitEnumDeclaration(EnumDeclaration node) {
    node.metadata.accept(this);
    node.name.accept(this);
    var classElement = node.declaredElement!;
    _variables!.recordDecoratedElementType(
        classElement, DecoratedType(classElement.thisType, _graph.never));

    makeNonNullNode(NullabilityNodeTarget target, [AstNode? forNode]) {
      forNode ??= node;
      final graphNode = NullabilityNode.forInferredType(target);
      _graph.makeNonNullableUnion(graphNode, EnumValueOrigin(source, forNode));
      return graphNode;
    }

    for (var item in node.constants) {
      var declaredElement = item.declaredElement!;
      var target = NullabilityNodeTarget.element(declaredElement, _getLineInfo);
      _variables!.recordDecoratedElementType(declaredElement,
          DecoratedType(classElement.thisType, makeNonNullNode(target, item)));
    }
    final valuesGetter = classElement.getGetter('values')!;
    var valuesTarget =
        NullabilityNodeTarget.element(valuesGetter, _getLineInfo);
    _variables!.recordDecoratedElementType(
        valuesGetter,
        DecoratedType(valuesGetter.type, makeNonNullNode(valuesTarget),
            returnType: DecoratedType(valuesGetter.returnType,
                makeNonNullNode(valuesTarget.returnType()),
                typeArguments: [
                  DecoratedType(classElement.thisType,
                      makeNonNullNode(valuesTarget.typeArgument(0)))
                ])));
    final indexGetter = classElement.getGetter('index')!;
    var indexTarget = NullabilityNodeTarget.element(indexGetter, _getLineInfo);
    _variables!.recordDecoratedElementType(
        indexGetter,
        DecoratedType(indexGetter.type, makeNonNullNode(indexTarget),
            returnType: DecoratedType(indexGetter.returnType,
                makeNonNullNode(indexTarget.returnType()))));
    final toString = classElement.getMethod('toString')!;
    var toStringTarget = NullabilityNodeTarget.element(toString, _getLineInfo);
    _variables!.recordDecoratedElementType(
        toString,
        DecoratedType(toString.type, makeNonNullNode(toStringTarget),
            returnType: DecoratedType(toString.returnType,
                makeNonNullNode(toStringTarget.returnType()))));
    return null;
  }

  @override
  DecoratedType? visitExtensionDeclaration(ExtensionDeclaration node) {
    node.metadata.accept(this);
    node.typeParameters?.accept(this);
    var type = _pushNullabilityNodeTarget(
        NullabilityNodeTarget.text('extended type'),
        () => node.extendedType.accept(this));
    _variables!.recordDecoratedElementType(node.declaredElement, type);
    node.members.accept(this);
    return null;
  }

  @override
  DecoratedType? visitFieldFormalParameter(FieldFormalParameter node) {
    return _handleFormalParameter(
        node, node.type, node.typeParameters, node.parameters);
  }

  @override
  DecoratedType? visitFormalParameterList(FormalParameterList node) {
    int index = 0;
    for (var parameter in node.parameters) {
      var element = parameter.declaredElement!;
      NullabilityNodeTarget newTarget;
      if (element.isNamed) {
        newTarget = safeTarget.namedParameter(element.name);
      } else {
        newTarget = safeTarget.positionalParameter(index++);
      }
      _pushNullabilityNodeTarget(newTarget, () => parameter.accept(this));
    }
    return null;
  }

  @override
  DecoratedType? visitFunctionDeclaration(FunctionDeclaration node) {
    _handleExecutableDeclaration(
        node,
        node.declaredElement!,
        node.metadata,
        node.returnType,
        node.functionExpression.typeParameters,
        node.functionExpression.parameters,
        null,
        node.functionExpression.body,
        null,
        isExternal: node.externalKeyword != null);
    return null;
  }

  @override
  DecoratedType? visitFunctionExpression(FunctionExpression node) {
    _handleExecutableDeclaration(node, node.declaredElement!, null, null,
        node.typeParameters, node.parameters, null, node.body, null,
        isExternal: false);
    return null;
  }

  @override
  DecoratedType? visitFunctionExpressionInvocation(
      FunctionExpressionInvocation node) {
    node.function.accept(this);
    _pushNullabilityNodeTarget(NullabilityNodeTarget.text('type argument'),
        () => node.typeArguments?.accept(this));
    node.argumentList.accept(this);
    return null;
  }

  @override
  DecoratedType? visitFunctionTypeAlias(FunctionTypeAlias node) {
    node.metadata.accept(this);
    var declaredElement = node.declaredElement!;
    var functionElement =
        declaredElement.aliasedElement as GenericFunctionTypeElement;
    var functionType = functionElement.type;
    var returnType = node.returnType;
    DecoratedType? decoratedReturnType;
    var target = NullabilityNodeTarget.element(declaredElement, _getLineInfo);
    if (returnType != null) {
      _pushNullabilityNodeTarget(target.returnType(), () {
        decoratedReturnType = returnType.accept(this);
      });
    } else {
      // Inferred return type.
      decoratedReturnType = DecoratedType.forImplicitType(
          _typeProvider, functionType.returnType, _graph, target.returnType());
      instrumentation?.implicitReturnType(source, node, decoratedReturnType);
    }
    var previousPositionalParameters = _positionalParameters;
    var previousNamedParameters = _namedParameters;
    _positionalParameters = [];
    _namedParameters = {};
    DecoratedType decoratedFunctionType;
    try {
      node.typeParameters?.accept(this);
      _pushNullabilityNodeTarget(target, () => node.parameters.accept(this));
      // Note: we don't pass _typeFormalBounds into DecoratedType because we're
      // not defining a generic function type, we're defining a generic typedef
      // of an ordinary (non-generic) function type.
      decoratedFunctionType = DecoratedType(functionType, _graph.never,
          returnType: decoratedReturnType,
          positionalParameters: _positionalParameters,
          namedParameters: _namedParameters);
    } finally {
      _positionalParameters = previousPositionalParameters;
      _namedParameters = previousNamedParameters;
    }
    _variables!
        .recordDecoratedElementType(functionElement, decoratedFunctionType);
    return null;
  }

  @override
  DecoratedType? visitFunctionTypedFormalParameter(
      FunctionTypedFormalParameter node) {
    return _handleFormalParameter(
        node, node.returnType, node.typeParameters, node.parameters);
  }

  @override
  DecoratedType? visitGenericTypeAlias(GenericTypeAlias node) {
    node.metadata.accept(this);
    DecoratedType? decoratedFunctionType;
    node.typeParameters?.accept(this);
    var target =
        NullabilityNodeTarget.element(node.declaredElement!, _getLineInfo);
    _pushNullabilityNodeTarget(target, () {
      decoratedFunctionType = node.functionType!.accept(this);
    });
    _variables!.recordDecoratedElementType(
        (node.declaredElement as TypeAliasElement).aliasedElement,
        decoratedFunctionType);
    return null;
  }

  @override
  DecoratedType? visitIsExpression(IsExpression node) {
    node.expression.accept(this);
    _pushNullabilityNodeTarget(NullabilityNodeTarget.text('tested type'),
        () => node.type.accept(this));
    return null;
  }

  @override
  DecoratedType? visitListLiteral(ListLiteral node) {
    _pushNullabilityNodeTarget(NullabilityNodeTarget.text('list element type'),
        () => node.typeArguments?.accept(this));
    node.elements.accept(this);
    return null;
  }

  @override
  DecoratedType? visitMethodDeclaration(MethodDeclaration node) {
    var declaredElement = node.declaredElement;
    var decoratedType = _handleExecutableDeclaration(
        node,
        declaredElement!,
        node.metadata,
        node.returnType,
        node.typeParameters,
        node.parameters,
        null,
        node.body,
        null,
        isExternal: node.externalKeyword != null);
    if (declaredElement is PropertyAccessorElement) {
      // Store a decorated type for the synthetic field so that in case we try
      // to access it later we won't crash (this could happen due to errors in
      // the source code).
      if (declaredElement.isGetter) {
        _variables!.recordDecoratedElementType(
            declaredElement.variable, decoratedType.returnType);
      } else {
        var type = decoratedType.positionalParameters![0];
        _variables!.recordDecoratedElementType(declaredElement.variable, type,
            soft: true);
        if (_hasAngularChildAnnotation(node.metadata)) {
          _graph.makeNullable(
              type!.node!, AngularAnnotationOrigin(source, node));
        }
      }
    }
    return null;
  }

  @override
  DecoratedType? visitMethodInvocation(MethodInvocation node) {
    node.target?.accept(this);
    node.methodName.accept(this);
    _pushNullabilityNodeTarget(NullabilityNodeTarget.text('type argument'),
        () => node.typeArguments?.accept(this));
    node.argumentList.accept(this);
    return null;
  }

  @override
  DecoratedType? visitMixinDeclaration(MixinDeclaration node) {
    node.metadata.accept(this);
    node.name.accept(this);
    node.typeParameters?.accept(this);
    node.members.accept(this);
    _handleSupertypeClauses(node, node.declaredElement!, null, null,
        node.implementsClause, node.onClause);
    return null;
  }

  @override
  DecoratedType visitNamedType(NamedType node) {
    namedTypeVisited(node); // Note this has been visited to NamedTypeTracker.
    return visitTypeAnnotation(node);
  }

  @override
  DecoratedType? visitSetOrMapLiteral(SetOrMapLiteral node) {
    var typeArguments = node.typeArguments;
    if (typeArguments != null) {
      var arguments = typeArguments.arguments;
      if (arguments.length == 2) {
        _pushNullabilityNodeTarget(NullabilityNodeTarget.text('map key type'),
            () => arguments[0].accept(this));
        _pushNullabilityNodeTarget(NullabilityNodeTarget.text('map value type'),
            () => arguments[1].accept(this));
      } else {
        _pushNullabilityNodeTarget(
            NullabilityNodeTarget.text('set element type'),
            () => typeArguments.accept(this));
      }
    }
    node.elements.accept(this);
    return null;
  }

  @override
  DecoratedType? visitSimpleFormalParameter(SimpleFormalParameter node) {
    return _handleFormalParameter(node, node.type, null, null);
  }

  @override
  DecoratedType visitTypeAnnotation(TypeAnnotation node) {
    var type = node.type!;
    var target = safeTarget.withCodeRef(node);
    if (type.isVoid || type.isDynamic) {
      var nullabilityNode = NullabilityNode.forTypeAnnotation(target);
      var decoratedType = DecoratedType(type, nullabilityNode);
      _variables!.recordDecoratedTypeAnnotation(source, node, decoratedType);
      if (_visitingExternalDeclaration) {
        _graph.makeNullableUnion(
            nullabilityNode, ExternalDynamicOrigin(source, node));
      }
      return decoratedType;
    }
    var typeArguments = const <DecoratedType>[];
    DecoratedType? decoratedReturnType;
    List<DecoratedType?> positionalParameters = const <DecoratedType>[];
    Map<String, DecoratedType?> namedParameters =
        const <String, DecoratedType>{};
    if (type is InterfaceType && type.element.typeParameters.isNotEmpty) {
      if (node is NamedType) {
        if (node.typeArguments == null) {
          int index = 0;
          typeArguments = type.typeArguments
              .map((t) => DecoratedType.forImplicitType(
                  _typeProvider, t, _graph, target.typeArgument(index++)))
              .toList();
          instrumentation?.implicitTypeArguments(source, node, typeArguments);
        } else {
          int index = 0;
          typeArguments = node.typeArguments!.arguments
              .map((t) => _pushNullabilityNodeTarget(
                  target.typeArgument(index++), () => t.accept(this)!))
              .toList();
        }
      } else {
        assert(false); // TODO(paulberry): is this possible?
      }
    }
    if (node is GenericFunctionType) {
      var returnType = node.returnType;
      if (returnType == null) {
        decoratedReturnType = DecoratedType.forImplicitType(_typeProvider,
            DynamicTypeImpl.instance, _graph, target.returnType());
        instrumentation?.implicitReturnType(source, node, decoratedReturnType);
      } else {
        // If [_target] is non-null, then it represents the return type for
        // a FunctionTypeAlias. Otherwise, create a return type target for
        // `target`.
        _pushNullabilityNodeTarget(target.returnType(), () {
          decoratedReturnType = returnType.accept(this);
        });
      }
      positionalParameters = <DecoratedType?>[];
      namedParameters = <String, DecoratedType?>{};
      var previousPositionalParameters = _positionalParameters;
      var previousNamedParameters = _namedParameters;
      try {
        _positionalParameters = positionalParameters;
        _namedParameters = namedParameters;
        node.typeParameters?.accept(this);
        node.parameters.accept(this);
      } finally {
        _positionalParameters = previousPositionalParameters;
        _namedParameters = previousNamedParameters;
      }
    }
    NullabilityNode nullabilityNode;
    if (typeIsNonNullableByContext(node)) {
      nullabilityNode = _graph.never;
    } else {
      nullabilityNode = NullabilityNode.forTypeAnnotation(target);
      nullabilityNode.hintActions
        ..[HintActionKind.addNullableHint] = {
          node.end: [AtomicEdit.insert('/*?*/')]
        }
        ..[HintActionKind.addNonNullableHint] = {
          node.end: [AtomicEdit.insert('/*!*/')]
        };
    }
    DecoratedType decoratedType;
    if (type is FunctionType && node is! GenericFunctionType) {
      (node as NamedType).typeArguments?.accept(this);
      // node is a reference to a typedef.  Treat it like an inferred type (we
      // synthesize new nodes for it).  These nodes will be unioned with the
      // typedef nodes by the edge builder.
      decoratedType = DecoratedType.forImplicitFunction(
          _typeProvider, type, nullabilityNode, _graph, target);
    } else {
      decoratedType = DecoratedType(type, nullabilityNode,
          typeArguments: typeArguments,
          returnType: decoratedReturnType,
          positionalParameters: positionalParameters,
          namedParameters: namedParameters);
    }
    _variables!.recordDecoratedTypeAnnotation(source, node, decoratedType);
    _handleNullabilityHint(node, decoratedType);
    return decoratedType;
  }

  @override
  DecoratedType? visitTypeParameter(TypeParameter node) {
    var element = node.declaredElement!;
    var bound = node.bound;
    DecoratedType? decoratedBound;
    var target = NullabilityNodeTarget.typeParameterBound(element);
    if (bound != null) {
      decoratedBound =
          _pushNullabilityNodeTarget(target, () => bound.accept(this));
    } else {
      var nullabilityNode = NullabilityNode.forInferredType(target);
      decoratedBound = DecoratedType(_typeProvider.objectType, nullabilityNode);
      _graph.connect(_graph.always, nullabilityNode,
          AlwaysNullableTypeOrigin.forElement(element, false));
    }
    DecoratedTypeParameterBounds.current!.put(element, decoratedBound);
    return null;
  }

  @override
  DecoratedType? visitVariableDeclarationList(VariableDeclarationList node) {
    node.metadata.accept(this);
    var typeAnnotation = node.type;
    var declaredType = _pushNullabilityNodeTarget(
        NullabilityNodeTarget.element(
            node.variables.first.declaredElement!, _getLineInfo),
        () => typeAnnotation?.accept(this));
    var hint = getPrefixHint(node.firstTokenAfterCommentAndMetadata);
    if (hint != null && hint.kind == HintCommentKind.late_) {
      _variables!.recordLateHint(source, node, hint);
    }
    if (hint != null && hint.kind == HintCommentKind.lateFinal) {
      _variables!.recordLateHint(source, node, hint);
    }
    var parent = node.parent;
    for (var variable in node.variables) {
      variable.metadata.accept(this);
      var declaredElement = variable.declaredElement;
      var type = declaredType;
      if (type == null) {
        var target =
            NullabilityNodeTarget.element(declaredElement!, _getLineInfo);
        type = DecoratedType.forImplicitType(
            _typeProvider, declaredElement.type, _graph, target);
        instrumentation?.implicitType(source, node, type);
      }
      _variables!.recordDecoratedElementType(declaredElement, type);
      variable.initializer?.accept(this);
      if (parent is FieldDeclaration) {
        if (_hasAngularChildAnnotation(parent.metadata)) {
          _graph.makeNullable(
              type.node!, AngularAnnotationOrigin(source, node));
        }
      }
    }
    return null;
  }

  DecoratedType _createDecoratedTypeForClass(
      ClassElement classElement, AstNode? node) {
    var typeArguments = classElement.typeParameters
        .map((t) => t.instantiate(nullabilitySuffix: NullabilitySuffix.star))
        .toList();
    var decoratedTypeArguments =
        typeArguments.map((t) => DecoratedType(t, _graph.never)).toList();
    return DecoratedType(
      classElement.instantiate(
        typeArguments: typeArguments,
        nullabilitySuffix: NullabilitySuffix.star,
      ),
      _graph.never,
      typeArguments: decoratedTypeArguments,
    );
  }

  /// Common handling of function and method declarations.
  DecoratedType _handleExecutableDeclaration(
      AstNode node,
      ExecutableElement declaredElement,
      NodeList<Annotation>? metadata,
      TypeAnnotation? returnType,
      TypeParameterList? typeParameters,
      FormalParameterList? parameters,
      NodeList<ConstructorInitializer>? initializers,
      FunctionBody body,
      ConstructorName? redirectedConstructor,
      {required bool isExternal}) {
    metadata?.accept(this);
    var previouslyVisitingExternalDeclaration = _visitingExternalDeclaration;
    try {
      if (isExternal) {
        _visitingExternalDeclaration = true;
      }
      var functionType = declaredElement.type;
      DecoratedType? decoratedReturnType;
      var target = NullabilityNodeTarget.element(declaredElement, _getLineInfo);
      if (returnType != null) {
        _pushNullabilityNodeTarget(target.returnType(), () {
          decoratedReturnType = returnType.accept(this);
        });
      } else if (declaredElement is ConstructorElement) {
        // Constructors have no explicit return type annotation, so use the
        // implicit return type.
        decoratedReturnType = _createDecoratedTypeForClass(
            declaredElement.enclosingElement, parameters!.parent);
        instrumentation?.implicitReturnType(source, node, decoratedReturnType);
      } else {
        // Inferred return type.
        decoratedReturnType = DecoratedType.forImplicitType(
            _typeProvider, functionType.returnType, _graph, target);
        instrumentation?.implicitReturnType(source, node, decoratedReturnType);
        if (isExternal && functionType.returnType.isDynamic) {
          _graph.makeNullableUnion(
              decoratedReturnType.node!, ExternalDynamicOrigin(source, node));
        }
      }
      var previousPositionalParameters = _positionalParameters;
      var previousNamedParameters = _namedParameters;
      _positionalParameters = [];
      _namedParameters = {};
      DecoratedType decoratedFunctionType;
      try {
        typeParameters?.accept(this);
        _pushNullabilityNodeTarget(target, () => parameters?.accept(this));
        redirectedConstructor?.accept(this);
        initializers?.accept(this);
        decoratedFunctionType = DecoratedType(functionType, _graph.never,
            returnType: decoratedReturnType,
            positionalParameters: _positionalParameters,
            namedParameters: _namedParameters);
        body.accept(this);
      } finally {
        _positionalParameters = previousPositionalParameters;
        _namedParameters = previousNamedParameters;
      }
      _variables!
          .recordDecoratedElementType(declaredElement, decoratedFunctionType);
      return decoratedFunctionType;
    } finally {
      _visitingExternalDeclaration = previouslyVisitingExternalDeclaration;
    }
  }

  DecoratedType? _handleFormalParameter(
      FormalParameter node,
      TypeAnnotation? type,
      TypeParameterList? typeParameters,
      FormalParameterList? parameters) {
    var declaredElement = node.declaredElement!;
    node.metadata.accept(this);
    DecoratedType? decoratedType;
    var target = safeTarget;
    if (parameters == null) {
      if (type != null) {
        decoratedType = type.accept(this);
      } else {
        decoratedType = DecoratedType.forImplicitType(
            _typeProvider, declaredElement.type, _graph, target);
        if (_visitingExternalDeclaration) {
          _graph.makeNullableUnion(
              decoratedType.node!, ExternalDynamicOrigin(source, node));
        }
        instrumentation?.implicitType(source, node, decoratedType);
      }
    } else {
      DecoratedType? decoratedReturnType;
      if (type == null) {
        decoratedReturnType = DecoratedType.forImplicitType(_typeProvider,
            DynamicTypeImpl.instance, _graph, target.returnType());
        instrumentation?.implicitReturnType(source, node, decoratedReturnType);
        if (_visitingExternalDeclaration) {
          _graph.makeNullableUnion(
              decoratedReturnType.node!, ExternalDynamicOrigin(source, node));
        }
      } else {
        decoratedReturnType = type.accept(this);
      }
      if (typeParameters != null) {
        // TODO(paulberry)
        _unimplemented(
            typeParameters, 'Function-typed parameter with type parameters');
      }
      var positionalParameters = <DecoratedType?>[];
      var namedParameters = <String, DecoratedType?>{};
      var previousPositionalParameters = _positionalParameters;
      var previousNamedParameters = _namedParameters;
      try {
        _positionalParameters = positionalParameters;
        _namedParameters = namedParameters;
        parameters.accept(this);
      } finally {
        _positionalParameters = previousPositionalParameters;
        _namedParameters = previousNamedParameters;
      }
      final nullabilityNode = NullabilityNode.forTypeAnnotation(target);
      decoratedType = DecoratedType(declaredElement.type, nullabilityNode,
          returnType: decoratedReturnType,
          positionalParameters: positionalParameters,
          namedParameters: namedParameters);
      _handleNullabilityHint(node, decoratedType);
    }
    _variables!.recordDecoratedElementType(declaredElement, decoratedType);
    for (var annotation in node.metadata) {
      var element = annotation.element;
      if (element is ConstructorElement &&
          element.enclosingElement.name == 'Optional' &&
          _isAngularUri(element.librarySource.uri)) {
        _graph.makeNullable(
            decoratedType!.node!, AngularAnnotationOrigin(source, node));
      }
    }
    if (declaredElement.isNamed) {
      _namedParameters![declaredElement.name] = decoratedType;
    } else {
      _positionalParameters!.add(decoratedType);
    }
    return decoratedType;
  }

  /// Nullability hints can be added to [TypeAnnotation]s,
  /// [FunctionTypedFormalParameter]s, and function-typed
  /// [FieldFormalParameter]s.
  void _handleNullabilityHint(AstNode node, DecoratedType decoratedType) {
    assert(node is TypeAnnotation ||
        node is FunctionTypedFormalParameter ||
        (node is FieldFormalParameter && node.parameters != null));
    var hint = getPostfixHint(node.endToken);
    if (hint != null) {
      switch (hint.kind) {
        case HintCommentKind.bang:
          _graph.makeNonNullableUnion(decoratedType.node!,
              NullabilityCommentOrigin(source, node, false));
          _variables!.recordNullabilityHint(source, node, hint);
          decoratedType
                  .node!.hintActions[HintActionKind.removeNonNullableHint] =
              hint.changesToRemove(source!.contents.data);
          decoratedType.node!.hintActions[HintActionKind.changeToNullableHint] =
              hint.changesToReplace(source!.contents.data, '/*?*/');
          break;
        case HintCommentKind.question:
          _graph.makeNullableUnion(decoratedType.node!,
              NullabilityCommentOrigin(source, node, true));
          _variables!.recordNullabilityHint(source, node, hint);
          decoratedType.node!.hintActions[HintActionKind.removeNullableHint] =
              hint.changesToRemove(source!.contents.data);
          decoratedType
                  .node!.hintActions[HintActionKind.changeToNonNullableHint] =
              hint.changesToReplace(source!.contents.data, '/*!*/');
          break;
        default:
          break;
      }

      decoratedType.node!.hintActions
        ..remove(HintActionKind.addNonNullableHint)
        ..remove(HintActionKind.addNullableHint);
    }
  }

  void _handleSupertypeClauses(
      NamedCompilationUnitMember astNode,
      ClassElement declaredElement,
      NamedType? superclass,
      WithClause? withClause,
      ImplementsClause? implementsClause,
      OnClause? onClause) {
    var supertypes = <NamedType?>[];
    supertypes.add(superclass);
    if (withClause != null) {
      supertypes.addAll(withClause.mixinTypes2);
    }
    if (implementsClause != null) {
      supertypes.addAll(implementsClause.interfaces2);
    }
    if (onClause != null) {
      supertypes.addAll(onClause.superclassConstraints2);
    }
    var decoratedSupertypes = <ClassElement, DecoratedType?>{};
    _pushNullabilityNodeTarget(
        NullabilityNodeTarget.element(declaredElement, _getLineInfo).supertype,
        () {
      for (var supertype in supertypes) {
        DecoratedType? decoratedSupertype;
        if (supertype == null) {
          var nullabilityNode =
              NullabilityNode.forInferredType(_target!.withCodeRef(astNode));
          _graph.makeNonNullableUnion(
              nullabilityNode, NonNullableObjectSuperclass(source, astNode));
          decoratedSupertype =
              DecoratedType(_typeProvider.objectType, nullabilityNode);
        } else {
          decoratedSupertype = supertype.accept(this);
        }
        var class_ = (decoratedSupertype!.type as InterfaceType).element;
        decoratedSupertypes[class_] = decoratedSupertype;
      }
    });
    _variables!
        .recordDecoratedDirectSupertypes(declaredElement, decoratedSupertypes);
  }

  /// Determines if the given [metadata] contains a reference to one of the
  /// Angular annotations `ViewChild` or `ContentChild`, either of which implies
  /// nullability of the underlying property.
  bool _hasAngularChildAnnotation(NodeList<Annotation> metadata) {
    for (var annotation in metadata) {
      var element = annotation.element;
      if (element is ConstructorElement) {
        var name = element.enclosingElement.name;
        if ((name == 'ViewChild' || name == 'ContentChild') &&
            _isAngularUri(element.librarySource.uri)) {
          return true;
        }
      }
    }
    return false;
  }

  /// Determines whether the given [uri] comes from the Angular package.
  bool _isAngularUri(Uri uri) {
    if (uri.scheme != 'package') return false;
    var packageName = uri.pathSegments[0];
    if (packageName == 'angular') return true;
    if (packageName == 'third_party.dart_src.angular.angular') {
      // This name is used for angular development internally at Google.
      return true;
    }
    return false;
  }

  T _pushNullabilityNodeTarget<T>(
      NullabilityNodeTarget target, T Function() fn) {
    NullabilityNodeTarget? previousTarget = _target;
    try {
      _target = target;
      return fn();
    } finally {
      _target = previousTarget;
    }
  }

  @alwaysThrows
  void _unimplemented(AstNode node, String message) {
    CompilationUnit unit = node.root as CompilationUnit;
    StringBuffer buffer = StringBuffer();
    buffer.write(message);
    buffer.write(' in "');
    buffer.write(node.toSource());
    buffer.write('" on line ');
    buffer.write(unit.lineInfo!.getLocation(node.offset).lineNumber);
    buffer.write(' of "');
    buffer.write(unit.declaredElement!.source.fullName);
    buffer.write('"');
    throw UnimplementedError(buffer.toString());
  }
}
