Compare names of class members, and refactor analyzer visitor.
The analyzer visitor now follows the suggestion of
https://dart-review.googlesource.com/c/sdk/+/72541/1/pkg/analyzer_fe_comparison/lib/src/analyzer.dart#51
Change-Id: I093f994b36d835ae6db0dc6a24ed3357dc53c8b7
Reviewed-on: https://dart-review.googlesource.com/72550
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer_fe_comparison/lib/src/analyzer.dart b/pkg/analyzer_fe_comparison/lib/src/analyzer.dart
index e7161ca..b0aff01 100644
--- a/pkg/analyzer_fe_comparison/lib/src/analyzer.dart
+++ b/pkg/analyzer_fe_comparison/lib/src/analyzer.dart
@@ -13,7 +13,6 @@
/// Analyzes the project located at [libPath] using the analyzer, and returns a
/// [ComparisonNode] representing it.
Future<ComparisonNode> driveAnalyzer(String libPath) async {
- var visitor = _AnalyzerVisitor();
var contextCollection = AnalysisContextCollection(includedPaths: [libPath]);
var contexts = contextCollection.contexts;
if (contexts.length != 1) {
@@ -36,9 +35,7 @@
for (var compilationUnit in libraryElement.units) {
var unitResult =
await session.getResolvedAst(compilationUnit.source.fullName);
- for (var astNode in unitResult.unit.declarations) {
- childNodes.addAll(astNode.accept(visitor));
- }
+ _AnalyzerVisitor(childNodes)._visitList(unitResult.unit.declarations);
}
libraryNodes.add(ComparisonNode.sorted(importUri.toString(), childNodes));
}
@@ -48,19 +45,43 @@
/// Visitor for serializing the contents of an analyzer AST into
/// ComparisonNodes.
-class _AnalyzerVisitor extends UnifyingAstVisitor<Iterable<ComparisonNode>> {
+///
+/// Results are accumulated into [_resultNodes].
+class _AnalyzerVisitor extends UnifyingAstVisitor<void> {
+ final List<ComparisonNode> _resultNodes;
+
+ _AnalyzerVisitor(this._resultNodes);
+
@override
- List<ComparisonNode> visitClassDeclaration(ClassDeclaration node) {
- return [ComparisonNode('Class ${node.name.name}')];
+ void visitClassDeclaration(ClassDeclaration node) {
+ var children = <ComparisonNode>[];
+ _AnalyzerVisitor(children)._visitList(node.members);
+ _resultNodes
+ .add(ComparisonNode.sorted('Class ${node.name.name}', children));
}
@override
- List<ComparisonNode> visitEnumDeclaration(EnumDeclaration node) {
- return [ComparisonNode('Enum ${node.name.name}')];
+ void visitConstructorDeclaration(ConstructorDeclaration node) {
+ _resultNodes
+ .add(ComparisonNode('Constructor ${node.name?.name ?? '(unnamed)'}'));
}
@override
- List<ComparisonNode> visitFunctionDeclaration(FunctionDeclaration node) {
+ void visitEnumDeclaration(EnumDeclaration node) {
+ var children = <ComparisonNode>[];
+ for (var enumValue in node.constants) {
+ children.add(ComparisonNode('EnumValue ${enumValue.name.name}'));
+ }
+ _resultNodes.add(ComparisonNode.sorted('Enum ${node.name.name}', children));
+ }
+
+ @override
+ void visitFieldDeclaration(FieldDeclaration node) {
+ node.fields.accept(this);
+ }
+
+ @override
+ void visitFunctionDeclaration(FunctionDeclaration node) {
String kind;
if (node.isGetter) {
kind = 'Getter';
@@ -70,12 +91,27 @@
// Kernel calls top level functions "methods".
kind = 'Method';
}
- return [ComparisonNode('$kind ${node.name.name}')];
+ _resultNodes.add(ComparisonNode('$kind ${node.name.name}'));
}
@override
- List<ComparisonNode> visitFunctionTypeAlias(FunctionTypeAlias node) {
- return [ComparisonNode('Typedef ${node.name.name}')];
+ void visitFunctionTypeAlias(FunctionTypeAlias node) {
+ _resultNodes.add(ComparisonNode('Typedef ${node.name.name}'));
+ }
+
+ @override
+ void visitMethodDeclaration(MethodDeclaration node) {
+ String kind;
+ if (node.isGetter) {
+ kind = 'Getter';
+ } else if (node.isSetter) {
+ kind = 'Setter';
+ } else if (node.isOperator) {
+ kind = 'Operator';
+ } else {
+ kind = 'Method';
+ }
+ _resultNodes.add(ComparisonNode('$kind ${node.name.name}'));
}
@override
@@ -84,11 +120,23 @@
}
@override
- Iterable<ComparisonNode> visitTopLevelVariableDeclaration(
- TopLevelVariableDeclaration node) sync* {
- for (var variableDeclaration in node.variables.variables) {
- // Kernel calls top level variable declarations "fields".
- yield ComparisonNode('Field ${variableDeclaration.name.name}');
+ void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+ node.variables.accept(this);
+ }
+
+ @override
+ void visitVariableDeclarationList(VariableDeclarationList node) {
+ for (var variableDeclaration in node.variables) {
+ // Kernel calls both fields and top level variable declarations "fields".
+ _resultNodes
+ .add(ComparisonNode('Field ${variableDeclaration.name.name}'));
+ }
+ }
+
+ /// Visits all the nodes in [nodes].
+ void _visitList(List<AstNode> nodes) {
+ for (var astNode in nodes) {
+ astNode.accept(this);
}
}
}
diff --git a/pkg/analyzer_fe_comparison/lib/src/kernel.dart b/pkg/analyzer_fe_comparison/lib/src/kernel.dart
index 138d05b..638447c 100644
--- a/pkg/analyzer_fe_comparison/lib/src/kernel.dart
+++ b/pkg/analyzer_fe_comparison/lib/src/kernel.dart
@@ -48,8 +48,21 @@
ComparisonNode visitClass(Class class_) {
if (class_.isAnonymousMixin) return null;
var kind = class_.isEnum ? 'Enum' : 'Class';
- // TODO(paulberry): handle fields from Class
- return ComparisonNode('$kind ${class_.name}');
+ var children = <ComparisonNode>[];
+ if (class_.isEnum) {
+ for (var field in class_.fields) {
+ if (!field.isStatic) continue;
+ if (field.name.name == 'values') continue;
+ // TODO(paulberry): handle index
+ children.add(ComparisonNode('EnumValue ${field.name.name}'));
+ }
+ } else {
+ _visitList(class_.fields, children);
+ _visitList(class_.constructors, children);
+ _visitList(class_.procedures, children);
+ }
+ // TODO(paulberry): handle more fields from Class
+ return ComparisonNode.sorted('$kind ${class_.name}', children);
}
@override
@@ -60,7 +73,19 @@
}
@override
+ ComparisonNode visitConstructor(Constructor constructor) {
+ if (constructor.isSynthetic) return null;
+ var name = constructor.name.name;
+ if (name.isEmpty) {
+ name = '(unnamed)';
+ }
+ // TODO(paulberry): handle fields from Constructor
+ return ComparisonNode('Constructor $name');
+ }
+
+ @override
ComparisonNode visitField(Field field) {
+ if (field.name.name == '_redirecting#') return null;
// TODO(paulberry): handle fields from Field
return ComparisonNode('Field ${field.name.name}');
}
@@ -82,9 +107,18 @@
@override
ComparisonNode visitProcedure(Procedure procedure) {
- var kind = procedure.kind.toString().replaceAll('ProcedureKind.', '');
+ if (procedure.isForwardingStub) return null;
+ // TODO(paulberry): add an annotation to the ComparisonNode when the
+ // procedure is a factory.
+ var kind = procedure.isFactory
+ ? 'Constructor'
+ : procedure.kind.toString().replaceAll('ProcedureKind.', '');
+ var name = procedure.name.name;
+ if (name.isEmpty) {
+ name = '(unnamed)';
+ }
// TODO(paulberry): handle fields from Procedure
- return ComparisonNode('$kind ${procedure.name.name}');
+ return ComparisonNode('$kind $name');
}
@override