|  | // 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/visitor.dart'; | 
|  | import 'package:analyzer/dart/element/element.dart'; | 
|  | import 'package:analyzer/dart/element/nullability_suffix.dart'; | 
|  | import 'package:analyzer/dart/element/scope.dart'; | 
|  | import 'package:analyzer/src/dart/ast/ast.dart'; | 
|  | import 'package:analyzer/src/dart/element/element.dart'; | 
|  | import 'package:analyzer/src/dart/element/scope.dart'; | 
|  | import 'package:analyzer/src/dart/element/type.dart'; | 
|  | import 'package:analyzer/src/dart/element/type_system.dart'; | 
|  | import 'package:analyzer/src/summary2/function_type_builder.dart'; | 
|  | import 'package:analyzer/src/summary2/link.dart'; | 
|  | import 'package:analyzer/src/summary2/linking_node_scope.dart'; | 
|  | import 'package:analyzer/src/summary2/named_type_builder.dart'; | 
|  | import 'package:analyzer/src/summary2/record_type_builder.dart'; | 
|  | import 'package:analyzer/src/summary2/types_builder.dart'; | 
|  | import 'package:analyzer/src/utilities/extensions/element.dart'; | 
|  |  | 
|  | /// Recursive visitor of [LinkedNode]s that resolves explicit type annotations | 
|  | /// in outlines.  This includes resolving element references in identifiers | 
|  | /// in type annotation, and setting [LinkedNodeType]s for corresponding type | 
|  | /// annotation nodes. | 
|  | /// | 
|  | /// Declarations that have type annotations, e.g. return types of methods, get | 
|  | /// the corresponding type set (so, if there is an explicit type annotation, | 
|  | /// the type is set, otherwise we keep it empty, so we will attempt to infer | 
|  | /// it later). | 
|  | class ReferenceResolver extends ThrowingAstVisitor<void> { | 
|  | final Linker linker; | 
|  | final TypeSystemImpl typeSystem; | 
|  | final NodesToBuildType nodesToBuildType; | 
|  |  | 
|  | Scope scope; | 
|  |  | 
|  | ReferenceResolver( | 
|  | this.linker, | 
|  | this.nodesToBuildType, | 
|  | this.typeSystem, | 
|  | this.scope, | 
|  | ); | 
|  |  | 
|  | @override | 
|  | void visitAnnotation(covariant AnnotationImpl node) { | 
|  | if (node.arguments != null) { | 
|  | var identifier = node.name; | 
|  | if (identifier is PrefixedIdentifierImpl) { | 
|  | var prefixNode = identifier.prefix; | 
|  | var prefixElement = scope.lookup(prefixNode.name).getter; | 
|  | prefixNode.staticElement = prefixElement; | 
|  |  | 
|  | if (prefixElement is PrefixElement) { | 
|  | var name = identifier.identifier.name; | 
|  | var element = prefixElement.scope.lookup(name).getter; | 
|  | identifier.identifier.staticElement = element; | 
|  | } | 
|  | } else if (identifier is SimpleIdentifierImpl) { | 
|  | var element = scope.lookup(identifier.name).getter; | 
|  | identifier.staticElement = element; | 
|  | return; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitBlockFunctionBody(BlockFunctionBody node) {} | 
|  |  | 
|  | @override | 
|  | void visitClassDeclaration(ClassDeclaration node) { | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as ClassElementImpl; | 
|  |  | 
|  | scope = TypeParameterScope(scope, element.typeParameters); | 
|  |  | 
|  | node.metadata.accept(this); | 
|  | node.typeParameters?.accept(this); | 
|  | node.extendsClause?.accept(this); | 
|  | node.withClause?.accept(this); | 
|  | node.implementsClause?.accept(this); | 
|  |  | 
|  | scope = InstanceScope(scope, element); | 
|  | LinkingNodeContext(node, scope); | 
|  |  | 
|  | node.members.accept(this); | 
|  | nodesToBuildType.addDeclaration(node); | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitClassTypeAlias(ClassTypeAlias node) { | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as ClassElementImpl; | 
|  |  | 
|  | scope = TypeParameterScope(scope, element.typeParameters); | 
|  | LinkingNodeContext(node, scope); | 
|  |  | 
|  | node.metadata.accept(this); | 
|  | node.typeParameters?.accept(this); | 
|  | node.superclass.accept(this); | 
|  | node.withClause.accept(this); | 
|  | node.implementsClause?.accept(this); | 
|  | nodesToBuildType.addDeclaration(node); | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitCompilationUnit(CompilationUnit node) { | 
|  | LinkingNodeContext(node, scope); | 
|  | node.declarations.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitConstructorDeclaration(ConstructorDeclaration node) { | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as ConstructorElementImpl; | 
|  |  | 
|  | scope = TypeParameterScope(scope, element.typeParameters); | 
|  | LinkingNodeContext(node, scope); | 
|  |  | 
|  | node.metadata.accept(this); | 
|  | node.parameters.accept(this); | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitDefaultFormalParameter(DefaultFormalParameter node) { | 
|  | node.parameter.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitEnumDeclaration(EnumDeclaration node) { | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as EnumElementImpl; | 
|  |  | 
|  | scope = TypeParameterScope(scope, element.typeParameters); | 
|  |  | 
|  | node.metadata.accept(this); | 
|  | node.typeParameters?.accept(this); | 
|  | node.implementsClause?.accept(this); | 
|  | node.withClause?.accept(this); | 
|  |  | 
|  | scope = InstanceScope(scope, element); | 
|  | LinkingNodeContext(node, scope); | 
|  |  | 
|  | node.members.accept(this); | 
|  | nodesToBuildType.addDeclaration(node); | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitExpressionFunctionBody(ExpressionFunctionBody node) {} | 
|  |  | 
|  | @override | 
|  | void visitExtendsClause(ExtendsClause node) { | 
|  | node.superclass.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitExtensionDeclaration(ExtensionDeclaration node) { | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as ExtensionElementImpl; | 
|  |  | 
|  | scope = TypeParameterScope(scope, element.typeParameters); | 
|  |  | 
|  | node.metadata.accept(this); | 
|  | node.typeParameters?.accept(this); | 
|  | node.onClause?.accept(this); | 
|  |  | 
|  | scope = ExtensionScope(scope, element); | 
|  | LinkingNodeContext(node, scope); | 
|  |  | 
|  | node.members.accept(this); | 
|  | nodesToBuildType.addDeclaration(node); | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitExtensionOnClause(ExtensionOnClause node) { | 
|  | node.extendedType.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitExtensionTypeDeclaration(ExtensionTypeDeclaration node) { | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as ExtensionTypeElementImpl; | 
|  |  | 
|  | scope = TypeParameterScope(scope, element.typeParameters); | 
|  |  | 
|  | node.metadata.accept(this); | 
|  | node.typeParameters?.accept(this); | 
|  | node.representation.accept(this); | 
|  | node.implementsClause?.accept(this); | 
|  |  | 
|  | scope = InstanceScope(scope, element); | 
|  | LinkingNodeContext(node, scope); | 
|  | LinkingNodeContext(node.representation, scope); | 
|  |  | 
|  | node.members.accept(this); | 
|  | nodesToBuildType.addDeclaration(node); | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitFieldDeclaration(FieldDeclaration node) { | 
|  | node.metadata.accept(this); | 
|  | node.fields.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitFieldFormalParameter(FieldFormalParameter node) { | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as FieldFormalParameterElementImpl; | 
|  |  | 
|  | scope = TypeParameterScope(scope, element.typeParameters); | 
|  |  | 
|  | node.type?.accept(this); | 
|  | node.typeParameters?.accept(this); | 
|  | node.parameters?.accept(this); | 
|  | nodesToBuildType.addDeclaration(node); | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitFormalParameterList(FormalParameterList node) { | 
|  | node.parameters.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitFunctionDeclaration(FunctionDeclaration node) { | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as ExecutableElementImpl; | 
|  |  | 
|  | scope = TypeParameterScope(outerScope, element.typeParameters); | 
|  | LinkingNodeContext(node, scope); | 
|  |  | 
|  | node.metadata.accept(this); | 
|  | node.returnType?.accept(this); | 
|  | node.functionExpression.accept(this); | 
|  | nodesToBuildType.addDeclaration(node); | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitFunctionExpression(FunctionExpression node) { | 
|  | node.typeParameters?.accept(this); | 
|  | node.parameters?.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitFunctionTypeAlias(FunctionTypeAlias node) { | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as TypeAliasElementImpl; | 
|  |  | 
|  | scope = TypeParameterScope(outerScope, element.typeParameters); | 
|  |  | 
|  | node.returnType?.accept(this); | 
|  | node.typeParameters?.accept(this); | 
|  | node.parameters.accept(this); | 
|  |  | 
|  | nodesToBuildType.addDeclaration(node); | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as ParameterElementImpl; | 
|  |  | 
|  | scope = TypeParameterScope(scope, element.typeParameters); | 
|  |  | 
|  | node.returnType?.accept(this); | 
|  | node.typeParameters?.accept(this); | 
|  | node.parameters.accept(this); | 
|  | nodesToBuildType.addDeclaration(node); | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitGenericFunctionType(GenericFunctionType node) { | 
|  | var nodeImpl = node as GenericFunctionTypeImpl; | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as GenericFunctionTypeElementImpl; | 
|  | scope = TypeParameterScope(outerScope, element.typeParameters); | 
|  |  | 
|  | node.returnType?.accept(this); | 
|  | node.typeParameters?.accept(this); | 
|  | node.parameters.accept(this); | 
|  |  | 
|  | var nullabilitySuffix = _getNullabilitySuffix(node.question != null); | 
|  | var builder = FunctionTypeBuilder.of(nodeImpl, nullabilitySuffix); | 
|  | nodeImpl.type = builder; | 
|  | nodesToBuildType.addDeclaration(node); | 
|  | nodesToBuildType.addTypeBuilder(builder); | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitGenericTypeAlias(GenericTypeAlias node) { | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as TypeAliasElementImpl; | 
|  |  | 
|  | scope = TypeParameterScope(outerScope, element.typeParameters); | 
|  |  | 
|  | node.metadata.accept(this); | 
|  | node.typeParameters?.accept(this); | 
|  | node.type.accept(this); | 
|  | nodesToBuildType.addDeclaration(node); | 
|  |  | 
|  | var aliasedType = node.type; | 
|  | if (aliasedType is GenericFunctionTypeImpl) { | 
|  | element.encloseElement( | 
|  | aliasedType.declaredElement as GenericFunctionTypeElementImpl, | 
|  | ); | 
|  | } | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitImplementsClause(ImplementsClause node) { | 
|  | node.interfaces.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitMethodDeclaration(MethodDeclaration node) { | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as ExecutableElementImpl; | 
|  |  | 
|  | scope = TypeParameterScope(scope, element.typeParameters); | 
|  | LinkingNodeContext(node, scope); | 
|  |  | 
|  | node.metadata.accept(this); | 
|  | node.returnType?.accept(this); | 
|  | node.typeParameters?.accept(this); | 
|  | node.parameters?.accept(this); | 
|  | nodesToBuildType.addDeclaration(node); | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitMixinDeclaration(MixinDeclaration node) { | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as MixinElementImpl; | 
|  |  | 
|  | scope = TypeParameterScope(scope, element.typeParameters); | 
|  |  | 
|  | node.metadata.accept(this); | 
|  | node.typeParameters?.accept(this); | 
|  | node.onClause?.accept(this); | 
|  | node.implementsClause?.accept(this); | 
|  |  | 
|  | scope = InstanceScope(scope, element); | 
|  | LinkingNodeContext(node, scope); | 
|  |  | 
|  | node.members.accept(this); | 
|  | nodesToBuildType.addDeclaration(node); | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitMixinOnClause(MixinOnClause node) { | 
|  | node.superclassConstraints.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitNamedType(covariant NamedTypeImpl node) { | 
|  | Element? element; | 
|  | var importPrefix = node.importPrefix; | 
|  | if (importPrefix != null) { | 
|  | var prefixToken = importPrefix.name; | 
|  | var prefixName = prefixToken.lexeme; | 
|  | var prefixElement = scope.lookup(prefixName).getter; | 
|  | importPrefix.element = prefixElement; | 
|  |  | 
|  | if (prefixElement is PrefixElement) { | 
|  | var name = node.name2.lexeme; | 
|  | element = prefixElement.scope.lookup(name).getter; | 
|  | } | 
|  | } else { | 
|  | var name = node.name2.lexeme; | 
|  |  | 
|  | if (name == 'void') { | 
|  | node.type = VoidTypeImpl.instance; | 
|  | return; | 
|  | } | 
|  |  | 
|  | element = scope.lookup(name).getter; | 
|  | } | 
|  | node.element2 = element.asElement2; | 
|  |  | 
|  | node.typeArguments?.accept(this); | 
|  |  | 
|  | var nullabilitySuffix = _getNullabilitySuffix(node.question != null); | 
|  | if (element == null) { | 
|  | node.type = InvalidTypeImpl.instance; | 
|  | } else if (element is TypeParameterElement) { | 
|  | node.type = TypeParameterTypeImpl( | 
|  | element: element, | 
|  | nullabilitySuffix: nullabilitySuffix, | 
|  | ); | 
|  | } else { | 
|  | var builder = NamedTypeBuilder.of( | 
|  | linker, | 
|  | typeSystem, | 
|  | node, | 
|  | element, | 
|  | nullabilitySuffix, | 
|  | ); | 
|  | node.type = builder; | 
|  | nodesToBuildType.addTypeBuilder(builder); | 
|  | } | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitRecordTypeAnnotation(covariant RecordTypeAnnotationImpl node) { | 
|  | node.positionalFields.accept(this); | 
|  | node.namedFields?.accept(this); | 
|  |  | 
|  | var builder = RecordTypeBuilder.of(typeSystem, node); | 
|  | node.type = builder; | 
|  | nodesToBuildType.addTypeBuilder(builder); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitRecordTypeAnnotationNamedField( | 
|  | RecordTypeAnnotationNamedField node, | 
|  | ) { | 
|  | node.type.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitRecordTypeAnnotationNamedFields( | 
|  | RecordTypeAnnotationNamedFields node, | 
|  | ) { | 
|  | node.fields.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitRecordTypeAnnotationPositionalField( | 
|  | RecordTypeAnnotationPositionalField node, | 
|  | ) { | 
|  | node.type.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitRepresentationDeclaration(RepresentationDeclaration node) { | 
|  | node.fieldType.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitSimpleFormalParameter(SimpleFormalParameter node) { | 
|  | node.type?.accept(this); | 
|  | nodesToBuildType.addDeclaration(node); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitSuperFormalParameter(SuperFormalParameter node) { | 
|  | var outerScope = scope; | 
|  |  | 
|  | var element = node.declaredElement as SuperFormalParameterElementImpl; | 
|  |  | 
|  | scope = TypeParameterScope(scope, element.typeParameters); | 
|  |  | 
|  | node.type?.accept(this); | 
|  | node.typeParameters?.accept(this); | 
|  | node.parameters?.accept(this); | 
|  | nodesToBuildType.addDeclaration(node); | 
|  |  | 
|  | scope = outerScope; | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { | 
|  | node.metadata.accept(this); | 
|  | node.variables.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitTypeArgumentList(TypeArgumentList node) { | 
|  | node.arguments.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitTypeParameter(TypeParameter node) { | 
|  | var bound = node.bound; | 
|  | if (bound != null) { | 
|  | bound.accept(this); | 
|  | var element = node.declaredElement as TypeParameterElementImpl; | 
|  | element.bound = bound.type; | 
|  | nodesToBuildType.addDeclaration(node); | 
|  | } | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitTypeParameterList(TypeParameterList node) { | 
|  | node.typeParameters.accept(this); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitVariableDeclarationList(VariableDeclarationList node) { | 
|  | node.type?.accept(this); | 
|  | nodesToBuildType.addDeclaration(node); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void visitWithClause(WithClause node) { | 
|  | node.mixinTypes.accept(this); | 
|  | } | 
|  |  | 
|  | NullabilitySuffix _getNullabilitySuffix(bool hasQuestion) { | 
|  | if (hasQuestion) { | 
|  | return NullabilitySuffix.question; | 
|  | } else { | 
|  | return NullabilitySuffix.none; | 
|  | } | 
|  | } | 
|  | } |