Skip to content

Commit ac1cab5

Browse files
authored
Classes and helper methods to avoid holding AstNodes (#1857)
* Remove crossdart * Avoid holding references to AstNodes. * dartfmt
1 parent 0957f65 commit ac1cab5

File tree

2 files changed

+93
-64
lines changed

2 files changed

+93
-64
lines changed

lib/src/markdown_processor.dart

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ library dartdoc.markdown_processor;
88
import 'dart:convert';
99
import 'dart:math';
1010

11-
import 'package:analyzer/dart/ast/ast.dart' hide TypeParameter;
1211
import 'package:analyzer/dart/element/element.dart';
1312
import 'package:dartdoc/src/element_type.dart';
1413
import 'package:dartdoc/src/model.dart';
@@ -186,7 +185,7 @@ ModelElement _getPreferredClass(ModelElement modelElement) {
186185

187186
/// Returns null if element is a parameter.
188187
MatchingLinkResult _getMatchingLinkElement(
189-
String codeRef, Warnable element, List<CommentReference> commentRefs) {
188+
String codeRef, Warnable element, List<ModelCommentReference> commentRefs) {
190189
if (!codeRef.contains(isConstructor) &&
191190
codeRef.contains(notARealDocReference)) {
192191
// Don't waste our time on things we won't ever find.
@@ -244,15 +243,14 @@ MatchingLinkResult _getMatchingLinkElement(
244243

245244
/// Given a set of commentRefs, return the one whose name matches the codeRef.
246245
Element _getRefElementFromCommentRefs(
247-
List<CommentReference> commentRefs, String codeRef) {
246+
List<ModelCommentReference> commentRefs, String codeRef) {
248247
if (commentRefs != null) {
249-
for (CommentReference ref in commentRefs) {
250-
if (ref.identifier.name == codeRef) {
251-
bool isConstrElement =
252-
ref.identifier.staticElement is ConstructorElement;
248+
for (ModelCommentReference ref in commentRefs) {
249+
if (ref.name == codeRef) {
250+
bool isConstrElement = ref.staticElement is ConstructorElement;
253251
// Constructors are now handled by library search.
254252
if (!isConstrElement) {
255-
Element refElement = ref.identifier.staticElement;
253+
Element refElement = ref.staticElement;
256254
if (refElement is PropertyAccessorElement) {
257255
// yay we found an accessor that wraps a const, but we really
258256
// want the top-level field itself
@@ -278,8 +276,8 @@ class _MarkdownCommentReference {
278276
/// The element containing the code reference.
279277
final Warnable element;
280278

281-
/// A list of [CommentReference]s from the analyzer.
282-
final List<CommentReference> commentRefs;
279+
/// A list of [ModelCommentReference]s for this element.
280+
final List<ModelCommentReference> commentRefs;
283281

284282
/// Disambiguate inheritance with this class.
285283
final Class preferredClass;
@@ -726,8 +724,8 @@ class _MarkdownCommentReference {
726724
}
727725
}
728726

729-
String _linkDocReference(
730-
String codeRef, Warnable warnable, List<CommentReference> commentRefs) {
727+
String _linkDocReference(String codeRef, Warnable warnable,
728+
List<ModelCommentReference> commentRefs) {
731729
MatchingLinkResult result;
732730
result = _getMatchingLinkElement(codeRef, warnable, commentRefs);
733731
final ModelElement linkedElement = result.element;
@@ -950,7 +948,7 @@ class Documentation {
950948
return _asOneLiner;
951949
}
952950

953-
List<CommentReference> get commentRefs => _element.commentRefs;
951+
List<ModelCommentReference> get commentRefs => _element.commentRefs;
954952

955953
void _renderHtmlForDartdoc(bool processAllDocs) {
956954
Tuple3<String, String, bool> renderResults =

lib/src/model.dart

Lines changed: 82 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,9 @@ class Accessor extends ModelElement implements EnclosedElement {
436436
String get sourceCode {
437437
if (_sourceCode == null) {
438438
if (isSynthetic) {
439-
_sourceCode =
440-
sourceCodeFor((element as PropertyAccessorElement).variable);
439+
_sourceCode = packageGraph
440+
._getModelNodeFor((element as PropertyAccessorElement).variable)
441+
.sourceCode;
441442
} else {
442443
_sourceCode = super.sourceCode;
443444
}
@@ -1420,13 +1421,72 @@ abstract class Categorization implements ModelElement {
14201421
}
14211422
}
14221423

1424+
/// A stripped down [CommentReference] containing only that information needed
1425+
/// for Dartdoc. Drops link to the [CommentReference] after construction.
1426+
class ModelCommentReference {
1427+
final String name;
1428+
final Element staticElement;
1429+
ModelCommentReference(CommentReference ref)
1430+
: name = ref.identifier.name,
1431+
staticElement = ref.identifier.staticElement {}
1432+
}
1433+
1434+
/// Stripped down information derived from [AstNode] containing only information
1435+
/// needed for Dartdoc. Drops link to the [AstNode] after construction.
1436+
class ModelNode {
1437+
final List<ModelCommentReference> commentRefs;
1438+
final String sourceCode;
1439+
final Element element;
1440+
1441+
ModelNode(AstNode sourceNode, this.element)
1442+
: sourceCode = _sourceCodeFor(sourceNode, element),
1443+
commentRefs = _commentRefsFor(sourceNode) {}
1444+
1445+
static List<ModelCommentReference> _commentRefsFor(AstNode node) {
1446+
if (node is AnnotatedNode &&
1447+
node?.documentationComment?.references != null) {
1448+
return node.documentationComment.references
1449+
.map((c) => ModelCommentReference(c))
1450+
.toList(growable: false);
1451+
}
1452+
return null;
1453+
}
1454+
1455+
static String _sourceCodeFor(AstNode node, Element element) {
1456+
String contents = getFileContentsFor(element);
1457+
if (node != null) {
1458+
// Find the start of the line, so that we can line up all the indents.
1459+
int i = node.offset;
1460+
while (i > 0) {
1461+
i -= 1;
1462+
if (contents[i] == '\n' || contents[i] == '\r') {
1463+
i += 1;
1464+
break;
1465+
}
1466+
}
1467+
1468+
// Trim the common indent from the source snippet.
1469+
var start = node.offset - (node.offset - i);
1470+
String source = contents.substring(start, node.end);
1471+
1472+
source = const HtmlEscape().convert(source);
1473+
source = stripIndentFromSource(source);
1474+
source = stripDartdocCommentsFromSource(source);
1475+
1476+
return source.trim();
1477+
} else {
1478+
return '';
1479+
}
1480+
}
1481+
}
1482+
14231483
/// Classes extending this class have canonicalization support in Dartdoc.
14241484
abstract class Canonicalization implements Locatable, Documentable {
14251485
bool get isCanonical;
14261486
Library get canonicalLibrary;
14271487

1428-
List<CommentReference> _commentRefs;
1429-
List<CommentReference> get commentRefs => _commentRefs;
1488+
List<ModelCommentReference> _commentRefs;
1489+
List<ModelCommentReference> get commentRefs => _commentRefs;
14301490

14311491
/// Pieces of the location split by [locationSplitter] (removing package: and
14321492
/// slashes).
@@ -1758,7 +1818,7 @@ class Field extends ModelElement
17581818
String get sourceCode {
17591819
if (_sourceCode == null) {
17601820
// We could use a set to figure the dupes out, but that would lose ordering.
1761-
String fieldSourceCode = sourceCodeFor(element) ?? '';
1821+
String fieldSourceCode = modelNode.sourceCode ?? '';
17621822
String getterSourceCode = getter?.sourceCode ?? '';
17631823
String setterSourceCode = setter?.sourceCode ?? '';
17641824
StringBuffer buffer = new StringBuffer();
@@ -3036,12 +3096,10 @@ abstract class ModelElement extends Canonicalization
30363096
.packageGraph.libraryElementReexportedBy[this.element.library];
30373097
}
30383098

3039-
AstNode _astNode;
3099+
ModelNode _modelNode;
30403100
@override
3041-
AstNode get astNode {
3042-
_astNode ??= element?.computeNode();
3043-
return _astNode;
3044-
}
3101+
ModelNode get modelNode =>
3102+
_modelNode ??= packageGraph._getModelNodeFor(element);
30453103

30463104
List<String> get annotations => annotationsFromMetadata(element.metadata);
30473105

@@ -3112,7 +3170,7 @@ abstract class ModelElement extends Canonicalization
31123170
}
31133171

31143172
@override
3115-
List<CommentReference> get commentRefs {
3173+
List<ModelCommentReference> get commentRefs {
31163174
if (_commentRefs == null) {
31173175
_commentRefs = [];
31183176
for (ModelElement from in documentationFrom) {
@@ -3121,11 +3179,7 @@ abstract class ModelElement extends Canonicalization
31213179
checkReferences.add(from.enclosingCombo);
31223180
}
31233181
for (ModelElement e in checkReferences) {
3124-
AstNode node = e.astNode;
3125-
if (node is AnnotatedNode &&
3126-
node?.documentationComment?.references != null) {
3127-
_commentRefs.addAll(node.documentationComment.references);
3128-
}
3182+
_commentRefs.addAll(e.modelNode.commentRefs ?? []);
31293183
}
31303184
}
31313185
}
@@ -4674,6 +4728,16 @@ class PackageGraph {
46744728
}
46754729
}
46764730

4731+
// Many ModelElements have the same ModelNode; don't build/cache this data more
4732+
// than once for them.
4733+
final Map<Element, ModelNode> _modelNodes = Map();
4734+
ModelNode _getModelNodeFor(element) {
4735+
/// TODO(jcollins-g): merge with removal of computeNode.
4736+
_modelNodes.putIfAbsent(
4737+
element, () => ModelNode(element?.computeNode(), element));
4738+
return _modelNodes[element];
4739+
}
4740+
46774741
SpecialClasses specialClasses;
46784742

46794743
/// It is safe to cache values derived from the _implementors table if this
@@ -6087,7 +6151,7 @@ class Parameter extends ModelElement implements EnclosedElement {
60876151
}
60886152

60896153
abstract class SourceCodeMixin implements Documentable {
6090-
AstNode get astNode;
6154+
ModelNode get modelNode;
60916155

60926156
Tuple2<int, int> get lineAndColumn;
60936157

@@ -6097,41 +6161,8 @@ abstract class SourceCodeMixin implements Documentable {
60976161

60986162
Library get library;
60996163

6100-
String sourceCodeFor(Element element) {
6101-
String contents = getFileContentsFor(element);
6102-
var node = element.computeNode();
6103-
if (node != null) {
6104-
// Find the start of the line, so that we can line up all the indents.
6105-
int i = node.offset;
6106-
while (i > 0) {
6107-
i -= 1;
6108-
if (contents[i] == '\n' || contents[i] == '\r') {
6109-
i += 1;
6110-
break;
6111-
}
6112-
}
6113-
6114-
// Trim the common indent from the source snippet.
6115-
var start = node.offset - (node.offset - i);
6116-
String source = contents.substring(start, node.end);
6117-
6118-
source = const HtmlEscape().convert(source);
6119-
source = stripIndentFromSource(source);
6120-
source = stripDartdocCommentsFromSource(source);
6121-
6122-
return source.trim();
6123-
} else {
6124-
return '';
6125-
}
6126-
}
6127-
61286164
String _sourceCode;
6129-
String get sourceCode {
6130-
if (_sourceCode == null) {
6131-
_sourceCode = sourceCodeFor(element);
6132-
}
6133-
return _sourceCode;
6134-
}
6165+
String get sourceCode => _sourceCode ??= modelNode.sourceCode;
61356166
}
61366167

61376168
abstract class TypeParameters implements ModelElement {

0 commit comments

Comments
 (0)