Skip to content

Commit 204039c

Browse files
DanTupCommit Queue
authored andcommitted
[analysis_server] Add "defaultValue" to EditableArguments API
This adds a new field "defaultValue" to the API response that contains the default value for a parameter. Change-Id: Ief11da553d57871ad1e3fab54c731cbc98d674a4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/406000 Reviewed-by: Elliott Brooks <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 671bbe9 commit 204039c

File tree

5 files changed

+239
-34
lines changed

5 files changed

+239
-34
lines changed

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,17 +152,17 @@ mixin EditableArgumentsMixin {
152152
return null;
153153
}
154154

155+
/// Returns a list of the constants of an enum constant prefixed with the enum
156+
/// name.
157+
List<String> getQualifiedEnumConstantNames(EnumElement2 element3) =>
158+
element3.constants2.map(getQualifiedEnumConstantName).nonNulls.toList();
159+
155160
/// Returns the name of an enum constant prefixed with the enum name.
156-
String? getQualifiedEnumConstantName(FieldElement2 enumConstant) {
161+
static String? getQualifiedEnumConstantName(FieldElement2 enumConstant) {
157162
var enumName = enumConstant.enclosingElement2.name3;
158163
var name = enumConstant.name3;
159164
return enumName != null && name != null ? '$enumName.$name' : null;
160165
}
161-
162-
/// Returns a list of the constants of an enum constant prefixed with the enum
163-
/// name.
164-
List<String> getQualifiedEnumConstantNames(EnumElement2 element3) =>
165-
element3.constants2.map(getQualifiedEnumConstantName).nonNulls.toList();
166166
}
167167

168168
extension on InvocationExpressionImpl {

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

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,14 @@ class EditableArgumentsHandler
167167
}) {
168168
var valueExpression =
169169
argument is NamedExpression ? argument.expression : argument;
170+
var hasArgument = valueExpression != null;
170171

171172
// Lazily compute the values if we will use this parameter/argument.
172173
late var values = _getValues(parameter, valueExpression);
173174

174175
String? type;
175176
Object? value;
177+
Object? defaultValue;
176178
List<String>? options;
177179

178180
// Determine whether a value for this parameter is editable.
@@ -186,40 +188,39 @@ class EditableArgumentsHandler
186188
if (parameter.type.isDartCoreDouble) {
187189
type = 'double';
188190
value =
189-
(values.argumentValue ?? values.parameterValue)?.toDoubleValue() ??
190-
(values.argumentValue ?? values.parameterValue)?.toIntValue();
191+
values.argumentValue?.toDoubleValue() ??
192+
values.argumentValue?.toIntValue();
193+
defaultValue =
194+
values.parameterValue?.toDoubleValue() ??
195+
values.parameterValue?.toIntValue();
191196
} else if (parameter.type.isDartCoreInt) {
192197
type = 'int';
193-
value = (values.argumentValue ?? values.parameterValue)?.toIntValue();
198+
value = values.argumentValue?.toIntValue();
199+
defaultValue = values.parameterValue?.toIntValue();
194200
} else if (parameter.type.isDartCoreBool) {
195201
type = 'bool';
196-
value = (values.argumentValue ?? values.parameterValue)?.toBoolValue();
202+
value = values.argumentValue?.toBoolValue();
203+
defaultValue = values.parameterValue?.toBoolValue();
197204
} else if (parameter.type.isDartCoreString) {
198205
type = 'string';
199-
value = (values.argumentValue ?? values.parameterValue)?.toStringValue();
206+
value = values.argumentValue?.toStringValue();
207+
defaultValue = values.parameterValue?.toStringValue();
200208
} else if (parameter.type case InterfaceType(:EnumElement2 element3)) {
201209
type = 'enum';
202210
options = getQualifiedEnumConstantNames(element3);
203-
204-
// Try to match the argument value up with the enum.
205-
var valueObject = values.argumentValue ?? values.parameterValue;
206-
if (valueObject?.type case InterfaceType(
207-
element3: EnumElement2 valueElement,
208-
) when element3 == valueElement) {
209-
var index = valueObject?.getField('index')?.toIntValue();
210-
if (index != null) {
211-
var enumConstant = element3.constants2.elementAtOrNull(index);
212-
if (enumConstant != null) {
213-
value = getQualifiedEnumConstantName(enumConstant);
214-
}
215-
}
216-
}
211+
value = values.argumentValue?.toEnumStringValue(element3);
212+
defaultValue = values.parameterValue?.toEnumStringValue(element3);
217213
} else {
218214
// TODO(dantup): Determine which parameters we don't include (such as
219215
// Widgets) and which we include just without values.
220216
return null;
221217
}
222218

219+
// If no argument is present, we always populate "value" with the default.
220+
if (!hasArgument) {
221+
value = defaultValue;
222+
}
223+
223224
var isEditable = notEditableReason == null;
224225

225226
// Compute a displayValue.
@@ -246,6 +247,7 @@ class EditableArgumentsHandler
246247
displayValue: displayValue,
247248
options: options,
248249
isDefault: values.isDefault,
250+
defaultValue: defaultValue,
249251
hasArgument: valueExpression != null,
250252
isRequired: parameter.isRequired,
251253
isNullable:
@@ -255,3 +257,23 @@ class EditableArgumentsHandler
255257
);
256258
}
257259
}
260+
261+
extension on DartObject? {
262+
Object? toEnumStringValue(EnumElement2 element3) {
263+
var valueObject = this;
264+
if (valueObject?.type case InterfaceType(
265+
element3: EnumElement2 valueElement,
266+
) when element3 == valueElement) {
267+
var index = valueObject?.getField('index')?.toIntValue();
268+
if (index != null) {
269+
var enumConstant = element3.constants2.elementAtOrNull(index);
270+
if (enumConstant != null) {
271+
return EditableArgumentsMixin.getQualifiedEnumConstantName(
272+
enumConstant,
273+
);
274+
}
275+
}
276+
}
277+
return null;
278+
}
279+
}

