Compare names of typedefs, top level variables, and top level functions.

Change-Id: I5d5b5a4e7609c8f6bcb63ca32ce83e49c42140ca
Reviewed-on: https://dart-review.googlesource.com/72541
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/analyzer_fe_comparison/lib/src/analyzer.dart b/pkg/analyzer_fe_comparison/lib/src/analyzer.dart
index 0fa04da..e7161ca 100644
--- a/pkg/analyzer_fe_comparison/lib/src/analyzer.dart
+++ b/pkg/analyzer_fe_comparison/lib/src/analyzer.dart
@@ -37,10 +37,7 @@
         var unitResult =
             await session.getResolvedAst(compilationUnit.source.fullName);
         for (var astNode in unitResult.unit.declarations) {
-          var childNode = astNode.accept(visitor);
-          if (childNode != null) {
-            childNodes.add(childNode);
-          }
+          childNodes.addAll(astNode.accept(visitor));
         }
       }
       libraryNodes.add(ComparisonNode.sorted(importUri.toString(), childNodes));
@@ -51,38 +48,47 @@
 
 /// Visitor for serializing the contents of an analyzer AST into
 /// ComparisonNodes.
-class _AnalyzerVisitor extends UnifyingAstVisitor<ComparisonNode> {
+class _AnalyzerVisitor extends UnifyingAstVisitor<Iterable<ComparisonNode>> {
   @override
-  ComparisonNode visitClassDeclaration(ClassDeclaration node) {
-    return ComparisonNode('Class ${node.name.name}');
+  List<ComparisonNode> visitClassDeclaration(ClassDeclaration node) {
+    return [ComparisonNode('Class ${node.name.name}')];
   }
 
   @override
-  ComparisonNode visitEnumDeclaration(EnumDeclaration node) {
-    return ComparisonNode('Enum ${node.name.name}');
+  List<ComparisonNode> visitEnumDeclaration(EnumDeclaration node) {
+    return [ComparisonNode('Enum ${node.name.name}')];
   }
 
   @override
-  ComparisonNode visitFunctionDeclaration(FunctionDeclaration node) {
-    // TODO(paulberry)
-    return null;
+  List<ComparisonNode> visitFunctionDeclaration(FunctionDeclaration node) {
+    String kind;
+    if (node.isGetter) {
+      kind = 'Getter';
+    } else if (node.isSetter) {
+      kind = 'Setter';
+    } else {
+      // Kernel calls top level functions "methods".
+      kind = 'Method';
+    }
+    return [ComparisonNode('$kind ${node.name.name}')];
   }
 
   @override
-  ComparisonNode visitFunctionTypeAlias(FunctionTypeAlias node) {
-    // TODO(paulberry)
-    return null;
+  List<ComparisonNode> visitFunctionTypeAlias(FunctionTypeAlias node) {
+    return [ComparisonNode('Typedef ${node.name.name}')];
   }
 
   @override
-  ComparisonNode visitNode(AstNode node) {
+  Null visitNode(AstNode node) {
     throw new UnimplementedError('AnalyzerVisitor: ${node.runtimeType}');
   }
 
   @override
-  ComparisonNode visitTopLevelVariableDeclaration(
-      TopLevelVariableDeclaration node) {
-    // TODO(paulberry)
-    return null;
+  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}');
+    }
   }
 }
diff --git a/pkg/analyzer_fe_comparison/lib/src/kernel.dart b/pkg/analyzer_fe_comparison/lib/src/kernel.dart
index 9be002b..138d05b 100644
--- a/pkg/analyzer_fe_comparison/lib/src/kernel.dart
+++ b/pkg/analyzer_fe_comparison/lib/src/kernel.dart
@@ -54,26 +54,53 @@
 
   @override
   ComparisonNode visitComponent(Component component) {
-    return ComparisonNode.sorted(
-        'Component',
-        component.libraries
-            .where((library) => _inputs.contains(library.importUri))
-            .map<ComparisonNode>((library) => library.accept(this)));
+    var children = <ComparisonNode>[];
+    _visitList(component.libraries, children);
+    return ComparisonNode.sorted('Component', children);
+  }
+
+  @override
+  ComparisonNode visitField(Field field) {
+    // TODO(paulberry): handle fields from Field
+    return ComparisonNode('Field ${field.name.name}');
   }
 
   @override
   ComparisonNode visitLibrary(Library library) {
+    if (!_inputs.contains(library.importUri)) return null;
     var children = <ComparisonNode>[];
     if (library.name != null) {
       children.add(ComparisonNode('name=${library.name}'));
     }
-    for (var class_ in library.classes) {
-      var childNode = class_.accept(this);
-      if (childNode != null) {
-        children.add(childNode);
-      }
-    }
+    _visitList(library.typedefs, children);
+    _visitList(library.classes, children);
+    _visitList(library.procedures, children);
+    _visitList(library.fields, children);
     // TODO(paulberry): handle more fields from Library
     return ComparisonNode.sorted(library.importUri.toString(), children);
   }
+
+  @override
+  ComparisonNode visitProcedure(Procedure procedure) {
+    var kind = procedure.kind.toString().replaceAll('ProcedureKind.', '');
+    // TODO(paulberry): handle fields from Procedure
+    return ComparisonNode('$kind ${procedure.name.name}');
+  }
+
+  @override
+  ComparisonNode visitTypedef(Typedef typedef) {
+    // TODO(paulberry): handle fields from Typedef
+    return ComparisonNode('Typedef ${typedef.name}');
+  }
+
+  /// Transforms all the nodes in [src] to [ComparisonNode]s, and adds those
+  /// with non-null results to [dst].
+  void _visitList(List<TreeNode> src, List<ComparisonNode> dst) {
+    for (var item in src) {
+      ComparisonNode result = item.accept(this);
+      if (result != null) {
+        dst.add(result);
+      }
+    }
+  }
 }