dartk: remove uses of .computeNode

As a result, this changes the order in which declarations appear in the generated output. The new order is more consistent with the textual order in the original file.

Calling .computeNode() is sort of an anti-pattern for using analyzer. This was
however used very sparsely in dartk. The few places where it was used,
computeNode was practically called immediately after resolving the library
element, so I don't expect this to make almost any difference in performance.

R=asgerf@google.com, paulberry@google.com

Review URL: https://codereview.chromium.org/2553303002 .
diff --git a/pkg/kernel/lib/analyzer/loader.dart b/pkg/kernel/lib/analyzer/loader.dart
index fb52300..ae16926 100644
--- a/pkg/kernel/lib/analyzer/loader.dart
+++ b/pkg/kernel/lib/analyzer/loader.dart
@@ -109,8 +109,8 @@
       ..fileUri = "file://${element.source.fullName}";
   }
 
-  void _buildTopLevelMember(ast.Member member, Element element) {
-    var astNode = element.computeNode();
+  void _buildTopLevelMember(
+      ast.Member member, Element element, Declaration astNode) {
     assert(member.parent != null);
     new MemberBodyBuilder(this, member, element).build(astNode);
   }
@@ -124,45 +124,56 @@
     return _libraryBeingLoaded == element;
   }
 
-  void _buildLibraryBody(LibraryElement element, ast.Library library) {
+  void _buildLibraryBody(LibraryElement element, ast.Library library,
+      List<CompilationUnit> units) {
     assert(_libraryBeingLoaded == null);
     _libraryBeingLoaded = element;
     var classes = <ast.Class>[];
     var procedures = <ast.Procedure>[];
     var fields = <ast.Field>[];
-    void loadClass(ClassElement classElement) {
-      var node = getClassReference(classElement);
-      promoteToBodyLevel(node);
+
+    void loadClass(NamedCompilationUnitMember declaration) {
+      // [declaration] can be a ClassDeclaration, EnumDeclaration, or a
+      // ClassTypeAlias.
+      ClassElement element = declaration.element;
+      var node = getClassReference(element);
+      promoteToBodyLevel(node, element, declaration);
       classes.add(node);
     }
 
-    void loadProcedure(Element memberElement) {
-      var node = getMemberReference(memberElement);
-      _buildTopLevelMember(node, memberElement);
+    void loadProcedure(FunctionDeclaration declaration) {
+      var element = declaration.element;
+      var node = getMemberReference(element);
+      _buildTopLevelMember(node, element, declaration);
       procedures.add(node);
     }
 
-    void loadField(Element memberElement) {
-      var node = getMemberReference(memberElement);
-      _buildTopLevelMember(node, memberElement);
-      fields.add(node);
+    void loadField(TopLevelVariableDeclaration declaration) {
+      for (var field in declaration.variables.variables) {
+        var element = field.element;
+        // Ignore fields inserted through error recovery.
+        if (element.name == '') continue;
+        var node = getMemberReference(element);
+        _buildTopLevelMember(node, element, field);
+        fields.add(node);
+      }
     }
 
-    for (var unit in element.units) {
-      unit.types.forEach(loadClass);
-      unit.enums.forEach(loadClass);
-      for (var accessor in unit.accessors) {
-        if (!accessor.isSynthetic) {
-          loadProcedure(accessor);
-        }
-      }
-      for (var function in unit.functions) {
-        loadProcedure(function);
-      }
-      for (var field in unit.topLevelVariables) {
-        // Ignore fields inserted through error recovery.
-        if (!field.isSynthetic && field.name != '') {
-          loadField(field);
+    for (var unit in units) {
+      for (CompilationUnitMember declaration in unit.declarations) {
+        if (declaration is ClassDeclaration ||
+            declaration is EnumDeclaration ||
+            declaration is ClassTypeAlias) {
+          loadClass(declaration);
+        } else if (declaration is FunctionDeclaration) {
+          loadProcedure(declaration);
+        } else if (declaration is TopLevelVariableDeclaration) {
+          loadField(declaration);
+        } else if (declaration is FunctionTypeAlias) {
+          // Nothing to do. Typedefs are handled lazily while constructing type
+          // references.
+        } else {
+          throw "unexpected node: ${declaration.runtimeType} $declaration";
         }
       }
     }
@@ -352,13 +363,11 @@
     }
   }
 
-  void promoteToBodyLevel(ast.Class classNode) {
+  void promoteToBodyLevel(ast.Class classNode, ClassElement element,
+      NamedCompilationUnitMember astNode) {
     if (classNode.level == ast.ClassLevel.Body) return;
     promoteToHierarchyLevel(classNode);
     classNode.level = ast.ClassLevel.Body;
-    var element = getClassElement(classNode);
-    if (element == null) return;
-    var astNode = element.computeNode();
     // Clear out the member references that were put in the class.
     // The AST builder will load them all put back in the right order.
     classNode..fields.clear()..procedures.clear()..constructors.clear();
@@ -585,20 +594,28 @@
         .forUri2(applicationRoot.absoluteUri(node.importUri));
     assert(source != null);
     var element = context.computeLibraryElement(source);
-    context.resolveCompilationUnit(source, element);
-    _buildLibraryBody(element, node);
-    if (node.importUri.scheme != 'dart') {
-      for (var unit in element.units) {
-        LineInfo lines;
-        for (var error in context.computeErrors(unit.source)) {
-          if (error.errorCode is CompileTimeErrorCode ||
-              error.errorCode is ParserErrorCode ||
-              error.errorCode is ScannerErrorCode ||
-              error.errorCode is StrongModeCode) {
-            lines ??= context.computeLineInfo(source);
-            errors.add(formatErrorMessage(error, source.shortName, lines));
-          }
-        }
+    var units = <CompilationUnit>[];
+    bool reportErrors = node.importUri.scheme != 'dart';
+    var tree = context.resolveCompilationUnit(source, element);
+    units.add(tree);
+    if (reportErrors) _processErrors(source);
+    for (var part in element.parts) {
+      var source = part.source;
+      units.add(context.resolveCompilationUnit(source, element));
+      if (reportErrors) _processErrors(source);
+    }
+    _buildLibraryBody(element, node, units);
+  }
+
+  void _processErrors(Source source) {
+    LineInfo lines;
+    for (var error in context.computeErrors(source)) {
+      if (error.errorCode is CompileTimeErrorCode ||
+          error.errorCode is ParserErrorCode ||
+          error.errorCode is ScannerErrorCode ||
+          error.errorCode is StrongModeCode) {
+        lines ??= context.computeLineInfo(source);
+        errors.add(formatErrorMessage(error, source.shortName, lines));
       }
     }
   }
@@ -655,10 +672,9 @@
     for (LibraryElement libraryElement in libraryElements) {
       for (CompilationUnitElement compilationUnitElement
           in libraryElement.units) {
-        // TODO(jensj): Get this another way?
-        LineInfo lineInfo = compilationUnitElement.computeNode().lineInfo;
-        program.uriToLineStarts[
-                "file://${compilationUnitElement.source.source.fullName}"] =
+        var source = compilationUnitElement.source;
+        LineInfo lineInfo = context.computeLineInfo(source);
+        program.uriToLineStarts["file://${source.fullName}"] =
             new List<int>.generate(lineInfo.lineCount, lineInfo.getOffsetOfLine,
                 growable: false);
       }