in pkg/analyzer/lib/src/services/available_declarations.dart [1319:1777]
void _buildFileDeclarations(CompilationUnit unit) {
lineInfo = unit.lineInfo!;
lineStarts = lineInfo.lineStarts;
isLibrary = true;
exports = [];
fileDeclarations = [];
libraryDeclarations = null;
exportedDeclarations = null;
templateNames = [];
templateValues = [];
for (var astDirective in unit.directives) {
if (astDirective is ExportDirective) {
var uri = _uriFromAst(astDirective.uri);
if (uri == null) continue;
var combinators = <_ExportCombinator>[];
for (var astCombinator in astDirective.combinators) {
if (astCombinator is ShowCombinator) {
combinators.add(_ExportCombinator(
astCombinator.shownNames.map((id) => id.name).toList(),
const [],
));
} else if (astCombinator is HideCombinator) {
combinators.add(_ExportCombinator(
const [],
astCombinator.hiddenNames.map((id) => id.name).toList(),
));
}
}
exports.add(_Export(uri, combinators));
} else if (astDirective is LibraryDirective) {
isLibraryDeprecated = _hasDeprecatedAnnotation(astDirective);
} else if (astDirective is PartDirective) {
var uri = _uriFromAst(astDirective.uri);
if (uri == null) continue;
parts.add(_Part(uri));
} else if (astDirective is PartOfDirective) {
isLibrary = false;
}
}
int codeOffset = 0;
int codeLength = 0;
void setCodeRange(AstNode node) {
if (node is VariableDeclaration) {
var variables = node.parent as VariableDeclarationList;
var i = variables.variables.indexOf(node);
codeOffset = (i == 0 ? variables.parent! : node).offset;
codeLength = node.end - codeOffset;
} else {
codeOffset = node.offset;
codeLength = node.length;
}
}
String? docComplete;
String? docSummary;
void setDartDoc(AnnotatedNode node) {
var docComment = node.documentationComment;
if (docComment != null) {
var rawText = getCommentNodeRawText(docComment);
docComplete = getDartDocPlainText(rawText);
docSummary = getDartDocSummary(docComplete);
} else {
docComplete = null;
docSummary = null;
}
}
Declaration? addDeclaration({
String? defaultArgumentListString,
List<int>? defaultArgumentListTextRanges,
bool isAbstract = false,
bool isConst = false,
bool isDeprecated = false,
bool isFinal = false,
bool isStatic = false,
required DeclarationKind kind,
required Identifier name,
String? parameters,
List<String>? parameterNames,
List<String>? parameterTypes,
Declaration? parent,
required List<String> relevanceTags,
int? requiredParameterCount,
String? returnType,
String? typeParameters,
}) {
if (Identifier.isPrivateName(name.name)) {
return null;
}
var locationOffset = name.offset;
var lineLocation = lineInfo.getLocation(locationOffset);
var declaration = Declaration(
children: <Declaration>[],
codeLength: codeLength,
codeOffset: codeOffset,
defaultArgumentListString: defaultArgumentListString,
defaultArgumentListTextRanges: defaultArgumentListTextRanges,
docComplete: docComplete,
docSummary: docSummary,
isAbstract: isAbstract,
isConst: isConst,
isDeprecated: isDeprecated,
isFinal: isFinal,
isStatic: isStatic,
kind: kind,
lineInfo: lineInfo,
locationOffset: locationOffset,
locationPath: path,
name: name.name,
locationStartColumn: lineLocation.columnNumber,
locationStartLine: lineLocation.lineNumber,
parameters: parameters,
parameterNames: parameterNames,
parameterTypes: parameterTypes,
parent: parent,
relevanceTagsInFile: relevanceTags,
requiredParameterCount: requiredParameterCount,
returnType: returnType,
typeParameters: typeParameters,
);
if (parent != null) {
parent.children.add(declaration);
} else {
fileDeclarations.add(declaration);
}
return declaration;
}
for (var node in unit.declarations) {
setCodeRange(node);
setDartDoc(node);
var isDeprecated = _hasDeprecatedAnnotation(node);
var hasConstructor = false;
void addClassMembers(Declaration parent, bool parentIsAbstract,
List<ClassMember> members) {
for (var classMember in members) {
setCodeRange(classMember);
setDartDoc(classMember);
isDeprecated = _hasDeprecatedAnnotation(classMember);
if (classMember is ConstructorDeclaration &&
(!parentIsAbstract || classMember.factoryKeyword != null)) {
var parameters = classMember.parameters;
var defaultArguments = _computeDefaultArguments(parameters);
var isConst = classMember.constKeyword != null;
var constructorName = classMember.name;
constructorName ??= SimpleIdentifierImpl(
StringToken(
TokenType.IDENTIFIER,
'',
classMember.returnType.offset,
),
);
// TODO(brianwilkerson) Should we be passing in `isConst`?
addDeclaration(
defaultArgumentListString: defaultArguments?.text,
defaultArgumentListTextRanges: defaultArguments?.ranges,
isDeprecated: isDeprecated,
kind: DeclarationKind.CONSTRUCTOR,
name: constructorName,
parameters: parameters.toSource(),
parameterNames: _getFormalParameterNames(parameters),
parameterTypes: _getFormalParameterTypes(parameters),
parent: parent,
relevanceTags: [
'ElementKind.CONSTRUCTOR',
if (isConst) 'ElementKind.CONSTRUCTOR+const'
],
requiredParameterCount:
_getFormalParameterRequiredCount(parameters),
returnType: classMember.returnType.name,
);
hasConstructor = true;
} else if (classMember is FieldDeclaration) {
// TODO(brianwilkerson) Why are we creating declarations for
// instance members?
var isStatic = classMember.isStatic;
var isConst = classMember.fields.isConst;
var isFinal = classMember.fields.isFinal;
for (var field in classMember.fields.variables) {
setCodeRange(field);
addDeclaration(
isConst: isConst,
isDeprecated: isDeprecated,
isFinal: isFinal,
isStatic: isStatic,
kind: DeclarationKind.FIELD,
name: field.name,
parent: parent,
relevanceTags: [
'ElementKind.FIELD',
if (isConst) 'ElementKind.FIELD+const',
...?RelevanceTags._forExpression(field.initializer)
],
returnType: _getTypeAnnotationString(classMember.fields.type),
);
}
} else if (classMember is MethodDeclaration) {
var isStatic = classMember.isStatic;
var parameters = classMember.parameters;
if (classMember.isGetter) {
addDeclaration(
isDeprecated: isDeprecated,
isStatic: isStatic,
kind: DeclarationKind.GETTER,
name: classMember.name,
parent: parent,
relevanceTags: ['ElementKind.FIELD'],
returnType: _getTypeAnnotationString(classMember.returnType),
);
} else if (classMember.isSetter && parameters != null) {
addDeclaration(
isDeprecated: isDeprecated,
isStatic: isStatic,
kind: DeclarationKind.SETTER,
name: classMember.name,
parameters: parameters.toSource(),
parameterNames: _getFormalParameterNames(parameters),
parameterTypes: _getFormalParameterTypes(parameters),
parent: parent,
relevanceTags: ['ElementKind.FIELD'],
requiredParameterCount:
_getFormalParameterRequiredCount(parameters),
);
} else if (parameters != null) {
var defaultArguments = _computeDefaultArguments(parameters);
addDeclaration(
defaultArgumentListString: defaultArguments?.text,
defaultArgumentListTextRanges: defaultArguments?.ranges,
isDeprecated: isDeprecated,
isStatic: isStatic,
kind: DeclarationKind.METHOD,
name: classMember.name,
parameters: parameters.toSource(),
parameterNames: _getFormalParameterNames(parameters),
parameterTypes: _getFormalParameterTypes(parameters),
parent: parent,
relevanceTags: ['ElementKind.METHOD'],
requiredParameterCount:
_getFormalParameterRequiredCount(parameters),
returnType: _getTypeAnnotationString(classMember.returnType),
typeParameters: classMember.typeParameters?.toSource(),
);
}
}
}
}
if (node is ClassDeclaration) {
var classDeclaration = addDeclaration(
isAbstract: node.isAbstract,
isDeprecated: isDeprecated,
kind: DeclarationKind.CLASS,
name: node.name,
relevanceTags: ['ElementKind.CLASS'],
);
if (classDeclaration == null) continue;
addClassMembers(
classDeclaration, classDeclaration.isAbstract, node.members);
if (!hasConstructor) {
classDeclaration.children.add(Declaration(
children: [],
codeLength: codeLength,
codeOffset: codeOffset,
defaultArgumentListString: null,
defaultArgumentListTextRanges: null,
docComplete: null,
docSummary: null,
isAbstract: false,
isConst: false,
isDeprecated: false,
isFinal: false,
isStatic: false,
kind: DeclarationKind.CONSTRUCTOR,
locationOffset: -1,
locationPath: path,
name: '',
lineInfo: lineInfo,
locationStartColumn: 0,
locationStartLine: 0,
parameters: '()',
parameterNames: [],
parameterTypes: [],
parent: classDeclaration,
relevanceTagsInFile: ['ElementKind.CONSTRUCTOR'],
requiredParameterCount: 0,
returnType: node.name.name,
typeParameters: null,
));
}
} else if (node is ClassTypeAlias) {
addDeclaration(
isDeprecated: isDeprecated,
kind: DeclarationKind.CLASS_TYPE_ALIAS,
name: node.name,
relevanceTags: ['ElementKind.CLASS'],
);
} else if (node is EnumDeclaration) {
var enumDeclaration = addDeclaration(
isDeprecated: isDeprecated,
kind: DeclarationKind.ENUM,
name: node.name,
relevanceTags: ['ElementKind.ENUM'],
);
if (enumDeclaration == null) continue;
for (var constant in node.constants) {
setDartDoc(constant);
var isDeprecated = _hasDeprecatedAnnotation(constant);
addDeclaration(
isDeprecated: isDeprecated,
kind: DeclarationKind.ENUM_CONSTANT,
name: constant.name,
parent: enumDeclaration,
relevanceTags: [
'ElementKind.ENUM_CONSTANT',
'ElementKind.ENUM_CONSTANT+const'
],
);
}
} else if (node is ExtensionDeclaration) {
var name = node.name;
if (name != null) {
addDeclaration(
isDeprecated: isDeprecated,
kind: DeclarationKind.EXTENSION,
name: name,
relevanceTags: ['ElementKind.EXTENSION'],
);
}
// TODO(brianwilkerson) Should we be creating declarations for the
// static members of the extension?
} else if (node is FunctionDeclaration) {
var functionExpression = node.functionExpression;
var parameters = functionExpression.parameters;
if (node.isGetter) {
addDeclaration(
isDeprecated: isDeprecated,
kind: DeclarationKind.GETTER,
name: node.name,
relevanceTags: ['ElementKind.FUNCTION'],
returnType: _getTypeAnnotationString(node.returnType),
);
} else if (node.isSetter && parameters != null) {
addDeclaration(
isDeprecated: isDeprecated,
kind: DeclarationKind.SETTER,
name: node.name,
parameters: parameters.toSource(),
parameterNames: _getFormalParameterNames(parameters),
parameterTypes: _getFormalParameterTypes(parameters),
relevanceTags: ['ElementKind.FUNCTION'],
requiredParameterCount:
_getFormalParameterRequiredCount(parameters),
);
} else if (parameters != null) {
var defaultArguments = _computeDefaultArguments(parameters);
addDeclaration(
defaultArgumentListString: defaultArguments?.text,
defaultArgumentListTextRanges: defaultArguments?.ranges,
isDeprecated: isDeprecated,
kind: DeclarationKind.FUNCTION,
name: node.name,
parameters: parameters.toSource(),
parameterNames: _getFormalParameterNames(parameters),
parameterTypes: _getFormalParameterTypes(parameters),
relevanceTags: ['ElementKind.FUNCTION'],
requiredParameterCount:
_getFormalParameterRequiredCount(parameters),
returnType: _getTypeAnnotationString(node.returnType),
typeParameters: functionExpression.typeParameters?.toSource(),
);
}
} else if (node is GenericTypeAlias) {
var functionType = node.functionType;
var type = node.type;
if (functionType != null) {
var parameters = functionType.parameters;
addDeclaration(
isDeprecated: isDeprecated,
kind: DeclarationKind.FUNCTION_TYPE_ALIAS,
name: node.name,
parameters: parameters.toSource(),
parameterNames: _getFormalParameterNames(parameters),
parameterTypes: _getFormalParameterTypes(parameters),
relevanceTags: ['ElementKind.FUNCTION_TYPE_ALIAS'],
requiredParameterCount:
_getFormalParameterRequiredCount(parameters),
returnType: _getTypeAnnotationString(functionType.returnType),
typeParameters: functionType.typeParameters?.toSource(),
);
} else if (type is NamedType && type.name.name.isNotEmpty) {
addDeclaration(
isDeprecated: isDeprecated,
kind: DeclarationKind.TYPE_ALIAS,
name: node.name,
relevanceTags: ['ElementKind.TYPE_ALIAS'],
);
}
} else if (node is FunctionTypeAlias) {
var parameters = node.parameters;
addDeclaration(
isDeprecated: isDeprecated,
kind: DeclarationKind.FUNCTION_TYPE_ALIAS,
name: node.name,
parameters: parameters.toSource(),
parameterNames: _getFormalParameterNames(parameters),
parameterTypes: _getFormalParameterTypes(parameters),
relevanceTags: ['ElementKind.FUNCTION_TYPE_ALIAS'],
requiredParameterCount: _getFormalParameterRequiredCount(parameters),
returnType: _getTypeAnnotationString(node.returnType),
typeParameters: node.typeParameters?.toSource(),
);
} else if (node is MixinDeclaration) {
var mixinDeclaration = addDeclaration(
isDeprecated: isDeprecated,
kind: DeclarationKind.MIXIN,
name: node.name,
relevanceTags: ['ElementKind.MIXIN'],
);
if (mixinDeclaration == null) continue;
addClassMembers(mixinDeclaration, false, node.members);
} else if (node is TopLevelVariableDeclaration) {
var isConst = node.variables.isConst;
var isFinal = node.variables.isFinal;
for (var variable in node.variables.variables) {
setCodeRange(variable);
addDeclaration(
isConst: isConst,
isDeprecated: isDeprecated,
isFinal: isFinal,
kind: DeclarationKind.VARIABLE,
name: variable.name,
relevanceTags: [
'ElementKind.TOP_LEVEL_VARIABLE',
if (isConst) 'ElementKind.TOP_LEVEL_VARIABLE+const',
...?RelevanceTags._forExpression(variable.initializer)
],
returnType: _getTypeAnnotationString(node.variables.type),
);
}
}
}
}