Classes and helper methods to avoid holding AstNodes (#1857)

* Remove crossdart

* Avoid holding references to AstNodes.

* dartfmt
diff --git a/lib/src/markdown_processor.dart b/lib/src/markdown_processor.dart
index eb3eda1..b5706ee 100644
--- a/lib/src/markdown_processor.dart
+++ b/lib/src/markdown_processor.dart
@@ -8,7 +8,6 @@
 import 'dart:convert';
 import 'dart:math';
 
-import 'package:analyzer/dart/ast/ast.dart' hide TypeParameter;
 import 'package:analyzer/dart/element/element.dart';
 import 'package:dartdoc/src/element_type.dart';
 import 'package:dartdoc/src/model.dart';
@@ -186,7 +185,7 @@
 
 /// Returns null if element is a parameter.
 MatchingLinkResult _getMatchingLinkElement(
-    String codeRef, Warnable element, List<CommentReference> commentRefs) {
+    String codeRef, Warnable element, List<ModelCommentReference> commentRefs) {
   if (!codeRef.contains(isConstructor) &&
       codeRef.contains(notARealDocReference)) {
     // Don't waste our time on things we won't ever find.
@@ -244,15 +243,14 @@
 
 /// Given a set of commentRefs, return the one whose name matches the codeRef.
 Element _getRefElementFromCommentRefs(
-    List<CommentReference> commentRefs, String codeRef) {
+    List<ModelCommentReference> commentRefs, String codeRef) {
   if (commentRefs != null) {
-    for (CommentReference ref in commentRefs) {
-      if (ref.identifier.name == codeRef) {
-        bool isConstrElement =
-            ref.identifier.staticElement is ConstructorElement;
+    for (ModelCommentReference ref in commentRefs) {
+      if (ref.name == codeRef) {
+        bool isConstrElement = ref.staticElement is ConstructorElement;
         // Constructors are now handled by library search.
         if (!isConstrElement) {
-          Element refElement = ref.identifier.staticElement;
+          Element refElement = ref.staticElement;
           if (refElement is PropertyAccessorElement) {
             // yay we found an accessor that wraps a const, but we really
             // want the top-level field itself
@@ -278,8 +276,8 @@
   /// The element containing the code reference.
   final Warnable element;
 
-  /// A list of [CommentReference]s from the analyzer.
-  final List<CommentReference> commentRefs;
+  /// A list of [ModelCommentReference]s for this element.
+  final List<ModelCommentReference> commentRefs;
 
   /// Disambiguate inheritance with this class.
   final Class preferredClass;
@@ -726,8 +724,8 @@
   }
 }
 
-String _linkDocReference(
-    String codeRef, Warnable warnable, List<CommentReference> commentRefs) {
+String _linkDocReference(String codeRef, Warnable warnable,
+    List<ModelCommentReference> commentRefs) {
   MatchingLinkResult result;
   result = _getMatchingLinkElement(codeRef, warnable, commentRefs);
   final ModelElement linkedElement = result.element;
@@ -950,7 +948,7 @@
     return _asOneLiner;
   }
 
-  List<CommentReference> get commentRefs => _element.commentRefs;
+  List<ModelCommentReference> get commentRefs => _element.commentRefs;
 
   void _renderHtmlForDartdoc(bool processAllDocs) {
     Tuple3<String, String, bool> renderResults =
diff --git a/lib/src/model.dart b/lib/src/model.dart
index b7cb12d..343cc30 100644
--- a/lib/src/model.dart
+++ b/lib/src/model.dart
@@ -436,8 +436,9 @@
   String get sourceCode {
     if (_sourceCode == null) {
       if (isSynthetic) {
-        _sourceCode =
-            sourceCodeFor((element as PropertyAccessorElement).variable);
+        _sourceCode = packageGraph
+            ._getModelNodeFor((element as PropertyAccessorElement).variable)
+            .sourceCode;
       } else {
         _sourceCode = super.sourceCode;
       }
@@ -1420,13 +1421,72 @@
   }
 }
 
+/// A stripped down [CommentReference] containing only that information needed
+/// for Dartdoc.  Drops link to the [CommentReference] after construction.
+class ModelCommentReference {
+  final String name;
+  final Element staticElement;
+  ModelCommentReference(CommentReference ref)
+      : name = ref.identifier.name,
+        staticElement = ref.identifier.staticElement {}
+}
+
+/// Stripped down information derived from [AstNode] containing only information
+/// needed for Dartdoc.  Drops link to the [AstNode] after construction.
+class ModelNode {
+  final List<ModelCommentReference> commentRefs;
+  final String sourceCode;
+  final Element element;
+
+  ModelNode(AstNode sourceNode, this.element)
+      : sourceCode = _sourceCodeFor(sourceNode, element),
+        commentRefs = _commentRefsFor(sourceNode) {}
+
+  static List<ModelCommentReference> _commentRefsFor(AstNode node) {
+    if (node is AnnotatedNode &&
+        node?.documentationComment?.references != null) {
+      return node.documentationComment.references
+          .map((c) => ModelCommentReference(c))
+          .toList(growable: false);
+    }
+    return null;
+  }
+
+  static String _sourceCodeFor(AstNode node, Element element) {
+    String contents = getFileContentsFor(element);
+    if (node != null) {
+      // Find the start of the line, so that we can line up all the indents.
+      int i = node.offset;
+      while (i > 0) {
+        i -= 1;
+        if (contents[i] == '\n' || contents[i] == '\r') {
+          i += 1;
+          break;
+        }
+      }
+
+      // Trim the common indent from the source snippet.
+      var start = node.offset - (node.offset - i);
+      String source = contents.substring(start, node.end);
+
+      source = const HtmlEscape().convert(source);
+      source = stripIndentFromSource(source);
+      source = stripDartdocCommentsFromSource(source);
+
+      return source.trim();
+    } else {
+      return '';
+    }
+  }
+}
+
 /// Classes extending this class have canonicalization support in Dartdoc.
 abstract class Canonicalization implements Locatable, Documentable {
   bool get isCanonical;
   Library get canonicalLibrary;
 
-  List<CommentReference> _commentRefs;
-  List<CommentReference> get commentRefs => _commentRefs;
+  List<ModelCommentReference> _commentRefs;
+  List<ModelCommentReference> get commentRefs => _commentRefs;
 
   /// Pieces of the location split by [locationSplitter] (removing package: and
   /// slashes).
@@ -1758,7 +1818,7 @@
   String get sourceCode {
     if (_sourceCode == null) {
       // We could use a set to figure the dupes out, but that would lose ordering.
-      String fieldSourceCode = sourceCodeFor(element) ?? '';
+      String fieldSourceCode = modelNode.sourceCode ?? '';
       String getterSourceCode = getter?.sourceCode ?? '';
       String setterSourceCode = setter?.sourceCode ?? '';
       StringBuffer buffer = new StringBuffer();
@@ -3036,12 +3096,10 @@
         .packageGraph.libraryElementReexportedBy[this.element.library];
   }
 
-  AstNode _astNode;
+  ModelNode _modelNode;
   @override
-  AstNode get astNode {
-    _astNode ??= element?.computeNode();
-    return _astNode;
-  }
+  ModelNode get modelNode =>
+      _modelNode ??= packageGraph._getModelNodeFor(element);
 
   List<String> get annotations => annotationsFromMetadata(element.metadata);
 
@@ -3112,7 +3170,7 @@
   }
 
   @override
-  List<CommentReference> get commentRefs {
+  List<ModelCommentReference> get commentRefs {
     if (_commentRefs == null) {
       _commentRefs = [];
       for (ModelElement from in documentationFrom) {
@@ -3121,11 +3179,7 @@
           checkReferences.add(from.enclosingCombo);
         }
         for (ModelElement e in checkReferences) {
-          AstNode node = e.astNode;
-          if (node is AnnotatedNode &&
-              node?.documentationComment?.references != null) {
-            _commentRefs.addAll(node.documentationComment.references);
-          }
+          _commentRefs.addAll(e.modelNode.commentRefs ?? []);
         }
       }
     }
@@ -4674,6 +4728,16 @@
     }
   }
 
+  // Many ModelElements have the same ModelNode; don't build/cache this data more
+  // than once for them.
+  final Map<Element, ModelNode> _modelNodes = Map();
+  ModelNode _getModelNodeFor(element) {
+    /// TODO(jcollins-g): merge with removal of computeNode.
+    _modelNodes.putIfAbsent(
+        element, () => ModelNode(element?.computeNode(), element));
+    return _modelNodes[element];
+  }
+
   SpecialClasses specialClasses;
 
   /// It is safe to cache values derived from the _implementors table if this
@@ -6087,7 +6151,7 @@
 }
 
 abstract class SourceCodeMixin implements Documentable {
-  AstNode get astNode;
+  ModelNode get modelNode;
 
   Tuple2<int, int> get lineAndColumn;
 
@@ -6097,41 +6161,8 @@
 
   Library get library;
 
-  String sourceCodeFor(Element element) {
-    String contents = getFileContentsFor(element);
-    var node = element.computeNode();
-    if (node != null) {
-      // Find the start of the line, so that we can line up all the indents.
-      int i = node.offset;
-      while (i > 0) {
-        i -= 1;
-        if (contents[i] == '\n' || contents[i] == '\r') {
-          i += 1;
-          break;
-        }
-      }
-
-      // Trim the common indent from the source snippet.
-      var start = node.offset - (node.offset - i);
-      String source = contents.substring(start, node.end);
-
-      source = const HtmlEscape().convert(source);
-      source = stripIndentFromSource(source);
-      source = stripDartdocCommentsFromSource(source);
-
-      return source.trim();
-    } else {
-      return '';
-    }
-  }
-
   String _sourceCode;
-  String get sourceCode {
-    if (_sourceCode == null) {
-      _sourceCode = sourceCodeFor(element);
-    }
-    return _sourceCode;
-  }
+  String get sourceCode => _sourceCode ??= modelNode.sourceCode;
 }
 
 abstract class TypeParameters implements ModelElement {