pkg/analysis_server/test/shared/shared_editable_arguments_tests.dart

Lines changed: 169 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ $content
7575
Object? displayValue = anything,
7676
Object? hasArgument = anything,
7777
Object? isDefault = anything,
78+
Object? defaultValue = anything,
7879
Object? isRequired = anything,
7980
Object? isNullable = anything,
8081
Object? isEditable = anything,
@@ -88,6 +89,7 @@ $content
8889
.having((arg) => arg.displayValue, 'displayValue', displayValue)
8990
.having((arg) => arg.hasArgument, 'hasArgument', hasArgument)
9091
.having((arg) => arg.isDefault, 'isDefault', isDefault)
92+
.having((arg) => arg.defaultValue, 'defaultValue', defaultValue)
9193
.having((arg) => arg.isRequired, 'isRequired', isRequired)
9294
.having((arg) => arg.isNullable, 'isNullable', isNullable)
9395
.having((arg) => arg.isEditable, 'isEditable', isEditable)
@@ -125,6 +127,104 @@ $content
125127
);
126128
}
127129

130+
test_defaultValue_named_default() async {
131+
var result = await getEditableArgumentsFor(r'''
132+
class MyWidget extends StatelessWidget {
133+
const MyWidget({int? a = 1});
134+
135+
@override
136+
Widget build(BuildContext context) => MyW^idget(a: 1);
137+
}
138+
''');
139+
expect(result, hasArg(isArg('a', defaultValue: 1)));
140+
}
141+
142+
test_defaultValue_named_default_constantVariable() async {
143+
var result = await getEditableArgumentsFor(r'''
144+
class MyWidget extends StatelessWidget {
145+
static const constantOne = 1;
146+
147+
const MyWidget({int? a = constantOne});
148+
149+
@override
150+
Widget build(BuildContext context) => MyW^idget(a: 1);
151+
}
152+
''');
153+
expect(result, hasArg(isArg('a', defaultValue: 1)));
154+
}
155+
156+
test_defaultValue_named_default_null() async {
157+
var result = await getEditableArgumentsFor(r'''
158+
class MyWidget extends StatelessWidget {
159+
const MyWidget({int? a = null});
160+
161+
@override
162+
Widget build(BuildContext context) => MyW^idget(a: 1);
163+
}
164+
''');
165+
expect(result, hasArg(isArg('a', defaultValue: null)));
166+
}
167+
168+
test_defaultValue_named_noDefault() async {
169+
var result = await getEditableArgumentsFor(r'''
170+
class MyWidget extends StatelessWidget {
171+
const MyWidget({int? a});
172+
173+
@override
174+
Widget build(BuildContext context) => MyW^idget(a: 1);
175+
}
176+
''');
177+
expect(result, hasArg(isArg('a', defaultValue: null)));
178+
}
179+
180+
test_defaultValue_named_required_noDefault() async {
181+
var result = await getEditableArgumentsFor(r'''
182+
class MyWidget extends StatelessWidget {
183+
const MyWidget({required int? a});
184+
185+
@override
186+
Widget build(BuildContext context) => MyW^idget(a: 1);
187+
}
188+
''');
189+
expect(result, hasArg(isArg('a', defaultValue: null)));
190+
}
191+
192+
test_defaultValue_positional() async {
193+
var result = await getEditableArgumentsFor(r'''
194+
class MyWidget extends StatelessWidget {
195+
const MyWidget(int a);
196+
197+
@override
198+
Widget build(BuildContext context) => MyW^idget(1);
199+
}
200+
''');
201+
expect(result, hasArg(isArg('a', defaultValue: null)));
202+
}
203+
204+
test_defaultValue_positional_optional_default() async {
205+
var result = await getEditableArgumentsFor(r'''
206+
class MyWidget extends StatelessWidget {
207+
const MyWidget([int? a = 1]);
208+
209+
@override
210+
Widget build(BuildContext context) => MyW^idget(1);
211+
}
212+
''');
213+
expect(result, hasArg(isArg('a', defaultValue: 1)));
214+
}
215+
216+
test_defaultValue_positional_optional_noDefault() async {
217+
var result = await getEditableArgumentsFor(r'''
218+
class MyWidget extends StatelessWidget {
219+
const MyWidget([int? a]);
220+
221+
@override
222+
Widget build(BuildContext context) => MyW^idget(1);
223+
}
224+
''');
225+
expect(result, hasArg(isArg('a', defaultValue: null)));
226+
}
227+
128228
test_documentation_literal() async {
129229
var result = await getEditableArgumentsFor('''
130230
class MyWidget extends StatelessWidget {
@@ -977,14 +1077,27 @@ class MyWidget extends StatelessWidget {
9771077
result,
9781078
hasArgs(
9791079
orderedEquals([
980-
isArg('supplied', type: 'bool', value: false, isDefault: false),
1080+
isArg(
1081+
'supplied',
1082+
type: 'bool',
1083+
value: false,
1084+
isDefault: false,
1085+
defaultValue: true,
1086+
),
9811087
isArg(
9821088
'suppliedAsDefault',
9831089
type: 'bool',
9841090
value: true,
9851091
isDefault: true,
1092+
defaultValue: true,
1093+
),
1094+
isArg(
1095+
'notSupplied',
1096+
type: 'bool',
1097+
value: true,
1098+
isDefault: true,
1099+
defaultValue: true,
9861100
),
987-
isArg('notSupplied', type: 'bool', value: true, isDefault: true),
9881101
]),
9891102
),
9901103
);
@@ -1054,14 +1167,27 @@ class MyWidget extends StatelessWidget {
10541167
result,
10551168
hasArgs(
10561169
orderedEquals([
1057-
isArg('supplied', type: 'double', value: 2.0, isDefault: false),
1170+
isArg(
1171+
'supplied',
1172+
type: 'double',
1173+
value: 2.0,
1174+
isDefault: false,
1175+
defaultValue: 1.0,
1176+
),
10581177
isArg(
10591178
'suppliedAsDefault',
10601179
type: 'double',
10611180
value: 1.0,
10621181
isDefault: true,
1182+
defaultValue: 1.0,
1183+
),
1184+
isArg(
1185+
'notSupplied',
1186+
type: 'double',
1187+
value: 1.0,
1188+
isDefault: true,
1189+
defaultValue: 1.0,
10631190
),
1064-
isArg('notSupplied', type: 'double', value: 1.0, isDefault: true),
10651191
]),
10661192
),
10671193
);
@@ -1167,20 +1293,23 @@ class MyWidget extends StatelessWidget {
11671293
type: 'enum',
11681294
value: 'E.two',
11691295
isDefault: false,
1296+
defaultValue: 'E.one',
11701297
options: optionsMatcher,
11711298
),
11721299
isArg(
11731300
'suppliedAsDefault',
11741301
type: 'enum',
11751302
value: 'E.one',
11761303
isDefault: true,
1304+
defaultValue: 'E.one',
11771305
options: optionsMatcher,
11781306
),
11791307
isArg(
11801308
'notSupplied',
11811309
type: 'enum',
11821310
value: 'E.one',
11831311
isDefault: true,
1312+
defaultValue: 'E.one',
11841313
options: optionsMatcher,
11851314
),
11861315
]),
@@ -1260,9 +1389,27 @@ class MyWidget extends StatelessWidget {
12601389
result,
12611390
hasArgs(
12621391
orderedEquals([
1263-
isArg('supplied', type: 'int', value: 2, isDefault: false),
1264-
isArg('suppliedAsDefault', type: 'int', value: 1, isDefault: true),
1265-
isArg('notSupplied', type: 'int', value: 1, isDefault: true),
1392+
isArg(
1393+
'supplied',
1394+
type: 'int',
1395+
value: 2,
1396+
isDefault: false,
1397+
defaultValue: 1,
1398+
),
1399+
isArg(
1400+
'suppliedAsDefault',
1401+
type: 'int',
1402+
value: 1,
1403+
isDefault: true,
1404+
defaultValue: 1,
1405+
),
1406+
isArg(
1407+
'notSupplied',
1408+
type: 'int',
1409+
value: 1,
1410+
isDefault: true,
1411+
defaultValue: 1,
1412+
),
12661413
]),
12671414
),
12681415
);
@@ -1332,14 +1479,27 @@ class MyWidget extends StatelessWidget {
13321479
result,
13331480
hasArgs(
13341481
orderedEquals([
1335-
isArg('supplied', type: 'string', value: 'b', isDefault: false),
1482+
isArg(
1483+
'supplied',
1484+
type: 'string',
1485+
value: 'b',
1486+
isDefault: false,
1487+
defaultValue: 'a',
1488+
),
13361489
isArg(
13371490
'suppliedAsDefault',
13381491
type: 'string',
13391492
value: 'a',
13401493
isDefault: true,
1494+
defaultValue: 'a',
1495+
),
1496+
isArg(
1497+
'notSupplied',
1498+
type: 'string',
1499+
value: 'a',
1500+
isDefault: true,
1501+
defaultValue: 'a',
13411502
),
1342-
isArg('notSupplied', type: 'string', value: 'a', isDefault: true),
13431503
]),
13441504
),
13451505
);

0 commit comments

Comments
 (0)