Set 'enclosingClass' for class members and type parameters.
R=brianwilkerson@google.com
Change-Id: I932f327da2b3eba196150840a60625b5780359e4
Reviewed-on: https://dart-review.googlesource.com/c/86983
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart b/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart
index 409d7b0..dcc3838 100644
--- a/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/dependency/library_builder.dart
@@ -156,6 +156,9 @@
/// locations are different.
List<int> enclosingClassNameSignature;
+ /// The node of the enclosing class.
+ Node enclosingClass;
+
_LibraryBuilder(this.uri, this.units);
Library build() {
@@ -181,60 +184,6 @@
enclosingClassNameSignature =
(ApiSignature()..addString(enclosingClassName)).toByteList();
- var hasConstConstructor = node.members.any(
- (m) => m is ConstructorDeclaration && m.constKeyword != null,
- );
-
- // TODO(scheglov) do we need type parameters at all?
- List<Node> classTypeParameters;
- if (node.typeParameters != null) {
- classTypeParameters = <Node>[];
- for (var typeParameter in node.typeParameters.typeParameters) {
- var api = referenceCollector.collect(
- _computeNodeTokenSignature(typeParameter),
- enclosingClassName: enclosingClassName,
- thisNodeName: typeParameter.name.name,
- type: typeParameter.bound,
- );
- classTypeParameters.add(Node(
- LibraryQualifiedName(uri, typeParameter.name.name),
- NodeKind.TYPE_PARAMETER,
- api,
- Dependencies.none,
- ));
- }
- classTypeParameters.sort(Node.compare);
- }
-
- var classMembers = <Node>[];
- var hasConstructor = false;
- for (var member in node.members) {
- if (member is ConstructorDeclaration) {
- hasConstructor = true;
- _addConstructor(classMembers, member);
- } else if (member is FieldDeclaration) {
- _addVariables(
- classMembers,
- member.metadata,
- member.fields,
- hasConstConstructor,
- );
- } else if (member is MethodDeclaration) {
- _addMethod(classMembers, member);
- } else {
- throw UnimplementedError('(${member.runtimeType}) $member');
- }
- }
-
- if (!hasConstructor && node is ClassDeclaration) {
- classMembers.add(Node(
- LibraryQualifiedName(uri, ''),
- NodeKind.CONSTRUCTOR,
- Dependencies.none,
- Dependencies.none,
- ));
- }
-
var apiTokenSignature = _computeTokenSignature(
node.beginToken,
node.leftBracket,
@@ -262,21 +211,78 @@
throw UnimplementedError('(${node.runtimeType}) $node');
}
- var classNode = Node(
+ enclosingClass = Node(
LibraryQualifiedName(uri, enclosingClassName),
node is MixinDeclaration ? NodeKind.MIXIN : NodeKind.CLASS,
api,
Dependencies.none,
- classTypeParameters: classTypeParameters,
);
- classMembers.sort(Node.compare);
- classNode.setClassMembers(classMembers);
+ var hasConstConstructor = node.members.any(
+ (m) => m is ConstructorDeclaration && m.constKeyword != null,
+ );
- declaredNodes.add(classNode);
+ // TODO(scheglov) do we need type parameters at all?
+ List<Node> classTypeParameters;
+ if (node.typeParameters != null) {
+ classTypeParameters = <Node>[];
+ for (var typeParameter in node.typeParameters.typeParameters) {
+ var api = referenceCollector.collect(
+ _computeNodeTokenSignature(typeParameter),
+ enclosingClassName: enclosingClassName,
+ thisNodeName: typeParameter.name.name,
+ type: typeParameter.bound,
+ );
+ classTypeParameters.add(Node(
+ LibraryQualifiedName(uri, typeParameter.name.name),
+ NodeKind.TYPE_PARAMETER,
+ api,
+ Dependencies.none,
+ enclosingClass: enclosingClass,
+ ));
+ }
+ classTypeParameters.sort(Node.compare);
+ enclosingClass.setTypeParameters(classTypeParameters);
+ }
+
+ var classMembers = <Node>[];
+ var hasConstructor = false;
+ for (var member in node.members) {
+ if (member is ConstructorDeclaration) {
+ hasConstructor = true;
+ _addConstructor(classMembers, member);
+ } else if (member is FieldDeclaration) {
+ _addVariables(
+ classMembers,
+ member.metadata,
+ member.fields,
+ hasConstConstructor,
+ );
+ } else if (member is MethodDeclaration) {
+ _addMethod(classMembers, member);
+ } else {
+ throw UnimplementedError('(${member.runtimeType}) $member');
+ }
+ }
+
+ if (node is ClassDeclaration && !hasConstructor) {
+ classMembers.add(Node(
+ LibraryQualifiedName(uri, ''),
+ NodeKind.CONSTRUCTOR,
+ Dependencies.none,
+ Dependencies.none,
+ enclosingClass: enclosingClass,
+ ));
+ }
+
+ classMembers.sort(Node.compare);
+ enclosingClass.setClassMembers(classMembers);
+
+ declaredNodes.add(enclosingClass);
enclosingClassName = null;
enclosingClassNameSignature = null;
enclosingSuperClass = null;
+ enclosingClass = null;
}
void _addClassTypeAlias(ClassTypeAlias node) {
@@ -325,12 +331,20 @@
NodeKind.CONSTRUCTOR,
api,
impl,
+ enclosingClass: enclosingClass,
));
}
void _addEnum(EnumDeclaration node) {
var enumTokenSignature = _newApiSignatureBuilder().toByteList();
+ var enumNode = Node(
+ LibraryQualifiedName(uri, node.name.name),
+ NodeKind.ENUM,
+ Dependencies(enumTokenSignature, [], [], [], [], []),
+ Dependencies.none,
+ );
+
Dependencies fieldDependencies;
{
var builder = _newApiSignatureBuilder();
@@ -347,6 +361,7 @@
NodeKind.GETTER,
fieldDependencies,
Dependencies.none,
+ enclosingClass: enumNode,
));
}
@@ -355,6 +370,7 @@
NodeKind.GETTER,
fieldDependencies,
Dependencies.none,
+ enclosingClass: enumNode,
));
members.add(Node(
@@ -362,15 +378,10 @@
NodeKind.GETTER,
fieldDependencies,
Dependencies.none,
+ enclosingClass: enumNode,
));
- members.sort(Node.compare);
- var enumNode = Node(
- LibraryQualifiedName(uri, node.name.name),
- NodeKind.ENUM,
- Dependencies(enumTokenSignature, [], [], [], [], []),
- Dependencies.none,
- );
+ members.sort(Node.compare);
enumNode.setClassMembers(members);
declaredNodes.add(enumNode);
@@ -545,7 +556,9 @@
);
var name = LibraryQualifiedName(uri, node.name.name);
- classMembers.add(Node(name, kind, api, impl));
+ classMembers.add(
+ Node(name, kind, api, impl, enclosingClass: enclosingClass),
+ );
}
void _addUnit(CompilationUnit unit) {
@@ -615,6 +628,7 @@
NodeKind.GETTER,
api,
impl,
+ enclosingClass: enclosingClass,
));
if (!variables.isConst && !variables.isFinal) {
@@ -626,6 +640,7 @@
NodeKind.SETTER,
api,
Dependencies.none,
+ enclosingClass: enclosingClass,
),
);
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/dependency/node.dart b/pkg/analyzer/lib/src/dart/analysis/dependency/node.dart
index 6fe7d43..ef5022d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/dependency/node.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/dependency/node.dart
@@ -181,7 +181,7 @@
/// If the node is a class, the nodes of its type parameters.
/// Otherwise `null`.
- final List<Node> classTypeParameters;
+ List<Node> classTypeParameters;
/// If the node is a class, the sorted list of members in this class.
/// Otherwise `null`.
@@ -210,6 +210,11 @@
classMembers = newClassMembers;
}
+ /// Set new class type parameters for this class.
+ void setTypeParameters(List<Node> newTypeParameters) {
+ classTypeParameters = newTypeParameters;
+ }
+
@override
String toString() {
if (enclosingClass != null) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/dependency/reference_collector.dart b/pkg/analyzer/lib/src/dart/analysis/dependency/reference_collector.dart
index 2d6a175..b191634 100644
--- a/pkg/analyzer/lib/src/dart/analysis/dependency/reference_collector.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/dependency/reference_collector.dart
@@ -253,7 +253,9 @@
for (var i = 0; i < initializers.length; i++) {
var initializer = initializers[i];
- if (initializer is ConstructorFieldInitializer) {
+ if (initializer is AssertInitializer) {
+ // TODO(scheglov) implement
+ } else if (initializer is ConstructorFieldInitializer) {
_visitExpression(initializer.expression);
} else if (initializer is SuperConstructorInvocation) {
_visitConstructor(superClass, initializer.constructorName);
diff --git a/pkg/analyzer/test/src/dart/analysis/dependency/base.dart b/pkg/analyzer/test/src/dart/analysis/dependency/base.dart
index 9bc3448..b217244 100644
--- a/pkg/analyzer/test/src/dart/analysis/dependency/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/dependency/base.dart
@@ -21,10 +21,8 @@
bool hasDartCore = false;
- void assertNodes(
- List<Node> actualNodes,
- List<ExpectedNode> expectedNodes,
- ) {
+ void assertNodes(List<Node> actualNodes, List<ExpectedNode> expectedNodes,
+ {Node expectedEnclosingClass}) {
expect(actualNodes, hasLength(expectedNodes.length));
for (var expectedNode in expectedNodes) {
var topNode = _getNode(
@@ -33,9 +31,11 @@
name: expectedNode.name,
kind: expectedNode.kind,
);
+ expect(topNode.enclosingClass, expectedEnclosingClass);
if (expectedNode.classMembers != null) {
- assertNodes(topNode.classMembers, expectedNode.classMembers);
+ assertNodes(topNode.classMembers, expectedNode.classMembers,
+ expectedEnclosingClass: topNode);
} else {
expect(topNode.classMembers, isNull);
}
@@ -44,6 +44,7 @@
assertNodes(
topNode.classTypeParameters,
expectedNode.classTypeParameters,
+ expectedEnclosingClass: topNode,
);
} else {
expect(topNode.classTypeParameters, isNull);