Skip to content

Commit a66b2db

Browse files
committed
handle doc references to top-level constants
1 parent 6e3c1dd commit a66b2db

File tree

5 files changed

+65
-37
lines changed

5 files changed

+65
-37
lines changed

lib/markdown_processor.dart

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import 'package:analyzer/src/generated/element.dart'
1111
LibraryElement,
1212
Element,
1313
ConstructorElement,
14+
CompilationUnitElement,
1415
ClassMemberElement,
16+
TopLevelVariableElement,
1517
PropertyAccessorElement;
1618
import 'package:html/dom.dart' show Document;
1719
import 'package:html/parser.dart' show parse;
@@ -20,8 +22,7 @@ import 'package:markdown/markdown.dart' as md;
2022
import 'src/html_utils.dart' show htmlEscape;
2123
import 'src/model.dart';
2224

23-
const _leftChar = '[';
24-
const _rightChar = ']';
25+
import 'src/debug.dart';
2526

2627
final List<md.InlineSyntax> _markdown_syntaxes = [new _InlineCodeSyntax()];
2728

@@ -85,6 +86,7 @@ class Documentation {
8586

8687
String renderMarkdownToHtml(String text, [ModelElement element]) {
8788
md.Node _linkResolver(String name) {
89+
//debugger(when: element != null && element.name == 'doAwesomeStuff');
8890
NodeList<CommentReference> commentRefs = _getCommentRefs(element);
8991
return new md.Text(_linkDocReference(name, element, commentRefs));
9092
}
@@ -147,6 +149,8 @@ NodeList<CommentReference> _getCommentRefs(ModelElement modelElement) {
147149
String _getMatchingLink(
148150
String codeRef, ModelElement element, List<CommentReference> commentRefs,
149151
{bool isConstructor: false}) {
152+
debugger(when: element.name == 'short');
153+
150154
if (commentRefs == null) return null;
151155

152156
Element refElement;
@@ -164,16 +168,15 @@ String _getMatchingLink(
164168

165169
if (refElement == null) return null;
166170

167-
Library refLibrary;
168-
var e = refElement is ClassMemberElement ||
169-
refElement is PropertyAccessorElement
170-
? refElement.enclosingElement
171-
: refElement;
171+
if (refElement is PropertyAccessorElement &&
172+
refElement.enclosingElement is CompilationUnitElement) {
173+
// yay we found an accessor that wraps a const, but we really
174+
// want the top-level field itself
175+
refElement = (refElement as PropertyAccessorElement).variable;
176+
}
177+
178+
Library refLibrary = element.package.findLibraryFor(refElement);
172179

173-
// If e is a ParameterElement, it's
174-
// never going to be in a library. So refLibrary is going to be null.
175-
refLibrary = element.package.libraries.firstWhere(
176-
(lib) => lib.hasInNamespace(e), orElse: () => null);
177180
if (refLibrary != null) {
178181
// Is there a way to pull this from a registry of known elements?
179182
// Seems like we're creating too many objects this way.

lib/src/html_utils.dart

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,6 @@ import 'dart:convert';
88

99
String htmlEscape(String text) => HTML_ESCAPE.convert(text);
1010

11-
String escapeBrackets(String text) {
12-
return text.replaceAll('>', '_').replaceAll('<', '_');
13-
}
14-
15-
String stringEscape(String text, String quoteType) {
16-
return text
17-
.replaceAll('\\', r'\\')
18-
.replaceAll(quoteType, "\\${quoteType}")
19-
.replaceAllMapped(_escapeRegExp, (m) {
20-
return _escapeMap[m.input];
21-
});
22-
}
23-
2411
String stripComments(String str) {
2512
if (str == null) return null;
2613

lib/src/model.dart

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import 'package:quiver/core.dart';
1414
import 'html_utils.dart';
1515
import 'model_utils.dart';
1616
import 'package_meta.dart';
17+
import 'debug.dart';
1718
import '../markdown_processor.dart';
1819

1920
int byName(a, b) => a.name.toUpperCase().compareTo(b.name.toUpperCase());
@@ -84,12 +85,12 @@ abstract class ModelElement implements Comparable {
8485
if (e is MethodElement && !e.isOperator) {
8586
return new Method(e, library);
8687
}
87-
if (e is PropertyAccessorElement) {
88-
return new Accessor(e, library);
89-
}
9088
if (e is TopLevelVariableElement) {
9189
return new TopLevelVariable(e, library);
9290
}
91+
if (e is PropertyAccessorElement) {
92+
return new Accessor(e, library);
93+
}
9394
if (e is TypeParameterElement) {
9495
return new TypeParameter(e, library);
9596
}
@@ -414,29 +415,42 @@ class Package {
414415

415416
String toString() => isSdk ? 'SDK' : 'Package $name';
416417

417-
bool isDocumented(Element element) {
418+
Library findLibraryFor(final Element element) {
418419
if (element is LibraryElement) {
419-
return _libraries.any((lib) => lib.element == element);
420+
// will equality work here? or should we check names?
421+
return _libraries.firstWhere((lib) => lib.element == element,
422+
orElse: () => null);
420423
}
421424

422425
Element el;
423426
if (element is ClassMemberElement || element is PropertyAccessorElement) {
424-
el = element.enclosingElement;
427+
if (element.enclosingElement is! CompilationUnitElement) {
428+
el = element.enclosingElement;
429+
} else {
430+
// in this case, element is an accessor for a library-level variable,
431+
// likely a const. We, in this case, actually don't want the enclosing
432+
// element because it's a compilation unit, whatever that is.
433+
el = element;
434+
}
425435
} else if (element is TopLevelVariableElement) {
426-
TopLevelVariableElement variable = element;
427-
if (variable.getter != null) {
428-
el = variable.getter;
429-
} else if (variable.setter != null) {
430-
el = variable.setter;
436+
final TopLevelVariableElement variableElement = element;
437+
if (variableElement.getter != null) {
438+
el = variableElement.getter;
439+
} else if (variableElement.setter != null) {
440+
el = variableElement.setter;
431441
} else {
432-
el = variable;
442+
el = variableElement;
433443
}
434444
} else {
435445
el = element;
436446
}
437-
return _libraries.any((lib) => lib.hasInNamespace(el));
447+
debugger(when: element.name == 'NAME_SINGLEUNDERSCORE');
448+
return _libraries.firstWhere((lib) => lib.hasInNamespace(el),
449+
orElse: () => null);
438450
}
439451

452+
bool isDocumented(Element element) => findLibraryFor(element) != null;
453+
440454
String get href => 'index.html';
441455

442456
Library _getLibraryFor(Element e) {

test/model_test.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ void main() {
170170
Class specialList;
171171
Class subForDocComments;
172172

173+
ModelFunction short;
174+
173175
setUp(() {
174176
incorrectReference = exLibrary.constants
175177
.firstWhere((c) => c.name == 'incorrectDocReference');
@@ -193,6 +195,17 @@ void main() {
193195

194196
subForDocComments =
195197
fakeLibrary.classes.firstWhere((c) => c.name == 'SubForDocComments');
198+
199+
short = fakeLibrary.functions.firstWhere((f) => f.name == 'short');
200+
});
201+
202+
test('multi-underscore names in brackets do not become italicized', () {
203+
expect(short.documentation, contains('[NAME_WITH_TWO_UNDERSCORES]'));
204+
expect(short.documentation, contains('[NAME_SINGLEUNDERSCORE]'));
205+
expect(short.documentationAsHtml, contains(
206+
'<a href="fake/NAME_WITH_TWO_UNDERSCORES.html">NAME_WITH_TWO_UNDERSCORES</a>'));
207+
expect(short.documentationAsHtml, contains(
208+
'<a href="fake/NAME_SINGLEUNDERSCORE.html">NAME_SINGLEUNDERSCORE</a>'));
196209
});
197210

198211
test('still has brackets inside code blocks', () {

test_package/lib/fake.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@ const ConstantClass CUSTOM_CLASS = const ConstantClass('custom');
8484
/// Getting up in the morning can be hard.
8585
const String UP = 'up';
8686

87+
const String NAME_SINGLEUNDERSCORE = 'yay bug hunting';
88+
89+
const String NAME_WITH_TWO_UNDERSCORES = 'episode seven better be good';
90+
91+
/// Testing [NAME_WITH_TWO_UNDERSCORES] should not be italicized.
92+
///
93+
/// This name should link correctly: [NAME_SINGLEUNDERSCORE]
94+
void short() {}
95+
8796
/// Dynamic-typed down.
8897
@deprecated
8998
const DOWN = 'down';
@@ -376,6 +385,8 @@ class BaseForDocComments {
376385
/// Takes a [value] and returns a String.
377386
///
378387
/// This methods is inside of [BaseForDocComments]
388+
///
389+
/// Also [NAME_WITH_TWO_UNDERSCORES]
379390
String doAwesomeStuff(int value) => null;
380391
}
381392

0 commit comments

Comments
 (0)