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

  /// 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.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);
    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?.superclass,
        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.superclass,
        node.withClause, node.implementsClause, null);
    for (var constructorElement in classElement.constructors) {
      assert(constructorElement.isSynthetic);
      var decoratedReturnType =
          _createDecoratedTypeForClass(classElement, node);
      var target = NullabilityNodeTarget.element(constructorElement);
      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.type.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);
    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);
      _variables!.recordDecoratedElementType(declaredElement,
          DecoratedType(classElement.thisType, makeNonNullNode(target, item)));
    }
    final valuesGetter = classElement.getGetter('values')!;
    var valuesTarget = NullabilityNodeTarget.element(valuesGetter);
    _variables!.recordDecoratedElementType(
        valuesGetter,
        DecoratedType(valuesGetter.type, makeNonNullNode(valuesTarget),
            returnType: DecoratedType(valuesGetter.returnType,
                makeNonNullNode(valuesTarget.returnType()),
                typeArguments: [
                  DecoratedType(classElement.thisType,
                      makeNonNullNode(valuesTarget.typeArgument(0)))
                ])));
    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);
    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!);
    _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 (_getAngularAnnotation(node.metadata) == _AngularAnnotation.child) {
          _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!),
        () => 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!);
        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) {
        var angularAnnotation = _getAngularAnnotation(parent.metadata);
        if (angularAnnotation != null) {
          switch (angularAnnotation) {
            case _AngularAnnotation.child:
              _graph.makeNullable(
                  type.node!, AngularAnnotationOrigin(source, node));
              break;
            case _AngularAnnotation.children:
              _graph.preventLate(
                  type.node!, AngularAnnotationOrigin(source, node));
              break;
          }
        }
      }
    }
    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,
    );
  }

  /// Determines if the given [metadata] contains a reference to one of the
  /// Angular annotations that we have special behaviors for.  If it does,
  /// returns an enumerated value describing the type of annotation.
  _AngularAnnotation? _getAngularAnnotation(NodeList<Annotation> metadata) {
    for (var annotation in metadata) {
      var element = annotation.element;
      if (element is ConstructorElement) {
        var name = element.enclosingElement.name;
        if (_isAngularUri(element.librarySource.uri)) {
          if (name == 'ViewChild' || name == 'ContentChild') {
            return _AngularAnnotation.child;
          } else if (name == 'ViewChildren' || name == 'ContentChildren') {
            return _AngularAnnotation.children;
          }
        }
      }
    }
    return null;
  }

  /// 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);
      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.mixinTypes);
    }
    if (implementsClause != null) {
      supertypes.addAll(implementsClause.interfaces);
    }
    if (onClause != null) {
      supertypes.addAll(onClause.superclassConstraints);
    }
    var decoratedSupertypes = <ClassElement, DecoratedType?>{};
    _pushNullabilityNodeTarget(
        NullabilityNodeTarget.element(declaredElement).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 whether the given [uri] comes from the Angular package.
  bool _isAngularUri(Uri uri) {
    if (!uri.isScheme('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());
  }
}

/// Enum describing the kinds of annotations supplied by the angular package for
/// which we have special migration behaviors.
enum _AngularAnnotation {
  /// Either the `@ViewChild` or `@ContentChild` annotation.  Fields with these
  /// annotations should always be nullable and should never be late.
  child,

  /// Either the `@ViewChildren` or `@ContentChildren` annotation.  Fields with
  /// these annotations should never be late.
  children,
}
