Skip to content

Commit af68c2d

Browse files
DanTupCommit Queue
authored andcommitted
[analysis_server] Add documentation to editable arguments that represent fields
If an argument is for a field parameter, this includes the documentation from that field, so that the property editor can show the same content you'd see by hovering over the argument name in the editor. See flutter/devtools#8938 Change-Id: Iebee757dd42fe9da2c8938c95febc99c0c96b609 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/411684 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]> Reviewed-by: Elliott Brooks <[email protected]>
1 parent ef71100 commit af68c2d

File tree

5 files changed

+69
-11
lines changed

5 files changed

+69
-11
lines changed

pkg/analysis_server/lib/src/lsp/handlers/custom/editable_arguments/editable_arguments_mixin.dart

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ typedef EditableInvocationInfo =
2828
mixin EditableArgumentsMixin {
2929
DartdocDirectiveInfo getDartdocDirectiveInfoFor(ResolvedUnitResult result);
3030

31+
String? getDocumentation(ResolvedUnitResult result, Element2 element) {
32+
var dartDocInfo = getDartdocDirectiveInfoFor(result);
33+
var dartDocComputer = DartDocumentationComputer(dartDocInfo);
34+
var dartDoc = dartDocComputer.compute(element);
35+
36+
return dartDoc?.full;
37+
}
38+
3139
/// Gets the argument list at [offset] that can be edited.
3240
EditableInvocationInfo? getInvocationInfo(
3341
ResolvedUnitResult result,
@@ -48,19 +56,11 @@ mixin EditableArgumentsMixin {
4856
widgetName = invocation.constructorName.type.name2.lexeme;
4957

5058
if (invocation.constructorName.element case var element?) {
51-
var dartDocInfo = getDartdocDirectiveInfoFor(result);
52-
var dartDocComputer = DartDocumentationComputer(dartDocInfo);
53-
var dartDoc = dartDocComputer.compute(element);
54-
55-
widgetDocumentation = dartDoc?.full;
59+
widgetDocumentation = getDocumentation(result, element);
5660
}
5761
} else if (invocation is InvocationExpression) {
5862
if (invocation.function case Identifier(:var element?)) {
59-
var dartDocInfo = getDartdocDirectiveInfoFor(result);
60-
var dartDocComputer = DartDocumentationComputer(dartDocInfo);
61-
var dartDoc = dartDocComputer.compute(element);
62-
63-
widgetDocumentation = dartDoc?.full;
63+
widgetDocumentation = getDocumentation(result, element);
6464
}
6565
}
6666

pkg/analysis_server/lib/src/lsp/handlers/custom/editable_arguments/handler_editable_arguments.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ class EditableArgumentsHandler
117117
var editableArguments = [
118118
for (var parameter in parameters)
119119
_toEditableArgument(
120+
result,
120121
parameter,
121122
parameterArguments[parameter],
122123
positionalIndex: positionalParameterIndexes[parameter],
@@ -148,6 +149,7 @@ class EditableArgumentsHandler
148149
/// Converts a [parameter]/[argument] pair into an [EditableArgument] if it
149150
/// is an argument that can be edited.
150151
EditableArgument? _toEditableArgument(
152+
ResolvedUnitResult result,
151153
FormalParameterElement parameter,
152154
Expression? argument, {
153155
int? positionalIndex,
@@ -223,8 +225,11 @@ class EditableArgumentsHandler
223225
displayValue = null;
224226
}
225227

228+
var documentation = getDocumentation(result, parameter);
229+
226230
return EditableArgument(
227231
name: parameter.displayName,
232+
documentation: documentation,
228233
type: type,
229234
value: value,
230235
displayValue: displayValue,

pkg/analysis_server/test/shared/shared_editable_arguments_tests.dart

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ $content
4040
return hasArgs(contains(matcher));
4141
}
4242

43-
Matcher hasArgNamed(String argumentName) {
43+
Matcher hasArgNamed(String argumentName, {String? doc}) {
4444
return hasArg(isArg(argumentName));
4545
}
4646

@@ -70,6 +70,7 @@ $content
7070

7171
Matcher isArg(
7272
String name, {
73+
Object? documentation = anything,
7374
Object? type = anything,
7475
Object? value = anything,
7576
Object? displayValue = anything,
@@ -83,6 +84,7 @@ $content
8384
}) {
8485
return isA<EditableArgument>()
8586
.having((arg) => arg.name, 'name', name)
87+
.having((arg) => arg.documentation, 'documentation', documentation)
8688
.having((arg) => arg.type, 'type', type)
8789
.having((arg) => arg.value, 'value', value)
8890
.having((arg) => arg.displayValue, 'displayValue', displayValue)
@@ -223,6 +225,41 @@ class MyWidget extends StatelessWidget {
223225
expect(result, hasArg(isArg('a', defaultValue: null)));
224226
}
225227

228+
test_documentation_fieldParameter_literal() async {
229+
var result = await getEditableArgumentsFor('''
230+
class MyWidget extends StatelessWidget {
231+
/// Documentation for x.
232+
final int x;
233+
234+
/// Creates a MyWidget.
235+
const MyWidget(this.x);
236+
237+
@override
238+
Widget build(BuildContext context) => MyW^idget(1);
239+
}
240+
''');
241+
expect(result, hasArg(isArg('x', documentation: 'Documentation for x.')));
242+
}
243+
244+
test_documentation_fieldParameter_macro() async {
245+
var result = await getEditableArgumentsFor('''
246+
/// {@template shared_docs}
247+
/// Shared docs.
248+
/// {@endtemplate}
249+
class MyWidget extends StatelessWidget {
250+
/// {@macro shared_docs}
251+
final int x;
252+
253+
/// Creates a MyWidget.
254+
const MyWidget(this.x);
255+
256+
@override
257+
Widget build(BuildContext context) => MyW^idget(1);
258+
}
259+
''');
260+
expect(result, hasArg(isArg('x', documentation: 'Shared docs.')));
261+
}
262+
226263
test_documentation_literal() async {
227264
var result = await getEditableArgumentsFor('''
228265
class MyWidget extends StatelessWidget {

pkg/analysis_server/tool/lsp_spec/generate_all.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ List<LspEntity> getCustomClasses() {
432432
type: 'string',
433433
comment: 'The name of the corresponding parameter.',
434434
),
435+
field('documentation', type: 'string', canBeUndefined: true),
435436
field(
436437
'type',
437438
type: 'string',

third_party/pkg/language_server_protocol/lib/protocol_custom_generated.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,8 @@ class EditableArgument implements ToJsonable {
14491449
/// same as the value field, for example an expression or named constant.
14501450
final String? displayValue;
14511451

1452+
final String? documentation;
1453+
14521454
/// Whether an explicit argument exists for this parameter in the code.
14531455
///
14541456
/// This will be true even if the explicit argument is the same value as the
@@ -1499,6 +1501,7 @@ class EditableArgument implements ToJsonable {
14991501
EditableArgument({
15001502
this.defaultValue,
15011503
this.displayValue,
1504+
this.documentation,
15021505
required this.hasArgument,
15031506
required this.isEditable,
15041507
required this.isNullable,
@@ -1513,6 +1516,7 @@ class EditableArgument implements ToJsonable {
15131516
int get hashCode => Object.hash(
15141517
defaultValue,
15151518
displayValue,
1519+
documentation,
15161520
hasArgument,
15171521
isEditable,
15181522
isNullable,
@@ -1530,6 +1534,7 @@ class EditableArgument implements ToJsonable {
15301534
other.runtimeType == EditableArgument &&
15311535
defaultValue == other.defaultValue &&
15321536
displayValue == other.displayValue &&
1537+
documentation == other.documentation &&
15331538
hasArgument == other.hasArgument &&
15341539
isEditable == other.isEditable &&
15351540
isNullable == other.isNullable &&
@@ -1550,6 +1555,9 @@ class EditableArgument implements ToJsonable {
15501555
if (displayValue != null) {
15511556
result['displayValue'] = displayValue;
15521557
}
1558+
if (documentation != null) {
1559+
result['documentation'] = documentation;
1560+
}
15531561
result['hasArgument'] = hasArgument;
15541562
result['isEditable'] = isEditable;
15551563
result['isNullable'] = isNullable;
@@ -1577,6 +1585,10 @@ class EditableArgument implements ToJsonable {
15771585
allowsUndefined: true, allowsNull: false)) {
15781586
return false;
15791587
}
1588+
if (!_canParseString(obj, reporter, 'documentation',
1589+
allowsUndefined: true, allowsNull: false)) {
1590+
return false;
1591+
}
15801592
if (!_canParseBool(obj, reporter, 'hasArgument',
15811593
allowsUndefined: false, allowsNull: false)) {
15821594
return false;
@@ -1618,6 +1630,8 @@ class EditableArgument implements ToJsonable {
16181630
final defaultValue = defaultValueJson;
16191631
final displayValueJson = json['displayValue'];
16201632
final displayValue = displayValueJson as String?;
1633+
final documentationJson = json['documentation'];
1634+
final documentation = documentationJson as String?;
16211635
final hasArgumentJson = json['hasArgument'];
16221636
final hasArgument = hasArgumentJson as bool;
16231637
final isEditableJson = json['isEditable'];
@@ -1640,6 +1654,7 @@ class EditableArgument implements ToJsonable {
16401654
return EditableArgument(
16411655
defaultValue: defaultValue,
16421656
displayValue: displayValue,
1657+
documentation: documentation,
16431658
hasArgument: hasArgument,
16441659
isEditable: isEditable,
16451660
isNullable: isNullable,

0 commit comments

Comments
 (0)