Skip to content

Commit 6c1d35d

Browse files
authored
documentationComment can now be non-nullable (#2819)
* Straight move * Partial * delete experiment * rebuild * moved computeDocumentationComment and documentationComment * Move more documentation comment handling * remove ??= from a cut and paste * Documentation comment move for combos * better as a getter * Untangle synthetic combo documentation in preparing for non-null * rebuild * documentationComment can be made non-nullable * Update test.yaml to delete sdk check from beta branch * tab conversion error * correct name
1 parent 590edba commit 6c1d35d

File tree

8 files changed

+123
-47
lines changed

8 files changed

+123
-47
lines changed

.github/workflows/test.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ jobs:
3636
job: flutter
3737
- sdk: beta
3838
job: sdk-analyzer
39+
# TODO(jcollins-g): Delete exception as 2.15 beta 2 gets underway
40+
- sdk: beta
41+
job: sdk-docs
3942

4043
steps:
4144
- name: Store date

lib/src/generator/templates.runtime_renderers.dart

+30
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,13 @@ class _Renderer_Accessor extends RendererBase<Accessor> {
165165
parent: r);
166166
},
167167
),
168+
'hasDocumentationComment': Property(
169+
getValue: (CT_ c) => c.hasDocumentationComment,
170+
renderVariable: (CT_ c, Property<CT_> self,
171+
List<String> remainingNames) =>
172+
self.renderSimpleVariable(c, remainingNames, 'bool'),
173+
getBool: (CT_ c) => c.hasDocumentationComment == true,
174+
),
168175
'href': Property(
169176
getValue: (CT_ c) => c.href,
170177
renderVariable:
@@ -4018,6 +4025,13 @@ class _Renderer_DocumentationComment
40184025
parent: r);
40194026
},
40204027
),
4028+
'hasDocumentationComment': Property(
4029+
getValue: (CT_ c) => c.hasDocumentationComment,
4030+
renderVariable: (CT_ c, Property<CT_> self,
4031+
List<String> remainingNames) =>
4032+
self.renderSimpleVariable(c, remainingNames, 'bool'),
4033+
getBool: (CT_ c) => c.hasDocumentationComment == true,
4034+
),
40214035
'hasNodoc': Property(
40224036
getValue: (CT_ c) => c.hasNodoc,
40234037
renderVariable: (CT_ c, Property<CT_> self,
@@ -6003,6 +6017,13 @@ class _Renderer_GetterSetterCombo extends RendererBase<GetterSetterCombo> {
60036017
self.renderSimpleVariable(c, remainingNames, 'bool'),
60046018
getBool: (CT_ c) => c.hasAccessorsWithDocs == true,
60056019
),
6020+
'hasDocumentationComment': Property(
6021+
getValue: (CT_ c) => c.hasDocumentationComment,
6022+
renderVariable: (CT_ c, Property<CT_> self,
6023+
List<String> remainingNames) =>
6024+
self.renderSimpleVariable(c, remainingNames, 'bool'),
6025+
getBool: (CT_ c) => c.hasDocumentationComment == true,
6026+
),
60066027
'hasExplicitGetter': Property(
60076028
getValue: (CT_ c) => c.hasExplicitGetter,
60086029
renderVariable: (CT_ c, Property<CT_> self,
@@ -9720,6 +9741,13 @@ class _Renderer_ModelElement extends RendererBase<ModelElement> {
97209741
self.renderSimpleVariable(c, remainingNames, 'bool'),
97219742
getBool: (CT_ c) => c.hasDocumentation == true,
97229743
),
9744+
'hasDocumentationComment': Property(
9745+
getValue: (CT_ c) => c.hasDocumentationComment,
9746+
renderVariable: (CT_ c, Property<CT_> self,
9747+
List<String> remainingNames) =>
9748+
self.renderSimpleVariable(c, remainingNames, 'bool'),
9749+
getBool: (CT_ c) => c.hasDocumentationComment == true,
9750+
),
97239751
'hasExtendedDocumentation': Property(
97249752
getValue: (CT_ c) => c.hasExtendedDocumentation,
97259753
renderVariable: (CT_ c, Property<CT_> self,
@@ -15224,6 +15252,7 @@ const _invisibleGetters = {
1522415252
'documentationAsHtml',
1522515253
'elementDocumentation',
1522615254
'documentationComment',
15255+
'hasDocumentationComment',
1522715256
'hasNodoc',
1522815257
'sourceFileName',
1522915258
'fullyQualifiedNameWithoutLibrary',
@@ -15441,6 +15470,7 @@ const _invisibleGetters = {
1544115470
'getterSetterBothAvailable',
1544215471
'oneLineDoc',
1544315472
'documentationComment',
15473+
'hasDocumentationComment',
1544415474
'modelType',
1544515475
'isCallable',
1544615476
'hasParameters',

lib/src/model/accessor.dart

+39-12
Original file line numberDiff line numberDiff line change
@@ -80,22 +80,49 @@ class Accessor extends ModelElement implements EnclosedElement {
8080
: _documentationComment ??= () {
8181
_documentationCommentComputed = true;
8282
if (isSynthetic) {
83-
// If we're a setter, only display something if we have something different than the getter.
84-
// TODO(jcollins-g): modify analyzer to do this itself?
85-
if (isGetter ||
86-
definingCombo.hasNodoc ||
87-
(isSetter &&
88-
definingCombo.hasGetter &&
89-
definingCombo.getter.documentationComment !=
90-
definingCombo.documentationComment)) {
91-
return stripComments(definingCombo.documentationComment);
92-
} else {
93-
return '';
94-
}
83+
return _syntheticDocumentationComment;
9584
}
9685
return stripComments(super.documentationComment);
9786
}();
9887

88+
String /*!*/ __syntheticDocumentationComment;
89+
90+
/// Build a documentation comment for this accessor assuming it is synthetic.
91+
/// Value here is not useful if [isSynthetic] is false.
92+
String /*!*/ get _syntheticDocumentationComment =>
93+
__syntheticDocumentationComment ??= () {
94+
if (_hasSyntheticDocumentationComment) {
95+
return definingCombo.documentationComment ?? '';
96+
}
97+
return '';
98+
}();
99+
100+
/// If this is a getter, assume we want synthetic documentation.
101+
/// If the definingCombo has a nodoc tag, we want synthetic documentation
102+
/// for a synthetic accessor just in case it is inherited somewhere
103+
/// down the line due to split inheritance.
104+
bool get _hasSyntheticDocumentationComment =>
105+
(isGetter || definingCombo.hasNodoc || _comboDocsAreIndependent()) &&
106+
definingCombo.hasDocumentationComment;
107+
108+
// If we're a setter, and a getter exists, do not add synthetic
109+
// documentation if the combo's documentation is actually derived
110+
// from that getter.
111+
bool _comboDocsAreIndependent() {
112+
if (isSetter && definingCombo.hasGetter) {
113+
if (definingCombo.getter.isSynthetic ||
114+
!definingCombo.documentationFrom.contains(this)) {
115+
return true;
116+
}
117+
}
118+
return false;
119+
}
120+
121+
@override
122+
bool get hasDocumentationComment => isSynthetic
123+
? _hasSyntheticDocumentationComment
124+
: element.documentationComment != null;
125+
99126
@override
100127
void warn(PackageWarning kind,
101128
{String message,

lib/src/model/documentation_comment.dart

+7-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ mixin DocumentationComment
5252
@override
5353
List<DocumentationComment> get documentationFrom =>
5454
_documentationFrom ??= () {
55-
if (documentationComment == null &&
55+
if (!hasDocumentationComment &&
5656
this is Inheritable &&
5757
(this as Inheritable).overriddenElement != null) {
5858
return (this as Inheritable).overriddenElement.documentationFrom;
@@ -81,11 +81,15 @@ mixin DocumentationComment
8181
return _elementDocumentation;
8282
}
8383

84-
String get documentationComment;
84+
String /*!*/ get documentationComment;
85+
86+
/// True if [this] has a synthetic/inherited or local documentation
87+
/// comment. False otherwise.
88+
bool get hasDocumentationComment;
8589

8690
/// Returns true if the raw documentation comment has a nodoc indication.
8791
bool get hasNodoc {
88-
if (documentationComment != null &&
92+
if (hasDocumentationComment &&
8993
(documentationComment.contains('@nodoc') ||
9094
documentationComment.contains('<nodoc>'))) {
9195
return true;

lib/src/model/getter_setter_combo.dart

+38-29
Original file line numberDiff line numberDiff line change
@@ -161,44 +161,53 @@ mixin GetterSetterCombo on ModelElement {
161161
bool _documentationCommentComputed = false;
162162
String _documentationComment;
163163
@override
164-
String get documentationComment => _documentationCommentComputed
164+
String /*!*/ get documentationComment => _documentationCommentComputed
165165
? _documentationComment
166166
: _documentationComment ??= () {
167167
_documentationCommentComputed = true;
168168
var docs = _getterSetterDocumentationComment;
169-
if (docs.isEmpty) return element.documentationComment;
169+
if (docs.isEmpty) return element.documentationComment ?? '';
170170
return docs;
171171
}();
172172

173-
/// Derive a synthetic documentation comment using the documentation from
174-
String get _getterSetterDocumentationComment {
175-
var buffer = StringBuffer();
176-
177-
// Check for synthetic before public, always, or stack overflow.
178-
if (hasGetter && !getter.isSynthetic && getter.isPublic) {
179-
assert(getter.documentationFrom.length == 1);
180-
// We have to check against dropTextFrom here since documentationFrom
181-
// doesn't yield the real elements for GetterSetterCombos.
182-
if (!config.dropTextFrom
183-
.contains(getter.documentationFrom.first.element.library.name)) {
184-
var docs = getter.documentationFrom.first.documentationComment;
185-
if (docs != null) buffer.write(docs);
186-
}
187-
}
173+
@override
174+
bool get hasDocumentationComment =>
175+
_getterSetterDocumentationComment.isNotEmpty ||
176+
element.documentationComment != null;
177+
178+
String __getterSetterDocumentationComment;
179+
180+
/// Derive a documentation comment for the combo by copying documentation
181+
/// from the [getter] and/or [setter].
182+
String /*!*/ get _getterSetterDocumentationComment =>
183+
__getterSetterDocumentationComment ??= () {
184+
var buffer = StringBuffer();
188185

189-
if (hasSetter && !setter.isSynthetic && setter.isPublic) {
190-
assert(setter.documentationFrom.length == 1);
191-
if (!config.dropTextFrom
192-
.contains(setter.documentationFrom.first.element.library.name)) {
193-
var docs = setter.documentationFrom.first.documentationComment;
194-
if (docs != null) {
195-
if (buffer.isNotEmpty) buffer.write('\n\n');
196-
buffer.write(docs);
186+
// Check for synthetic before public, always, or stack overflow.
187+
if (hasGetter && !getter.isSynthetic && getter.isPublic) {
188+
assert(getter.documentationFrom.length == 1);
189+
var fromGetter = getter.documentationFrom.first;
190+
// We have to check against dropTextFrom here since documentationFrom
191+
// doesn't yield the real elements for GetterSetterCombos.
192+
if (!config.dropTextFrom.contains(fromGetter.element.library.name)) {
193+
if (fromGetter.hasDocumentationComment) {
194+
buffer.write(fromGetter.documentationComment);
195+
}
196+
}
197197
}
198-
}
199-
}
200-
return buffer.toString();
201-
}
198+
199+
if (hasSetter && !setter.isSynthetic && setter.isPublic) {
200+
assert(setter.documentationFrom.length == 1);
201+
var fromSetter = setter.documentationFrom.first;
202+
if (!config.dropTextFrom.contains(fromSetter.element.library.name)) {
203+
if (fromSetter.hasDocumentationComment) {
204+
if (buffer.isNotEmpty) buffer.write('\n\n');
205+
buffer.write(fromSetter.documentationComment);
206+
}
207+
}
208+
}
209+
return buffer.toString();
210+
}();
202211

203212
ElementType get modelType {
204213
if (hasGetter) return getter.modelType.returnType;

lib/src/model/model_element.dart

+4-1
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,10 @@ abstract class ModelElement extends Canonicalization
917917
}
918918

919919
@override
920-
String get documentationComment => element.documentationComment;
920+
String /*!*/ get documentationComment => element.documentationComment ?? '';
921+
922+
@override
923+
bool get hasDocumentationComment => element.documentationComment != null;
921924

922925
String _sourceCode;
923926
@override

lib/src/model/package_graph.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ class PackageGraph with CommentReferable, Nameable {
123123

124124
Iterable<Future<void>> precacheOneElement(ModelElement m) sync* {
125125
for (var d
126-
in m.documentationFrom.where((d) => d.documentationComment != null)) {
126+
in m.documentationFrom.where((d) => d.hasDocumentationComment)) {
127127
if (d.needsPrecache && !precachedElements.contains(d)) {
128128
precachedElements.add(d);
129129
yield d.precacheLocalDocs();

test/end2end/model_test.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ void main() {
630630
() {
631631
// Verify setup of the test is correct.
632632
expect(invokeToolParentDoc.isCanonical, isTrue);
633-
expect(invokeToolParentDoc.documentationComment, isNull);
633+
expect(invokeToolParentDoc.hasDocumentationComment, isFalse);
634634
// Error message here might look strange due to toString() on Methods, but if this
635635
// fails that means we don't have the correct invokeToolParentDoc instance.
636636
expect(invokeToolParentDoc.documentationFrom,

0 commit comments

Comments
 (0)