blob: 20300863183fda55890437dcec2a7d7f89121284 [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/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary2/ast_binary_reader.dart';
import 'package:analyzer/src/summary2/ast_resolver.dart';
import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/reference.dart';
class MetadataResolver {
AstResolver _astResolver;
MetadataResolver(Linker linker, Reference libraryRef) {
_astResolver = AstResolver(linker, libraryRef);
}
void resolve(UnitBuilder unit) {
var unitDeclarations = unit.node.compilationUnit_declarations;
for (LinkedNodeBuilder unitDeclaration in unitDeclarations) {
var kind = unitDeclaration.kind;
if (_isAnnotatedNode(kind)) {
_annotatedNode(
unit,
unitDeclaration,
);
}
if (kind == LinkedNodeKind.classDeclaration) {
_class(unit, unitDeclaration);
} else if (kind == LinkedNodeKind.enumDeclaration) {
_enumDeclaration(unit, unitDeclaration);
} else if (kind == LinkedNodeKind.functionDeclaration) {
var function = unitDeclaration.functionDeclaration_functionExpression;
_formalParameterList(
unit,
function.functionExpression_formalParameters,
);
} else if (kind == LinkedNodeKind.topLevelVariableDeclaration) {
_variables(
unit,
unitDeclaration,
unitDeclaration.topLevelVariableDeclaration_variableList,
);
}
}
}
void _annotatedNode(UnitBuilder unit, LinkedNodeBuilder node) {
var unresolved = node.annotatedNode_metadata;
var resolved = _list(unit, unresolved);
node.annotatedNode_metadata = resolved;
}
void _class(UnitBuilder unit, LinkedNodeBuilder unitDeclaration) {
var members = unitDeclaration.classOrMixinDeclaration_members;
for (var classMember in members) {
var kind = classMember.kind;
if (_isAnnotatedNode(kind)) {
_annotatedNode(unit, classMember);
}
if (kind == LinkedNodeKind.fieldDeclaration) {
_variables(
unit,
classMember,
classMember.fieldDeclaration_fields,
);
} else if (kind == LinkedNodeKind.methodDeclaration) {
_formalParameterList(
unit,
classMember.methodDeclaration_formalParameters,
);
}
}
}
void _enumDeclaration(UnitBuilder unit, LinkedNodeBuilder node) {
for (var constant in node.enumDeclaration_constants) {
var kind = constant.kind;
if (kind == LinkedNodeKind.enumConstantDeclaration) {
_annotatedNode(unit, constant);
}
}
}
void _formalParameterList(UnitBuilder unit, LinkedNodeBuilder node) {
if (node == null) return;
for (var parameter in node.formalParameterList_parameters) {
if (parameter.kind == LinkedNodeKind.defaultFormalParameter) {
var actual = parameter.defaultFormalParameter_parameter;
var unresolved = actual.normalFormalParameter_metadata;
var resolved = _list(unit, unresolved);
actual.normalFormalParameter_metadata = resolved;
} else {
var unresolved = parameter.normalFormalParameter_metadata;
var resolved = _list(unit, unresolved);
parameter.normalFormalParameter_metadata = resolved;
}
}
}
List<LinkedNodeBuilder> _list(UnitBuilder unit, List<LinkedNode> unresolved) {
var resolved = List<LinkedNodeBuilder>(unresolved.length);
for (var i = 0; i < unresolved.length; ++i) {
var unresolvedNode = unresolved[i];
var reader = AstBinaryReader(unit.context);
var ast = reader.readNode(unresolvedNode) as Annotation;
ast.elementAnnotation = ElementAnnotationImpl(null);
// Set some parent, so that resolver does not bail out.
astFactory.libraryDirective(null, [ast], null, null, null);
var resolvedNode = _astResolver.resolve(unit, ast);
resolved[i] = resolvedNode;
}
return resolved;
}
/// Resolve annotations of the [declaration] (field or top-level variable),
/// and set them as metadata for each variable in the [variableList].
void _variables(UnitBuilder unit, LinkedNodeBuilder declaration,
LinkedNodeBuilder variableList) {
for (var variable in variableList.variableDeclarationList_variables) {
var unresolved = declaration.annotatedNode_metadata;
var resolved = _list(unit, unresolved);
variable.annotatedNode_metadata = resolved;
}
}
static bool _isAnnotatedNode(LinkedNodeKind kind) {
return kind == LinkedNodeKind.classDeclaration ||
kind == LinkedNodeKind.classTypeAlias ||
kind == LinkedNodeKind.constructorDeclaration ||
kind == LinkedNodeKind.enumDeclaration ||
kind == LinkedNodeKind.functionDeclaration ||
kind == LinkedNodeKind.functionTypeAlias ||
kind == LinkedNodeKind.methodDeclaration;
}
}