Skip to content

Commit 0447df5

Browse files
Merge branch 'master' of https://github.com/dart-lang/dartdoc
2 parents e0ed412 + 3d990ca commit 0447df5

14 files changed

+399
-107
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
//
5+
import 'package:analyzer/dart/ast/ast.dart';
6+
import 'package:analyzer/dart/element/element.dart';
7+
import 'package:analyzer/file_system/file_system.dart';
8+
import 'package:dartdoc/src/model_utils.dart';
9+
10+
/// A stripped down analyzer AST [CommentReference] containing only that
11+
/// information needed for Dartdoc. Drops link to the [CommentReference]
12+
/// and [ResourceProvider] after construction.
13+
class ModelCommentReference {
14+
final String codeRef;
15+
final Element staticElement;
16+
17+
ModelCommentReference(CommentReference ref, ResourceProvider resourceProvider)
18+
: codeRef = _referenceText(ref, resourceProvider),
19+
staticElement = ref.identifier.staticElement;
20+
21+
/// "Unparse" the code reference into the raw text associated with the
22+
/// [CommentReference].
23+
static String _referenceText(
24+
CommentReference ref, ResourceProvider resourceProvider) {
25+
var contents = getFileContentsFor(
26+
(ref.root as CompilationUnit).declaredElement, resourceProvider);
27+
return contents.substring(ref.offset, ref.end);
28+
}
29+
}

