Skip to content

Commit f06af8b

Browse files
authored
Extract nodoc into mixin and refactor (#2368)
* Extract nodoc into mixin and refactor * Rename files * Fix ordering
1 parent 1276e33 commit f06af8b

6 files changed

+75
-53
lines changed

lib/src/model/accessor.dart

+22-12
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,29 @@ class Accessor extends ModelElement implements EnclosedElement {
2323

2424
bool get isSynthetic => element.isSynthetic;
2525

26+
GetterSetterCombo _definingCombo;
27+
// The [enclosingCombo] where this element was defined.
28+
GetterSetterCombo get definingCombo {
29+
if (_definingCombo == null) {
30+
var variable = (element as PropertyAccessorElement).variable;
31+
var accessor = isGetter ? variable.getter : variable.setter;
32+
var accessorLibrary = Library(accessor.library, packageGraph);
33+
var definingAccessor =
34+
ModelElement.from(accessor, accessorLibrary, packageGraph)
35+
as Accessor;
36+
_definingCombo = definingAccessor.enclosingCombo;
37+
}
38+
return _definingCombo;
39+
}
40+
2641
String _sourceCode;
2742

2843
@override
2944
String get sourceCode {
3045
if (_sourceCode == null) {
3146
if (isSynthetic) {
32-
_sourceCode = packageGraph
33-
.getModelNodeFor((element as PropertyAccessorElement).variable)
34-
.sourceCode;
47+
_sourceCode =
48+
packageGraph.getModelNodeFor(definingCombo.element).sourceCode;
3549
} else {
3650
_sourceCode = super.sourceCode;
3751
}
@@ -42,19 +56,15 @@ class Accessor extends ModelElement implements EnclosedElement {
4256
@override
4357
String computeDocumentationComment() {
4458
if (isSynthetic) {
45-
var docComment =
46-
(element as PropertyAccessorElement).variable.documentationComment;
4759
// If we're a setter, only display something if we have something different than the getter.
4860
// TODO(jcollins-g): modify analyzer to do this itself?
4961
if (isGetter ||
50-
// TODO(jcollins-g): @nodoc reading from comments is at the wrong abstraction level here.
51-
(docComment != null &&
52-
(docComment.contains('<nodoc>') ||
53-
docComment.contains('@nodoc'))) ||
62+
definingCombo.hasNodoc ||
5463
(isSetter &&
55-
enclosingCombo.hasGetter &&
56-
enclosingCombo.getter.documentationComment != docComment)) {
57-
return stripComments(docComment);
64+
definingCombo.hasGetter &&
65+
definingCombo.getter.documentationComment !=
66+
definingCombo.documentationComment)) {
67+
return stripComments(definingCombo.documentationComment);
5868
} else {
5969
return '';
6070
}

lib/src/model/comment_processable.dart lib/src/model/documentation_comment.dart

+34-14
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import 'package:dartdoc/src/model/model.dart';
44
import 'package:dartdoc/src/render/model_element_renderer.dart';
55
import 'package:dartdoc/src/utils.dart';
66
import 'package:dartdoc/src/warnings.dart';
7-
import 'package:meta/meta.dart';
87
import 'package:path/path.dart' as path;
98

109
final _templatePattern = RegExp(
@@ -27,8 +26,33 @@ final _examplePattern = RegExp(r'{@example\s+([^}]+)}');
2726
///
2827
/// [processCommentWithoutTools] and [processComment] are the primary
2928
/// entrypoints.
30-
mixin CommentProcessable on Documentable, Warnable, Locatable, SourceCodeMixin {
31-
/// Process [documentationComment], performing various actions based on
29+
mixin DocumentationComment
30+
on Documentable, Warnable, Locatable, SourceCodeMixin {
31+
/// The documentation comment on the Element may be null, so memoization
32+
/// cannot rely on the null-ness of [_documentationComment], it must be
33+
/// more explicit.
34+
bool _documentationCommentComputed = false;
35+
String _documentationComment;
36+
37+
String get documentationComment {
38+
if (_documentationCommentComputed == false) {
39+
_documentationComment = computeDocumentationComment();
40+
_documentationCommentComputed = true;
41+
}
42+
return _documentationComment;
43+
}
44+
45+
/// Implement to derive the raw documentation comment string from the
46+
/// analyzer.
47+
String computeDocumentationComment();
48+
49+
/// Returns true if the raw documentation comment has a nodoc indication.
50+
bool get hasNodoc =>
51+
documentationComment != null &&
52+
(documentationComment.contains('@nodoc') ||
53+
documentationComment.contains('<nodoc>'));
54+
55+
/// Process a [documentationComment], performing various actions based on
3256
/// `{@}`-style directives, except `{@tool}`, returning the processed result.
3357
String processCommentWithoutTools(String documentationComment) {
3458
var docs = stripComments(documentationComment);
@@ -68,17 +92,13 @@ mixin CommentProcessable on Documentable, Warnable, Locatable, SourceCodeMixin {
6892
return docs;
6993
}
7094

71-
String get _sourceFileName => element.source.fullName;
95+
String get sourceFileName;
7296

73-
String get _fullyQualifiedNameWithoutLibrary =>
74-
// Remember, periods are legal in library names.
75-
fullyQualifiedName.replaceFirst('${library.fullyQualifiedName}.', '');
97+
String get fullyQualifiedNameWithoutLibrary;
7698

77-
path.Context get pathContext => packageGraph.resourceProvider.pathContext;
99+
path.Context get pathContext;
78100

79-
@visibleForTesting
80-
ModelElementRenderer get modelElementRenderer =>
81-
packageGraph.rendererFactory.modelElementRenderer;
101+
ModelElementRenderer get modelElementRenderer;
82102

83103
static const _allDirectiveNames = [
84104
'animation',
@@ -209,13 +229,13 @@ mixin CommentProcessable on Documentable, Warnable, Locatable, SourceCodeMixin {
209229
'SOURCE_LINE': characterLocation?.lineNumber.toString(),
210230
'SOURCE_COLUMN': characterLocation?.columnNumber.toString(),
211231
'SOURCE_PATH':
212-
(_sourceFileName == null || package?.packagePath == null)
232+
(sourceFileName == null || package?.packagePath == null)
213233
? null
214-
: path.relative(_sourceFileName, from: package.packagePath),
234+
: path.relative(sourceFileName, from: package.packagePath),
215235
'PACKAGE_PATH': package?.packagePath,
216236
'PACKAGE_NAME': package?.name,
217237
'LIBRARY_NAME': library?.fullyQualifiedName,
218-
'ELEMENT_NAME': _fullyQualifiedNameWithoutLibrary,
238+
'ELEMENT_NAME': fullyQualifiedNameWithoutLibrary,
219239
'INVOCATION_INDEX': invocationIndex.toString(),
220240
'PACKAGE_INVOCATION_INDEX':
221241
(package.toolInvocationIndex++).toString(),

lib/src/model/getter_setter_combo.dart

+3-2
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ mixin GetterSetterCombo on ModelElement {
156156
String get getterSetterDocumentationComment {
157157
var buffer = StringBuffer();
158158

159-
if (hasPublicGetter && !getter.isSynthetic) {
159+
// Check for synthetic before public, always, or stack overflow.
160+
if (hasGetter && !getter.isSynthetic && getter.isPublic) {
160161
assert(getter.documentationFrom.length == 1);
161162
// We have to check against dropTextFrom here since documentationFrom
162163
// doesn't yield the real elements for GetterSetterCombos.
@@ -167,7 +168,7 @@ mixin GetterSetterCombo on ModelElement {
167168
}
168169
}
169170

170-
if (hasPublicSetter && !setter.isSynthetic) {
171+
if (hasSetter && !setter.isSynthetic && setter.isPublic) {
171172
assert(setter.documentationFrom.length == 1);
172173
if (!config.dropTextFrom
173174
.contains(setter.documentationFrom.first.element.library.name)) {

lib/src/model/model.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ export 'canonicalization.dart';
77
export 'categorization.dart';
88
export 'category.dart';
99
export 'class.dart';
10-
export 'comment_processable.dart';
1110
export 'constructor.dart';
1211
export 'container.dart';
1312
export 'container_member.dart';
1413
export 'documentable.dart';
1514
export 'documentation.dart';
15+
export 'documentation_comment.dart';
1616
export 'dynamic.dart';
1717
export 'enclosed_element.dart';
1818
export 'enum.dart';

lib/src/model/model_element.dart

+15-24
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import 'package:analyzer/src/dart/element/member.dart'
1616
import 'package:collection/collection.dart';
1717
import 'package:dartdoc/src/dartdoc_options.dart';
1818
import 'package:dartdoc/src/element_type.dart';
19-
import 'package:dartdoc/src/model/comment_processable.dart';
19+
import 'package:dartdoc/src/model/documentation_comment.dart';
2020
import 'package:dartdoc/src/model/feature_set.dart';
2121
import 'package:dartdoc/src/model/model.dart';
2222
import 'package:dartdoc/src/model_utils.dart' as utils;
@@ -135,7 +135,7 @@ abstract class ModelElement extends Canonicalization
135135
SourceCodeMixin,
136136
Indexable,
137137
FeatureSet,
138-
CommentProcessable
138+
DocumentationComment
139139
implements Comparable<ModelElement>, Documentable {
140140
final Element _element;
141141

@@ -472,13 +472,10 @@ abstract class ModelElement extends Canonicalization
472472
!(enclosingElement as Extension).isPublic) {
473473
_isPublic = false;
474474
} else {
475-
var docComment = documentationComment;
476-
if (docComment == null) {
475+
if (documentationComment == null) {
477476
_isPublic = utils.hasPublicName(element);
478477
} else {
479-
_isPublic = utils.hasPublicName(element) &&
480-
!(docComment.contains('@nodoc') ||
481-
docComment.contains('<nodoc>'));
478+
_isPublic = utils.hasPublicName(element) && !hasNodoc;
482479
}
483480
}
484481
}
@@ -821,7 +818,7 @@ abstract class ModelElement extends Canonicalization
821818
/// does not exist.
822819
String get extendedDocLink {
823820
if (hasExtendedDocumentation) {
824-
return _modelElementRenderer.renderExtendedDocLink(this);
821+
return modelElementRenderer.renderExtendedDocLink(this);
825822
}
826823
return '';
827824
}
@@ -843,13 +840,15 @@ abstract class ModelElement extends Canonicalization
843840
}
844841

845842
String _fullyQualifiedNameWithoutLibrary;
843+
@override
846844
String get fullyQualifiedNameWithoutLibrary {
847845
// Remember, periods are legal in library names.
848846
_fullyQualifiedNameWithoutLibrary ??=
849847
fullyQualifiedName.replaceFirst('${library.fullyQualifiedName}.', '');
850848
return _fullyQualifiedNameWithoutLibrary;
851849
}
852850

851+
@override
853852
String get sourceFileName => element.source.fullName;
854853

855854
CharacterLocation _characterLocation;
@@ -956,7 +955,9 @@ abstract class ModelElement extends Canonicalization
956955
return _linkedName;
957956
}
958957

959-
ModelElementRenderer get _modelElementRenderer =>
958+
@visibleForTesting
959+
@override
960+
ModelElementRenderer get modelElementRenderer =>
960961
packageGraph.rendererFactory.modelElementRenderer;
961962

962963
ParameterRenderer get _parameterRenderer =>
@@ -1067,6 +1068,9 @@ abstract class ModelElement extends Canonicalization
10671068
return _allParameters;
10681069
}
10691070

1071+
@override
1072+
path.Context get pathContext => packageGraph.resourceProvider.pathContext;
1073+
10701074
List<Parameter> get parameters {
10711075
if (!canHaveParameters) {
10721076
throw StateError('$element cannot have parameters');
@@ -1112,22 +1116,9 @@ abstract class ModelElement extends Canonicalization
11121116
extendedDebug: extendedDebug);
11131117
}
11141118

1119+
@override
11151120
String computeDocumentationComment() => element.documentationComment;
11161121

1117-
/// The documentation comment on the Element may be null, so memoization
1118-
/// cannot rely on the null-ness of [_documentationComment], it must be
1119-
/// more explicit.
1120-
bool _documentationCommentComputed = false;
1121-
String _documentationComment;
1122-
1123-
String get documentationComment {
1124-
if (_documentationCommentComputed == false) {
1125-
_documentationComment = computeDocumentationComment();
1126-
_documentationCommentComputed = true;
1127-
}
1128-
return _documentationComment;
1129-
}
1130-
11311122
/// Unconditionally precache local documentation.
11321123
///
11331124
/// Use only in factory for [PackageGraph].
@@ -1191,7 +1182,7 @@ abstract class ModelElement extends Canonicalization
11911182
return htmlEscape.convert(name);
11921183
}
11931184

1194-
return _modelElementRenderer.renderLinkedName(this);
1185+
return modelElementRenderer.renderLinkedName(this);
11951186
}
11961187

11971188
/// Replace &lt;<dartdoc-html>[digest]</dartdoc-html>&gt; in API comments with
File renamed without changes.

0 commit comments

Comments
 (0)