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 {