lib/src/generator/templates.renderers.dart

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -614,12 +614,13 @@ class _Renderer_Canonicalization extends RendererBase<Canonicalization> {
614614
getValue: (CT_ c) => c.commentRefs,
615615
renderVariable: (CT_ c, Property<CT_> self,
616616
List<String> remainingNames) =>
617-
self.renderSimpleVariable(
618-
c, remainingNames, 'List<ModelCommentReference>'),
619-
renderIterable:
617+
self.renderSimpleVariable(c, remainingNames,
618+
'Map<String, ModelCommentReference>'),
619+
isNullValue: (CT_ c) => c.commentRefs == null,
620+
renderValue:
620621
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
621-
return c.commentRefs.map(
622-
(e) => renderSimple(e, ast, r.template, parent: r));
622+
return renderSimple(c.commentRefs, ast, r.template,
623+
parent: r);
623624
},
624625
),
625626
'isCanonical': Property(
@@ -902,6 +903,19 @@ class _Renderer_Category extends RendererBase<Category> {
902903
(e) => _render_Class(e, ast, r.template, parent: r));
903904
},
904905
),
906+
'commentRefs': Property(
907+
getValue: (CT_ c) => c.commentRefs,
908+
renderVariable: (CT_ c, Property<CT_> self,
909+
List<String> remainingNames) =>
910+
self.renderSimpleVariable(c, remainingNames,
911+
'Map<String, ModelCommentReference>'),
912+
isNullValue: (CT_ c) => c.commentRefs == null,
913+
renderValue:
914+
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
915+
return renderSimple(c.commentRefs, ast, r.template,
916+
parent: r);
917+
},
918+
),
905919
'config': Property(
906920
getValue: (CT_ c) => c.config,
907921
renderVariable: (CT_ c, Property<CT_> self,
@@ -8912,12 +8926,13 @@ class _Renderer_ModelElement extends RendererBase<ModelElement> {
89128926
getValue: (CT_ c) => c.commentRefs,
89138927
renderVariable: (CT_ c, Property<CT_> self,
89148928
List<String> remainingNames) =>
8915-
self.renderSimpleVariable(
8916-
c, remainingNames, 'List<ModelCommentReference>'),
8917-
renderIterable:
8929+
self.renderSimpleVariable(c, remainingNames,
8930+
'Map<String, ModelCommentReference>'),
8931+
isNullValue: (CT_ c) => c.commentRefs == null,
8932+
renderValue:
89188933
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
8919-
return c.commentRefs.map(
8920-
(e) => renderSimple(e, ast, r.template, parent: r));
8934+
return renderSimple(c.commentRefs, ast, r.template,
8935+
parent: r);
89218936
},
89228937
),
89238938
'compilationUnitElement': Property(
@@ -10394,6 +10409,19 @@ class _Renderer_Package extends RendererBase<Package> {
1039410409
(e) => _render_Category(e, ast, r.template, parent: r));
1039510410
},
1039610411
),
10412+
'commentRefs': Property(
10413+
getValue: (CT_ c) => c.commentRefs,
10414+
renderVariable: (CT_ c, Property<CT_> self,
10415+
List<String> remainingNames) =>
10416+
self.renderSimpleVariable(c, remainingNames,
10417+
'Map<String, ModelCommentReference>'),
10418+
isNullValue: (CT_ c) => c.commentRefs == null,
10419+
renderValue:
10420+
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
10421+
return renderSimple(c.commentRefs, ast, r.template,
10422+
parent: r);
10423+
},
10424+
),
1039710425
'config': Property(
1039810426
getValue: (CT_ c) => c.config,
1039910427
renderVariable: (CT_ c, Property<CT_> self,

lib/src/markdown_processor.dart

Lines changed: 43 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,6 @@ final RegExp nonHTML =
126126
/// parentheses.
127127
final _trailingIgnorePattern = RegExp(r'(<.*>|\(.*\)|\?|!)$');
128128

129-
@Deprecated('Public variable intended to be private; will be removed as early '
130-
'as Dartdoc 1.0.0')
131-
RegExp get trailingIgnoreStuff => _trailingIgnorePattern;
132-
133129
/// Things to ignore at the beginning of a doc reference.
134130
///
135131
/// This is intended to catch various keywords that a developer may include in
@@ -139,18 +135,10 @@ RegExp get trailingIgnoreStuff => _trailingIgnorePattern;
139135
final _leadingIgnorePattern =
140136
RegExp(r'^(const|final|var)[\s]+', multiLine: true);
141137

142-
@Deprecated('Public variable intended to be private; will be removed as early '
143-
'as Dartdoc 1.0.0')
144-
RegExp get leadingIgnoreStuff => _leadingIgnorePattern;
145-
146138
/// If found, this pattern may indicate a reference to a constructor.
147139
final _constructorIndicationPattern =
148140
RegExp(r'(^new[\s]+|\(\)$)', multiLine: true);
149141

150-
@Deprecated('Public variable intended to be private; will be removed as early '
151-
'as Dartdoc 1.0.0')
152-
RegExp get isConstructor => _constructorIndicationPattern;
153-
154142
/// A pattern indicating that text which looks like a doc reference is not
155143
/// intended to be.
156144
///
@@ -288,8 +276,8 @@ ModelElement _getPreferredClass(ModelElement modelElement) {
288276
}
289277

290278
/// Implements _getMatchingLinkElement via [CommentReferable.referenceBy].
291-
MatchingLinkResult _getMatchingLinkElementCommentReferable(String codeRef,
292-
Warnable warnable, List<ModelCommentReference> commentRefs) {
279+
MatchingLinkResult _getMatchingLinkElementCommentReferable(
280+
String codeRef, Warnable warnable) {
293281
if (!codeRef.contains(_constructorIndicationPattern) &&
294282
codeRef.contains(notARealDocReference)) {
295283
// Don't waste our time on things we won't ever find.
@@ -304,8 +292,8 @@ MatchingLinkResult _getMatchingLinkElementCommentReferable(String codeRef,
304292
}
305293

306294
/// Returns null if element is a parameter.
307-
MatchingLinkResult _getMatchingLinkElementLegacy(String codeRef,
308-
Warnable warnable, List<ModelCommentReference> commentRefs) {
295+
MatchingLinkResult _getMatchingLinkElementLegacy(
296+
String codeRef, Warnable warnable) {
309297
if (!codeRef.contains(_constructorIndicationPattern) &&
310298
codeRef.contains(notARealDocReference)) {
311299
// Don't waste our time on things we won't ever find.
@@ -322,9 +310,9 @@ MatchingLinkResult _getMatchingLinkElementLegacy(String codeRef,
322310
message:
323311
'Comment reference resolution inside extension methods is not yet implemented');
324312
} else {
325-
refModelElement = _MarkdownCommentReference(
326-
codeRef, warnable, commentRefs, preferredClass)
327-
.computeReferredElement();
313+
refModelElement =
314+
_MarkdownCommentReference(codeRef, warnable, preferredClass)
315+
.computeReferredElement();
328316
}
329317
}
330318

@@ -368,27 +356,28 @@ MatchingLinkResult _getMatchingLinkElementLegacy(String codeRef,
368356
return MatchingLinkResult(refModelElement);
369357
}
370358

371-
/// Given a set of commentRefs, return the one whose name matches the codeRef.
372-
Element _getRefElementFromCommentRefs(
373-
List<ModelCommentReference> commentRefs, String codeRef) {
374-
if (commentRefs != null) {
375-
for (var ref in commentRefs) {
376-
if (ref.name == codeRef) {
377-
var isConstrElement = ref.staticElement is ConstructorElement;
378-
// Constructors are now handled by library search.
379-
if (!isConstrElement) {
380-
var refElement = ref.staticElement;
381-
if (refElement is PropertyAccessorElement) {
382-
// yay we found an accessor that wraps a const, but we really
383-
// want the top-level field itself
384-
refElement = (refElement as PropertyAccessorElement).variable;
385-
}
386-
if (refElement is PrefixElement) {
387-
// We found a prefix element, but what we really want is the library element.
388-
refElement = (refElement as PrefixElement).enclosingElement;
389-
}
390-
return refElement;
359+
/// Get the element referred by the [codeRef] in analyzer.
360+
/// Deletes constructors and otherwise messes with the output for the rest
361+
/// of the heuristics.
362+
Element _getRefElementFromCommentRefs(Warnable element, String codeRef) {
363+
if (element.commentRefs != null) {
364+
var ref = element.commentRefs[codeRef];
365+
// ref can be null here if the analyzer failed to recognize this as a
366+
// comment reference (e.g. [Foo.operator []]).
367+
if (ref != null) {
368+
// Constructors are now handled by library search.
369+
if (ref.staticElement is! ConstructorElement) {
370+
var refElement = ref.staticElement;
371+
if (refElement is PropertyAccessorElement) {
372+
// yay we found an accessor that wraps a const, but we really
373+
// want the top-level field itself
374+
refElement = (refElement as PropertyAccessorElement).variable;
391375
}
376+
if (refElement is PrefixElement) {
377+
// We found a prefix element, but what we really want is the library element.
378+
refElement = (refElement as PrefixElement).enclosingElement;
379+
}
380+
return refElement;
392381
}
393382
}
394383
}
@@ -403,9 +392,6 @@ class _MarkdownCommentReference {
403392
/// The element containing the code reference.
404393
final Warnable element;
405394

406-
/// A list of [ModelCommentReference]s for this element.
407-
final List<ModelCommentReference> commentRefs;
408-
409395
/// Disambiguate inheritance with this class.
410396
final Class preferredClass;
411397

@@ -421,8 +407,7 @@ class _MarkdownCommentReference {
421407
/// PackageGraph associated with this element.
422408
PackageGraph packageGraph;
423409

424-
_MarkdownCommentReference(
425-
this.codeRef, this.element, this.commentRefs, this.preferredClass) {
410+
_MarkdownCommentReference(this.codeRef, this.element, this.preferredClass) {
426411
assert(element != null);
427412
assert(element.packageGraph.allLibrariesAdded);
428413

@@ -589,7 +574,7 @@ class _MarkdownCommentReference {
589574
_codeRefChompedParts ??= codeRefChomped.split('.');
590575

591576
void _reducePreferAnalyzerResolution() {
592-
var refElement = _getRefElementFromCommentRefs(commentRefs, codeRef);
577+
var refElement = _getRefElementFromCommentRefs(element, codeRef);
593578
if (results.any((me) => me.element == refElement)) {
594579
results.removeWhere((me) => me.element != refElement);
595580
}
@@ -663,26 +648,23 @@ class _MarkdownCommentReference {
663648
void _findWithoutLeadingIgnoreStuff() {
664649
if (codeRef.contains(_leadingIgnorePattern)) {
665650
var newCodeRef = codeRef.replaceFirst(_leadingIgnorePattern, '');
666-
results.add(_MarkdownCommentReference(
667-
newCodeRef, element, commentRefs, preferredClass)
651+
results.add(_MarkdownCommentReference(newCodeRef, element, preferredClass)
668652
.computeReferredElement());
669653
}
670654
}
671655

672656
void _findWithoutTrailingIgnoreStuff() {
673657
if (codeRef.contains(_trailingIgnorePattern)) {
674658
var newCodeRef = codeRef.replaceFirst(_trailingIgnorePattern, '');
675-
results.add(_MarkdownCommentReference(
676-
newCodeRef, element, commentRefs, preferredClass)
659+
results.add(_MarkdownCommentReference(newCodeRef, element, preferredClass)
677660
.computeReferredElement());
678661
}
679662
}
680663

681664
void _findWithoutOperatorPrefix() {
682665
if (codeRef.startsWith(operatorPrefix)) {
683666
var newCodeRef = codeRef.replaceFirst(operatorPrefix, '');
684-
results.add(_MarkdownCommentReference(
685-
newCodeRef, element, commentRefs, preferredClass)
667+
results.add(_MarkdownCommentReference(newCodeRef, element, preferredClass)
686668
.computeReferredElement());
687669
}
688670
}
@@ -826,7 +808,7 @@ class _MarkdownCommentReference {
826808
}
827809

828810
void _findAnalyzerReferences() {
829-
var refElement = _getRefElementFromCommentRefs(commentRefs, codeRef);
811+
var refElement = _getRefElementFromCommentRefs(element, codeRef);
830812
if (refElement == null) return;
831813

832814
ModelElement refModelElement;
@@ -943,9 +925,8 @@ const _referenceLookupWarnings = {
943925
PackageWarning.referenceLookupMissingWithNew,
944926
};
945927

946-
md.Node _makeLinkNode(String codeRef, Warnable warnable,
947-
List<ModelCommentReference> commentRefs) {
948-
var result = _getMatchingLinkElement(warnable, codeRef, commentRefs);
928+
md.Node _makeLinkNode(String codeRef, Warnable warnable) {
929+
var result = _getMatchingLinkElement(warnable, codeRef);
949930
var textContent = htmlEscape.convert(codeRef);
950931
var linkedElement = result.modelElement;
951932
if (linkedElement != null) {
@@ -974,18 +955,16 @@ md.Node _makeLinkNode(String codeRef, Warnable warnable,
974955
return md.Element.text('code', textContent);
975956
}
976957

977-
MatchingLinkResult _getMatchingLinkElement(Warnable warnable, String codeRef,
978-
List<ModelCommentReference> commentRefs) {
958+
MatchingLinkResult _getMatchingLinkElement(Warnable warnable, String codeRef) {
979959
MatchingLinkResult result, resultOld, resultNew;
980960
// Do a comparison between result types only if the warnings for them are
981961
// enabled, because there's a significant performance penalty.
982962
var doComparison = warnable.config.packageWarningOptions.warningModes.entries
983963
.where((entry) => _referenceLookupWarnings.contains(entry.key))
984964
.any((entry) => entry.value != PackageWarningMode.ignore);
985965
if (doComparison) {
986-
resultNew =
987-
_getMatchingLinkElementCommentReferable(codeRef, warnable, commentRefs);
988-
resultOld = _getMatchingLinkElementLegacy(codeRef, warnable, commentRefs);
966+
resultNew = _getMatchingLinkElementCommentReferable(codeRef, warnable);
967+
resultOld = _getMatchingLinkElementLegacy(codeRef, warnable);
989968
if (resultNew.modelElement != null) {
990969
markdownStats.resolvedNewLookupReferences++;
991970
}
@@ -996,10 +975,9 @@ MatchingLinkResult _getMatchingLinkElement(Warnable warnable, String codeRef,
996975
}
997976
} else {
998977
if (warnable.config.experimentalReferenceLookup) {
999-
result = _getMatchingLinkElementCommentReferable(
1000-
codeRef, warnable, commentRefs);
978+
result = _getMatchingLinkElementCommentReferable(codeRef, warnable);
1001979
} else {
1002-
result = _getMatchingLinkElementLegacy(codeRef, warnable, commentRefs);
980+
result = _getMatchingLinkElementLegacy(codeRef, warnable);
1003981
}
1004982
}
1005983
if (doComparison) {
@@ -1084,13 +1062,12 @@ Iterable<int> findFreeHangingGenericsPositions(String string) sync* {
10841062
}
10851063

10861064
class MarkdownDocument extends md.Document {
1087-
factory MarkdownDocument.withElementLinkResolver(
1088-
Canonicalization element, List<ModelCommentReference> commentRefs) {
1065+
factory MarkdownDocument.withElementLinkResolver(Canonicalization element) {
10891066
md.Node /*?*/ linkResolver(String name, [String /*?*/ _]) {
10901067
if (name.isEmpty) {
10911068
return null;
10921069
}
1093-
return _makeLinkNode(name, element, commentRefs);
1070+
return _makeLinkNode(name, element);
10941071
}
10951072

10961073
return MarkdownDocument(

lib/src/model/accessor.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
import 'package:analyzer/dart/element/element.dart';
66
import 'package:analyzer/src/dart/element/member.dart' show ExecutableMember;
7-
import 'package:dartdoc/src/model/comment_referable.dart';
87
import 'package:dartdoc/src/element_type.dart';
8+
import 'package:dartdoc/src/model/comment_referable.dart';
99
import 'package:dartdoc/src/model/model.dart';
1010
import 'package:dartdoc/src/render/source_code_renderer.dart';
1111
import 'package:dartdoc/src/utils.dart';

lib/src/model/canonicalization.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:dartdoc/src/comment_references/model_comment_reference.dart';
56
import 'package:dartdoc/src/model/model.dart';
67

78
/// Classes extending this class have canonicalization support in Dartdoc.
@@ -10,7 +11,12 @@ abstract class Canonicalization implements Locatable, Documentable {
1011

1112
Library get canonicalLibrary;
1213

13-
List<ModelCommentReference> get commentRefs => null;
14+
/// A map of [ModelCommentReference.codeRef] to [ModelCommentReference].
15+
/// This map deduplicates comment references as all identical reference
16+
/// strings inside a single documentation comment will point to the same
17+
/// place, so it should not be used to count exactly how many references
18+
/// there are.
19+
Map<String, ModelCommentReference> get commentRefs;
1420

1521
/// Pieces of the location, split to remove 'package:' and slashes.
1622
Set<String> get locationPieces;

0 commit comments

Comments
 (0)