blob: 552f46c288b24f33439ba7655c3f1a0608d052a3 [file] [log] [blame]
// 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/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary2/ast_binary_reader.dart';
import 'package:analyzer/src/summary2/lazy_ast.dart';
import 'package:analyzer/src/summary2/linked_bundle_context.dart';
import 'package:analyzer/src/summary2/reference.dart';
/// The context of a unit - the context of the bundle, and the unit tokens.
class LinkedUnitContext {
final LinkedBundleContext bundleContext;
final LinkedLibraryContext libraryContext;
final int indexInLibrary;
final String uriStr;
final Reference reference;
final bool isSynthetic;
final LinkedNodeUnit data;
/// This list is filled lazily with [GenericFunctionType] nodes as they
/// are requested by [getGenericFunctionType].
List<GenericFunctionType> _genericFunctionTypeNodeList;
AstBinaryReader _astReader;
CompilationUnit _unit;
bool _hasDirectivesRead = false;
/// Mapping from identifiers to synthetic type parameters.
///
/// Synthetic type parameters are added when [readType] begins reading a
/// [FunctionType], and removed when reading is done.
final Map<int, TypeParameterElementImpl> _typeParameters = {};
int _nextSyntheticTypeParameterId = 0x10000;
LinkedUnitContext(
this.bundleContext,
this.libraryContext,
this.indexInLibrary,
this.uriStr,
this.reference,
this.isSynthetic,
this.data,
{CompilationUnit unit}) {
_astReader = AstBinaryReader(this);
_astReader.isLazy = unit == null;
if (data != null) {
_genericFunctionTypeNodeList = List<GenericFunctionType>(
data.genericFunctionTypes.length,
);
}
_unit = unit;
_hasDirectivesRead = _unit != null;
}
bool get hasPartOfDirective {
for (var directive in unit_withDirectives.directives) {
if (directive is PartOfDirective) {
return true;
}
}
return false;
}
/// Return `true` if this unit is a part of a bundle that is being linked.
bool get isLinking => bundleContext.isLinking;
bool get isNNBD {
if (data != null) return data.isNNBD;
return _unit.featureSet.isEnabled(Feature.non_nullable);
}
TypeProvider get typeProvider =>
bundleContext.elementFactory.analysisContext.typeProvider;
CompilationUnit get unit => _unit;
CompilationUnit get unit_withDeclarations {
if (_unit == null) {
_unit = _astReader.readNode(data.node);
_unit.lineInfo = LineInfo(data.lineStarts);
}
return _unit;
}
CompilationUnit get unit_withDirectives {
if (!_hasDirectivesRead) {
var directiveDataList = data.node.compilationUnit_directives;
for (var i = 0; i < directiveDataList.length; ++i) {
var directiveData = directiveDataList[i];
_unit.directives[i] = _astReader.readNode(directiveData);
}
_hasDirectivesRead = true;
}
return _unit;
}
/// Return the [LibraryElement] referenced in the [node].
LibraryElement directiveLibrary(UriBasedDirective node) {
var uriStr = LazyDirective.getSelectedUri(node);
if (uriStr == null || uriStr.isEmpty) return null;
return bundleContext.elementFactory.libraryOfUri(uriStr);
}
int getCodeLength(AstNode node) {
if (node is ClassDeclaration) {
return LazyClassDeclaration.getCodeLength(_astReader, node);
} else if (node is ClassTypeAlias) {
return LazyClassTypeAlias.getCodeLength(_astReader, node);
} else if (node is CompilationUnit) {
if (data != null) {
return data.node.codeLength;
} else {
return node.length;
}
} else if (node is ConstructorDeclaration) {
return LazyConstructorDeclaration.getCodeLength(_astReader, node);
} else if (node is EnumDeclaration) {
return LazyEnumDeclaration.getCodeLength(_astReader, node);
} else if (node is FormalParameter) {
return LazyFormalParameter.getCodeLength(_astReader, node);
} else if (node is FunctionDeclaration) {
return LazyFunctionDeclaration.getCodeLength(_astReader, node);
} else if (node is FunctionTypeAliasImpl) {
return LazyFunctionTypeAlias.getCodeLength(_astReader, node);
} else if (node is GenericTypeAlias) {
return LazyGenericTypeAlias.getCodeLength(_astReader, node);
} else if (node is MethodDeclaration) {
return LazyMethodDeclaration.getCodeLength(_astReader, node);
} else if (node is MixinDeclaration) {
return LazyMixinDeclaration.getCodeLength(_astReader, node);
} else if (node is TypeParameter) {
return LazyTypeParameter.getCodeLength(_astReader, node);
} else if (node is VariableDeclaration) {
return LazyVariableDeclaration.getCodeLength(_astReader, node);
}
throw UnimplementedError('${node.runtimeType}');
}
int getCodeOffset(AstNode node) {
if (node is ClassDeclaration) {
return LazyClassDeclaration.getCodeOffset(_astReader, node);
} else if (node is ClassTypeAlias) {
return LazyClassTypeAlias.getCodeOffset(_astReader, node);
} else if (node is CompilationUnit) {
return 0;
} else if (node is ConstructorDeclaration) {
return LazyConstructorDeclaration.getCodeOffset(_astReader, node);
} else if (node is EnumDeclaration) {
return LazyEnumDeclaration.getCodeOffset(_astReader, node);
} else if (node is FormalParameter) {
return LazyFormalParameter.getCodeOffset(_astReader, node);
} else if (node is FunctionDeclaration) {
return LazyFunctionDeclaration.getCodeOffset(_astReader, node);
} else if (node is FunctionTypeAliasImpl) {
return LazyFunctionTypeAlias.getCodeOffset(_astReader, node);
} else if (node is GenericTypeAlias) {
return LazyGenericTypeAlias.getCodeOffset(_astReader, node);
} else if (node is MethodDeclaration) {
return LazyMethodDeclaration.getCodeOffset(_astReader, node);
} else if (node is MixinDeclaration) {
return LazyMixinDeclaration.getCodeOffset(_astReader, node);
} else if (node is TypeParameter) {
return LazyTypeParameter.getCodeOffset(_astReader, node);
} else if (node is VariableDeclaration) {
return LazyVariableDeclaration.getCodeOffset(_astReader, node);
}
throw UnimplementedError('${node.runtimeType}');
}
List<ConstructorInitializer> getConstructorInitializers(
ConstructorDeclaration node,
) {
LazyConstructorDeclaration.readInitializers(_astReader, node);
return node.initializers;
}
ConstructorName getConstructorRedirected(ConstructorDeclaration node) {
LazyConstructorDeclaration.readRedirectedConstructor(_astReader, node);
return node.redirectedConstructor;
}
Iterable<ConstructorDeclaration> getConstructors(AstNode node) sync* {
if (node is ClassOrMixinDeclaration) {
var members = _getClassOrMixinMembers(node);
for (var member in members) {
if (member is ConstructorDeclaration) {
yield member;
}
}
}
}
DartType getDefaultType(TypeParameter node) {
return LazyTypeParameter.getDefaultType(_astReader, node);
}
String getDefaultValueCode(AstNode node) {
if (node is DefaultFormalParameter) {
LazyFormalParameter.readDefaultValue(_astReader, node);
return node.defaultValue?.toString();
}
return null;
}
int getDirectiveOffset(AstNode node) {
return LazyDirective.getNameOffset(node);
}
Comment getDocumentationComment(AstNode node) {
if (node is ClassDeclaration) {
LazyClassDeclaration.readDocumentationComment(_astReader, node);
return node.documentationComment;
} else if (node is ClassTypeAlias) {
LazyClassTypeAlias.readDocumentationComment(_astReader, node);
return node.documentationComment;
} else if (node is ConstructorDeclaration) {
LazyConstructorDeclaration.readDocumentationComment(_astReader, node);
return node.documentationComment;
} else if (node is EnumConstantDeclaration) {
LazyEnumConstantDeclaration.readDocumentationComment(_astReader, node);
return node.documentationComment;
} else if (node is EnumDeclaration) {
LazyEnumDeclaration.readDocumentationComment(_astReader, node);
return node.documentationComment;
} else if (node is FunctionDeclaration) {
LazyFunctionDeclaration.readDocumentationComment(_astReader, node);
return node.documentationComment;
} else if (node is FunctionTypeAlias) {
LazyFunctionTypeAlias.readDocumentationComment(_astReader, node);
return node.documentationComment;
} else if (node is GenericTypeAlias) {
LazyGenericTypeAlias.readDocumentationComment(_astReader, node);
return node.documentationComment;
} else if (node is MethodDeclaration) {
LazyMethodDeclaration.readDocumentationComment(_astReader, node);
return node.documentationComment;
} else if (node is MixinDeclaration) {
LazyMixinDeclaration.readDocumentationComment(_astReader, node);
return node.documentationComment;
} else if (node is VariableDeclaration) {
var parent2 = node.parent.parent;
if (parent2 is FieldDeclaration) {
LazyFieldDeclaration.readDocumentationComment(_astReader, parent2);
return parent2.documentationComment;
} else if (parent2 is TopLevelVariableDeclaration) {
LazyTopLevelVariableDeclaration.readDocumentationComment(
_astReader,
parent2,
);
return parent2.documentationComment;
} else {
throw UnimplementedError('${parent2.runtimeType}');
}
} else {
throw UnimplementedError('${node.runtimeType}');
}
}
List<EnumConstantDeclaration> getEnumConstants(EnumDeclaration node) {
LazyEnumDeclaration.readConstants(_astReader, node);
return node.constants;
}
String getFieldFormalParameterName(AstNode node) {
if (node is DefaultFormalParameter) {
return getFieldFormalParameterName(node.parameter);
} else if (node is FieldFormalParameter) {
return node.identifier.name;
} else {
throw StateError('${node.runtimeType}');
}
}
Iterable<VariableDeclaration> getFields(ClassOrMixinDeclaration node) sync* {
var members = _getClassOrMixinMembers(node);
for (var member in members) {
if (member is FieldDeclaration) {
for (var field in member.fields.variables) {
yield field;
}
}
}
}
List<FormalParameter> getFormalParameters(AstNode node) {
if (node is ConstructorDeclaration) {
LazyConstructorDeclaration.readFormalParameters(_astReader, node);
return node.parameters.parameters;
} else if (node is FunctionDeclaration) {
LazyFunctionDeclaration.readFunctionExpression(_astReader, node);
return getFormalParameters(node.functionExpression);
} else if (node is FunctionExpression) {
LazyFunctionExpression.readFormalParameters(_astReader, node);
return node.parameters?.parameters;
} else if (node is FormalParameter) {
if (node is DefaultFormalParameter) {
return getFormalParameters(node.parameter);
} else if (node is FieldFormalParameter) {
LazyFormalParameter.readFormalParameters(_astReader, node);
return node.parameters?.parameters;
} else if (node is FunctionTypedFormalParameter) {
LazyFormalParameter.readFormalParameters(_astReader, node);
return node.parameters.parameters;
} else {
return null;
}
} else if (node is FunctionTypeAlias) {
LazyFunctionTypeAlias.readFormalParameters(_astReader, node);
return node.parameters.parameters;
} else if (node is GenericFunctionType) {
LazyGenericFunctionType.readFormalParameters(_astReader, node);
return node.parameters.parameters;
} else if (node is MethodDeclaration) {
LazyMethodDeclaration.readFormalParameters(_astReader, node);
return node.parameters?.parameters;
} else {
throw UnimplementedError('${node.runtimeType}');
}
}
GenericFunctionTypeImpl getGenericFunctionType(int id) {
GenericFunctionTypeImpl node = _genericFunctionTypeNodeList[id];
if (node == null) {
var data = this.data.genericFunctionTypes[id];
node = _astReader.readGenericFunctionType(data);
LazyAst.setGenericFunctionTypeId(node, id);
_genericFunctionTypeNodeList[id] = node;
var containerRef = this.reference.getChild('@genericFunctionType');
var reference = containerRef.getChild('$id');
var element = GenericFunctionTypeElementImpl.forLinkedNode(
this.reference.element,
reference,
node,
);
node.declaredElement = element;
}
return node;
}
Reference getGenericFunctionTypeReference(GenericFunctionType node) {
var containerRef = reference.getChild('@genericFunctionType');
var id = LazyAst.getGenericFunctionTypeId(node);
return containerRef.getChild('$id');
}
GenericFunctionType getGeneticTypeAliasFunction(GenericTypeAlias node) {
LazyGenericTypeAlias.readFunctionType(_astReader, node);
return node.functionType;
}
bool getHasTypedefSelfReference(AstNode node) {
if (node is FunctionTypeAlias) {
return LazyFunctionTypeAlias.getHasSelfReference(node);
} else if (node is GenericTypeAlias) {
return LazyGenericTypeAlias.getHasSelfReference(node);
}
return false;
}
ImplementsClause getImplementsClause(AstNode node) {
if (node is ClassDeclaration) {
LazyClassDeclaration.readImplementsClause(_astReader, node);
return node.implementsClause;
} else if (node is ClassTypeAlias) {
LazyClassTypeAlias.readImplementsClause(_astReader, node);
return node.implementsClause;
} else if (node is MixinDeclaration) {
LazyMixinDeclaration.readImplementsClause(_astReader, node);
return node.implementsClause;
} else {
throw UnimplementedError('${node.runtimeType}');
}
}
bool getInheritsCovariant(AstNode node) {
if (node is DefaultFormalParameter) {
return getInheritsCovariant(node.parameter);
} else if (node is FormalParameter) {
return LazyAst.getInheritsCovariant(node);
} else if (node is VariableDeclaration) {
return LazyAst.getInheritsCovariant(node);
} else {
throw StateError('${node.runtimeType}');
}
}
InterfaceType getInterfaceType(LinkedNodeType linkedType) {
var type = readType(linkedType);
if (type is InterfaceType && !type.element.isEnum) {
return type;
}
return null;
}
Comment getLibraryDocumentationComment(CompilationUnit unit) {
for (var directive in unit.directives) {
if (directive is LibraryDirective) {
return directive.documentationComment;
}
}
return null;
}
List<Annotation> getLibraryMetadata(CompilationUnit unit) {
for (var directive in unit.directives) {
if (directive is LibraryDirective) {
return getMetadata(directive);
}
}
return const <Annotation>[];
}
List<Annotation> getMetadata(AstNode node) {
if (node is ClassDeclaration) {
LazyClassDeclaration.readMetadata(_astReader, node);
return node.metadata;
} else if (node is ClassTypeAlias) {
LazyClassTypeAlias.readMetadata(_astReader, node);
return node.metadata;
} else if (node is CompilationUnit) {
assert(node == _unit);
if (indexInLibrary != 0) {
return _getPartDirectiveAnnotation();
} else {
return const <Annotation>[];
}
} else if (node is ConstructorDeclaration) {
LazyConstructorDeclaration.readMetadata(_astReader, node);
return node.metadata;
} else if (node is DefaultFormalParameter) {
return getMetadata(node.parameter);
} else if (node is Directive) {
LazyDirective.readMetadata(_astReader, node);
return node.metadata;
} else if (node is EnumConstantDeclaration) {
LazyEnumConstantDeclaration.readMetadata(_astReader, node);
return node.metadata;
} else if (node is EnumDeclaration) {
LazyEnumDeclaration.readMetadata(_astReader, node);
return node.metadata;
} else if (node is FormalParameter) {
LazyFormalParameter.readMetadata(_astReader, node);
return node.metadata;
} else if (node is FunctionDeclaration) {
LazyFunctionDeclaration.readMetadata(_astReader, node);
return node.metadata;
} else if (node is FunctionTypeAlias) {
LazyFunctionTypeAlias.readMetadata(_astReader, node);
return node.metadata;
} else if (node is GenericTypeAlias) {
LazyGenericTypeAlias.readMetadata(_astReader, node);
return node.metadata;
} else if (node is MethodDeclaration) {
LazyMethodDeclaration.readMetadata(_astReader, node);
return node.metadata;
} else if (node is MixinDeclaration) {
LazyMixinDeclaration.readMetadata(_astReader, node);
return node.metadata;
} else if (node is TypeParameter) {
LazyTypeParameter.readMetadata(_astReader, node);
return node.metadata;
} else if (node is VariableDeclaration) {
var parent2 = node.parent.parent;
if (parent2 is FieldDeclaration) {
LazyFieldDeclaration.readMetadata(_astReader, parent2);
return parent2.metadata;
} else if (parent2 is TopLevelVariableDeclaration) {
LazyTopLevelVariableDeclaration.readMetadata(_astReader, parent2);
return parent2.metadata;
}
}
return const <Annotation>[];
}
Iterable<MethodDeclaration> getMethods(AstNode node) sync* {
if (node is ClassOrMixinDeclaration) {
var members = _getClassOrMixinMembers(node);
for (var member in members) {
if (member is MethodDeclaration) {
yield member;
}
}
}
}
List<String> getMixinSuperInvokedNames(MixinDeclaration node) {
return LazyMixinDeclaration.get(node).getSuperInvokedNames();
}
int getNameOffset(AstNode node) {
if (node is ConstructorDeclaration) {
if (node.name != null) {
return node.name.offset;
} else {
return node.returnType.offset;
}
} else if (node is EnumConstantDeclaration) {
return node.name.offset;
} else if (node is FormalParameter) {
return node.identifier?.offset ?? -1;
} else if (node is MethodDeclaration) {
return node.name.offset;
} else if (node is NamedCompilationUnitMember) {
return node.name.offset;
} else if (node is TypeParameter) {
return node.name.offset;
} else if (node is VariableDeclaration) {
return node.name.offset;
}
throw UnimplementedError('${node.runtimeType}');
}
OnClause getOnClause(MixinDeclaration node) {
LazyMixinDeclaration.readOnClause(_astReader, node);
return node.onClause;
}
/// Return the actual return type for the [node] - explicit or inferred.
DartType getReturnType(AstNode node) {
if (node is FunctionDeclaration) {
return LazyFunctionDeclaration.getReturnType(_astReader, node);
} else if (node is FunctionTypeAlias) {
return LazyFunctionTypeAlias.getReturnType(_astReader, node);
} else if (node is GenericFunctionType) {
return LazyGenericFunctionType.getReturnType(_astReader, node);
} else if (node is MethodDeclaration) {
return LazyMethodDeclaration.getReturnType(_astReader, node);
} else {
throw UnimplementedError('${node.runtimeType}');
}
}
TypeAnnotation getReturnTypeNode(AstNode node) {
if (node is FunctionTypeAlias) {
LazyFunctionTypeAlias.readReturnTypeNode(_astReader, node);
return node.returnType;
} else if (node is GenericFunctionType) {
LazyGenericFunctionType.readReturnTypeNode(_astReader, node);
return node.returnType;
} else if (node is FunctionDeclaration) {
LazyFunctionDeclaration.readReturnTypeNode(_astReader, node);
return node.returnType;
} else if (node is MethodDeclaration) {
LazyMethodDeclaration.readReturnTypeNode(_astReader, node);
return node.returnType;
} else {
throw UnimplementedError('${node.runtimeType}');
}
}
String getSelectedUri(UriBasedDirective node) {
return LazyDirective.getSelectedUri(node);
}
String getStringContent(LinkedNode node) {
return node.simpleStringLiteral_value;
}
TypeName getSuperclass(AstNode node) {
if (node is ClassDeclaration) {
LazyClassDeclaration.readExtendsClause(_astReader, node);
return node.extendsClause?.superclass;
} else if (node is ClassTypeAlias) {
LazyClassTypeAlias.readSuperclass(_astReader, node);
return node.superclass;
} else {
throw StateError('${node.runtimeType}');
}
}
/// Return the actual type for the [node] - explicit or inferred.
DartType getType(AstNode node) {
if (node is DefaultFormalParameter) {
return getType(node.parameter);
} else if (node is FormalParameter) {
return LazyFormalParameter.getType(_astReader, node);
} else if (node is VariableDeclaration) {
return LazyVariableDeclaration.getType(_astReader, node);
} else {
throw UnimplementedError('${node.runtimeType}');
}
}
TopLevelInferenceError getTypeInferenceError(AstNode node) {
if (node is DefaultFormalParameter) {
return getTypeInferenceError(node.parameter);
} else if (node is SimpleFormalParameter) {
return LazyFormalParameter.getTypeInferenceError(node);
} else if (node is VariableDeclaration) {
return LazyVariableDeclaration.getTypeInferenceError(node);
} else {
return null;
}
}
TypeAnnotation getTypeParameterBound(TypeParameter node) {
LazyTypeParameter.readBound(_astReader, node);
return node.bound;
}
TypeParameterList getTypeParameters2(AstNode node) {
if (node is ClassDeclaration) {
return node.typeParameters;
} else if (node is ClassTypeAlias) {
return node.typeParameters;
} else if (node is ConstructorDeclaration) {
return null;
} else if (node is DefaultFormalParameter) {
return getTypeParameters2(node.parameter);
} else if (node is FieldFormalParameter) {
return null;
} else if (node is FunctionDeclaration) {
LazyFunctionDeclaration.readFunctionExpression(_astReader, node);
return getTypeParameters2(node.functionExpression);
} else if (node is FunctionExpression) {
return node.typeParameters;
} else if (node is FunctionTypedFormalParameter) {
return node.typeParameters;
} else if (node is FunctionTypeAlias) {
return node.typeParameters;
} else if (node is GenericFunctionType) {
return node.typeParameters;
} else if (node is GenericTypeAlias) {
return node.typeParameters;
} else if (node is MethodDeclaration) {
return node.typeParameters;
} else if (node is MixinDeclaration) {
return node.typeParameters;
} else if (node is SimpleFormalParameter) {
return null;
} else {
throw UnimplementedError('${node.runtimeType}');
}
}
WithClause getWithClause(AstNode node) {
if (node is ClassDeclaration) {
LazyClassDeclaration.readWithClause(_astReader, node);
return node.withClause;
} else if (node is ClassTypeAlias) {
LazyClassTypeAlias.readWithClause(_astReader, node);
return node.withClause;
} else {
throw UnimplementedError('${node.runtimeType}');
}
}
bool hasDefaultValue(FormalParameter node) {
if (node is DefaultFormalParameter) {
return LazyFormalParameter.hasDefaultValue(node);
}
return false;
}
bool hasImplicitReturnType(AstNode node) {
if (node is FunctionDeclaration) {
LazyFunctionDeclaration.readFunctionExpression(_astReader, node);
return node.returnType == null;
}
if (node is MethodDeclaration) {
LazyMethodDeclaration.readReturnTypeNode(_astReader, node);
return node.returnType == null;
}
return false;
}
bool hasImplicitType(AstNode node) {
if (node is DefaultFormalParameter) {
return hasImplicitType(node.parameter);
} else if (node is SimpleFormalParameter) {
return node.type == null;
} else if (node is VariableDeclaration) {
VariableDeclarationList parent = node.parent;
LazyVariableDeclarationList.readTypeNode(_astReader, parent);
return parent.type == null;
}
return false;
}
bool hasInitializer(VariableDeclaration node) {
return LazyVariableDeclaration.hasInitializer(node);
}
bool hasOverrideInferenceDone(AstNode node) {
// Only nodes in the libraries being linked might be not inferred yet.
if (_astReader.isLazy) return true;
return LazyAst.hasOverrideInferenceDone(node);
}
bool isAbstract(AstNode node) {
if (node is ClassDeclaration) {
return node.abstractKeyword != null;
} else if (node is ClassTypeAlias) {
return node.abstractKeyword != null;
} else if (node is FunctionDeclaration) {
return false;
} else if (node is MethodDeclaration) {
return LazyMethodDeclaration.isAbstract(node);
}
throw UnimplementedError('${node.runtimeType}');
}
bool isAsynchronous(AstNode node) {
if (node is ConstructorDeclaration) {
return false;
} else if (node is FunctionDeclaration) {
LazyFunctionDeclaration.readFunctionExpression(_astReader, node);
return isAsynchronous(node.functionExpression);
} else if (node is FunctionExpression) {
return LazyFunctionExpression.isAsynchronous(node);
} else if (node is MethodDeclaration) {
return LazyMethodDeclaration.isAsynchronous(node);
} else {
throw UnimplementedError('${node.runtimeType}');
}
}
bool isConst(AstNode node) {
if (node is FormalParameter) {
return node.isConst;
}
if (node is VariableDeclaration) {
VariableDeclarationList parent = node.parent;
return parent.isConst;
}
throw UnimplementedError('${node.runtimeType}');
}
bool isExplicitlyCovariant(AstNode node) {
if (node is EnumConstantDeclaration) {
return false;
} else if (node is FormalParameter) {
return node.covariantKeyword != null;
} else if (node is VariableDeclaration) {
var parent2 = node.parent.parent;
return parent2 is FieldDeclaration && parent2.covariantKeyword != null;
} else {
throw StateError('${node.runtimeType}');
}
}
bool isExternal(AstNode node) {
if (node is ConstructorDeclaration) {
return node.externalKeyword != null;
} else if (node is FunctionDeclaration) {
return node.externalKeyword != null;
} else if (node is MethodDeclaration) {
return node.externalKeyword != null;
} else {
throw UnimplementedError('${node.runtimeType}');
}
}
bool isFinal(AstNode node) {
if (node is EnumConstantDeclaration) {
return false;
}
if (node is VariableDeclaration) {
VariableDeclarationList parent = node.parent;
return parent.isFinal;
}
throw UnimplementedError('${node.runtimeType}');
}
bool isFunction(LinkedNode node) {
return node.kind == LinkedNodeKind.functionDeclaration;
}
bool isGenerator(AstNode node) {
if (node is ConstructorDeclaration) {
return false;
} else if (node is FunctionDeclaration) {
LazyFunctionDeclaration.readFunctionExpression(_astReader, node);
return isGenerator(node.functionExpression);
} else if (node is FunctionExpression) {
return LazyFunctionExpression.isGenerator(node);
} else if (node is MethodDeclaration) {
return LazyMethodDeclaration.isGenerator(node);
} else {
throw UnimplementedError('${node.runtimeType}');
}
}
bool isGetter(AstNode node) {
if (node is FunctionDeclaration) {
return node.isGetter;
} else if (node is MethodDeclaration) {
return node.isGetter;
} else {
throw StateError('${node.runtimeType}');
}
}
bool isLate(AstNode node) {
if (node is VariableDeclaration) {
return node.isLate;
}
if (node is VariableDeclarationList) {
return node.isLate;
}
if (node is EnumConstantDeclaration) {
return false;
}
throw UnimplementedError('${node.runtimeType}');
}
bool isMethod(LinkedNode node) {
return node.kind == LinkedNodeKind.methodDeclaration;
}
bool isSetter(AstNode node) {
if (node is FunctionDeclaration) {
return node.isSetter;
} else if (node is MethodDeclaration) {
return node.isSetter;
} else {
throw StateError('${node.runtimeType}');
}
}
bool isSimplyBounded(AstNode node) {
return LazyAst.isSimplyBounded(node);
}
bool isStatic(AstNode node) {
if (node is FunctionDeclaration) {
return true;
} else if (node is MethodDeclaration) {
return node.modifierKeyword != null;
} else if (node is VariableDeclaration) {
var parent2 = node.parent.parent;
return parent2 is FieldDeclaration && parent2.isStatic;
}
throw UnimplementedError('${node.runtimeType}');
}
Expression readInitializer(AstNode node) {
if (node is DefaultFormalParameter) {
LazyFormalParameter.readDefaultValue(_astReader, node);
return node.defaultValue;
} else if (node is VariableDeclaration) {
LazyVariableDeclaration.readInitializer(_astReader, node);
return node.initializer;
} else {
throw StateError('${node.runtimeType}');
}
}
AstNode readNode(LinkedNode linkedNode) {
return _astReader.readNode(linkedNode);
}
DartType readType(LinkedNodeType linkedType) {
if (linkedType == null) return null;
var kind = linkedType.kind;
if (kind == LinkedNodeTypeKind.bottom) {
return BottomTypeImpl.instance;
} else if (kind == LinkedNodeTypeKind.dynamic_) {
return DynamicTypeImpl.instance;
} else if (kind == LinkedNodeTypeKind.function) {
var typeParameterDataList = linkedType.functionTypeParameters;
var typeParametersLength = typeParameterDataList.length;
var typeParameters = List<TypeParameterElement>(typeParametersLength);
for (var i = 0; i < typeParametersLength; ++i) {
var typeParameterData = typeParameterDataList[i];
var element = TypeParameterElementImpl(typeParameterData.name, -1);
typeParameters[i] = element;
_typeParameters[_nextSyntheticTypeParameterId++] = element;
}
// Type parameters might use each other in bounds, including forward
// references. So, we read bounds after reading all type parameters.
for (var i = 0; i < typeParametersLength; ++i) {
var typeParameterData = typeParameterDataList[i];
TypeParameterElementImpl element = typeParameters[i];
element.bound = readType(typeParameterData.bound);
}
var returnType = readType(linkedType.functionReturnType);
var formalParameters = linkedType.functionFormalParameters.map((p) {
var type = readType(p.type);
var kind = _formalParameterKind(p.kind);
return ParameterElementImpl.synthetic(p.name, type, kind);
}).toList();
for (var i = 0; i < typeParametersLength; ++i) {
_typeParameters.remove(--_nextSyntheticTypeParameterId);
}
var nullabilitySuffix = _nullabilitySuffix(linkedType.nullabilitySuffix);
return FunctionTypeImpl.synthetic(
returnType,
typeParameters,
formalParameters,
).withNullability(nullabilitySuffix);
} else if (kind == LinkedNodeTypeKind.interface) {
var element = bundleContext.elementOfIndex(linkedType.interfaceClass);
var nullabilitySuffix = _nullabilitySuffix(linkedType.nullabilitySuffix);
return InterfaceTypeImpl.explicit(
element,
linkedType.interfaceTypeArguments.map(readType).toList(),
nullabilitySuffix: nullabilitySuffix,
);
} else if (kind == LinkedNodeTypeKind.typeParameter) {
TypeParameterElement element;
var id = linkedType.typeParameterId;
if (id != 0) {
element = _typeParameters[id];
assert(element != null);
} else {
var index = linkedType.typeParameterElement;
element = bundleContext.elementOfIndex(index);
}
var nullabilitySuffix = _nullabilitySuffix(linkedType.nullabilitySuffix);
return TypeParameterTypeImpl(element).withNullability(nullabilitySuffix);
} else if (kind == LinkedNodeTypeKind.void_) {
return VoidTypeImpl.instance;
} else {
throw UnimplementedError('$kind');
}
}
void setInheritsCovariant(AstNode node, bool value) {
if (node is FormalParameter) {
LazyAst.setInheritsCovariant(node, value);
} else if (node is VariableDeclaration) {
LazyAst.setInheritsCovariant(node, value);
} else {
throw StateError('${node.runtimeType}');
}
}
void setOverrideInferenceDone(AstNode node) {
// TODO(scheglov) This assert fails, check how to avoid this.
// assert(!_astReader.isLazy);
LazyAst.setOverrideInferenceDone(node);
}
void setReturnType(AstNode node, DartType type) {
LazyAst.setReturnType(node, type);
}
void setVariableType(AstNode node, DartType type) {
if (node is DefaultFormalParameter) {
setVariableType(node.parameter, type);
} else {
LazyAst.setType(node, type);
}
}
bool shouldBeConstFieldElement(AstNode node) {
if (node is VariableDeclaration) {
VariableDeclarationList variableList = node.parent;
if (variableList.isConst) return true;
if (variableList.isFinal) {
ClassOrMixinDeclaration class_ = variableList.parent.parent;
for (var member in class_.members) {
if (member is ConstructorDeclaration && member.constKeyword != null) {
return true;
}
}
}
}
return false;
}
Iterable<VariableDeclaration> topLevelVariables(CompilationUnit unit) sync* {
for (var declaration in unit.declarations) {
if (declaration is TopLevelVariableDeclaration) {
for (var variable in declaration.variables.variables) {
yield variable;
}
}
}
}
ParameterKind _formalParameterKind(LinkedNodeFormalParameterKind kind) {
if (kind == LinkedNodeFormalParameterKind.optionalNamed) {
return ParameterKind.NAMED;
} else if (kind == LinkedNodeFormalParameterKind.optionalPositional) {
return ParameterKind.POSITIONAL;
} else if (kind == LinkedNodeFormalParameterKind.requiredNamed) {
return ParameterKind.NAMED_REQUIRED;
}
return ParameterKind.REQUIRED;
}
List<ClassMember> _getClassOrMixinMembers(ClassOrMixinDeclaration node) {
if (node is ClassDeclaration) {
LazyClassDeclaration.readMembers(_astReader, node);
} else if (node is MixinDeclaration) {
LazyMixinDeclaration.readMembers(_astReader, node);
} else {
throw StateError('${node.runtimeType}');
}
return node.members;
}
NodeList<Annotation> _getPartDirectiveAnnotation() {
var definingContext = libraryContext.definingUnit;
var unit = definingContext.unit;
var partDirectiveIndex = 0;
for (var directive in unit.directives) {
if (directive is PartDirective) {
partDirectiveIndex++;
if (partDirectiveIndex == indexInLibrary) {
LazyDirective.readMetadata(definingContext._astReader, directive);
return directive.metadata;
}
}
}
throw StateError('Expected to find $indexInLibrary part directive.');
}
static List<LinkedNode> getTypeParameters(LinkedNode node) {
LinkedNode typeParameterList;
var kind = node.kind;
if (kind == LinkedNodeKind.classTypeAlias) {
typeParameterList = node.classTypeAlias_typeParameters;
} else if (kind == LinkedNodeKind.classDeclaration ||
kind == LinkedNodeKind.mixinDeclaration) {
typeParameterList = node.classOrMixinDeclaration_typeParameters;
} else if (kind == LinkedNodeKind.constructorDeclaration) {
return const [];
} else if (kind == LinkedNodeKind.functionDeclaration) {
return getTypeParameters(node.functionDeclaration_functionExpression);
} else if (kind == LinkedNodeKind.functionExpression) {
typeParameterList = node.functionExpression_typeParameters;
} else if (kind == LinkedNodeKind.functionTypeAlias) {
typeParameterList = node.functionTypeAlias_typeParameters;
} else if (kind == LinkedNodeKind.genericFunctionType) {
typeParameterList = node.genericFunctionType_typeParameters;
} else if (kind == LinkedNodeKind.genericTypeAlias) {
typeParameterList = node.genericTypeAlias_typeParameters;
} else if (kind == LinkedNodeKind.methodDeclaration) {
typeParameterList = node.methodDeclaration_typeParameters;
} else {
throw UnimplementedError('$kind');
}
return typeParameterList?.typeParameterList_typeParameters;
}
static NullabilitySuffix _nullabilitySuffix(EntityRefNullabilitySuffix data) {
switch (data) {
case EntityRefNullabilitySuffix.starOrIrrelevant:
return NullabilitySuffix.star;
case EntityRefNullabilitySuffix.question:
return NullabilitySuffix.question;
case EntityRefNullabilitySuffix.none:
return NullabilitySuffix.none;
default:
throw StateError('$data');
}
}
}