Skip to content

Commit 1165528

Browse files
DanTupCommit Queue
authored andcommitted
[analysis_server] Improve the formatting of inserted arguments
This improves the formatting of inserted arguments by including newlines and indentation if an invocation spans multiple lines. Change-Id: Idef4602ee9ac9f145879a4628190ec44f87a0018 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/405122 Commit-Queue: Brian Wilkerson <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]> Reviewed-by: Elliott Brooks <[email protected]>
1 parent 199d50a commit 1165528

File tree

2 files changed

+104
-12
lines changed

2 files changed

+104
-12
lines changed

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

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ import 'package:analysis_server/src/lsp/handlers/custom/editable_arguments/edita
1212
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
1313
import 'package:analysis_server/src/lsp/mapping.dart';
1414
import 'package:analysis_server/src/lsp/source_edits.dart';
15+
import 'package:analysis_server_plugin/edit/correction_utils.dart';
1516
import 'package:analyzer/dart/analysis/results.dart';
1617
import 'package:analyzer/dart/ast/ast.dart';
18+
import 'package:analyzer/dart/ast/token.dart';
1719
import 'package:analyzer/dart/element/element2.dart';
1820
import 'package:analyzer/dart/element/nullability_suffix.dart';
1921
import 'package:analyzer/dart/element/type.dart';
22+
import 'package:analyzer/source/line_info.dart';
2023
import 'package:analyzer/source/source_range.dart';
2124
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
2225
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
@@ -234,10 +237,13 @@ class EditArgumentHandler extends SharedMessageHandler<EditArgumentParams, Null>
234237
);
235238

236239
var changeBuilder = ChangeBuilder(session: result.session);
240+
var utils = CorrectionUtils(result);
237241
await changeBuilder.addDartFileEdit(result.path, (builder) {
238242
if (argument == null) {
239243
_writeNewArgument(
240244
builder,
245+
utils,
246+
result.lineInfo,
241247
parameters,
242248
argumentList,
243249
parameter,
@@ -352,6 +358,8 @@ class EditArgumentHandler extends SharedMessageHandler<EditArgumentParams, Null>
352358
/// earlier missing positionals.
353359
void _writeNewArgument(
354360
DartFileEditBuilder builder,
361+
CorrectionUtils utils,
362+
LineInfo lineInfo,
355363
List<FormalParameterElement> parameters,
356364
ArgumentList argumentList,
357365
FormalParameterElement parameter,
@@ -377,28 +385,64 @@ class EditArgumentHandler extends SharedMessageHandler<EditArgumentParams, Null>
377385
}
378386

379387
var parameterName = parameter.name3;
380-
var prefix =
388+
var argumentNamePrefix =
381389
parameter.isNamed && parameterName != null ? '$parameterName: ' : '';
382-
var argumentCodeToInsert = '$prefix$newValueCode';
390+
var argumentCode = '$argumentNamePrefix$newValueCode';
383391

384392
// Usually we insert at the end (after the last argument), but if the last
385393
// argument is child/children we should go before it.
386394
var argumentToInsertAfter = argumentList.arguments.lastWhereOrNull(
387395
_isNotNamedChildOrChildren,
388396
);
389397

398+
var hasArgumentsBefore = argumentToInsertAfter != null;
399+
var hasArgumentsAfter =
400+
(argumentToInsertAfter == null && argumentList.arguments.isNotEmpty) ||
401+
(argumentToInsertAfter != null &&
402+
argumentToInsertAfter != argumentList.arguments.last);
403+
var commaFollowsInsertion =
404+
argumentToInsertAfter?.endToken.next?.type == TokenType.COMMA;
405+
406+
// If the invocation is already across more than one line, we will format
407+
// accordingly. If it is already on one line, keep it that way.
408+
var isMultiline =
409+
lineInfo.getLocation(argumentList.leftParenthesis.offset).lineNumber !=
410+
lineInfo.getLocation(argumentList.rightParenthesis.offset).lineNumber;
411+
412+
// If we are multiline, indent one level more than the invocation.
413+
var indent =
414+
isMultiline
415+
? '${utils.getLinePrefix(argumentList.leftParenthesis.offset)} '
416+
: '';
417+
418+
// The prefix we need depends on whether there is an argument before us
419+
// and whether we are multiline.
420+
var codePrefix = switch ((isMultiline, hasArgumentsBefore)) {
421+
(true, true) => ',${utils.endOfLine}$indent',
422+
(true, false) => '${utils.endOfLine}$indent',
423+
(false, true) => ', ',
424+
(false, false) => '',
425+
};
426+
427+
// The suffix depends on whether there is an argument after us and whether
428+
// we are multiline. If there is an argument after us, there is already
429+
// the correct whitespace and comma after our insertion point.
430+
var codeSuffix = switch ((
431+
isMultiline,
432+
hasArgumentsAfter,
433+
commaFollowsInsertion,
434+
)) {
435+
(_, true, _) => '',
436+
(true, false, false) => ',',
437+
(true, false, true) => '',
438+
(false, false, _) => '',
439+
};
440+
390441
// Build the final code to insert.
391442
var newCode = StringBuffer();
392-
if (argumentToInsertAfter != null) {
393-
// If we're being inserted after an argument, put a new comma between us.
394-
newCode.write(', ');
395-
}
396-
newCode.write(argumentCodeToInsert);
397-
if (argumentToInsertAfter == null && argumentList.arguments.isNotEmpty) {
398-
// If we're not inserted after an existing argument but there are future
399-
// arguments, add a comma in between us.
400-
newCode.write(', ');
401-
}
443+
newCode.write(codePrefix);
444+
newCode.write(argumentCode);
445+
newCode.write(codeSuffix);
402446

403447
builder.addSimpleInsertion(
404448
argumentToInsertAfter?.end ?? argumentList.leftParenthesis.end,

pkg/analysis_server/test/shared/shared_edit_argument_tests.dart

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,54 @@ mixin SharedEditArgumentTests
6666
);
6767
}
6868

69+
test_format_multiline_insert_between() async {
70+
await _expectSimpleArgumentEdit(
71+
params: '({ int? x, int? y, int? children })',
72+
originalArgs: '''\n
73+
(
74+
x: 1,
75+
children: 3,
76+
)''',
77+
edit: ArgumentEdit(name: 'y', newValue: 2),
78+
expectedArgs: '''\n
79+
(
80+
x: 1,
81+
y: 2,
82+
children: 3,
83+
)''',
84+
);
85+
}
86+
87+
test_format_multiline_insert_last() async {
88+
await _expectSimpleArgumentEdit(
89+
params: '({ int? x, int? y })',
90+
originalArgs: '''\n
91+
(
92+
x: 1,
93+
)''',
94+
edit: ArgumentEdit(name: 'y', newValue: 2),
95+
expectedArgs: '''\n
96+
(
97+
x: 1,
98+
y: 2,
99+
)''',
100+
);
101+
}
102+
103+
test_format_multiline_insert_solo() async {
104+
await _expectSimpleArgumentEdit(
105+
params: '({ int? x })',
106+
originalArgs: '''\n
107+
(
108+
)''',
109+
edit: ArgumentEdit(name: 'x', newValue: 1),
110+
expectedArgs: '''\n
111+
(
112+
x: 1,
113+
)''',
114+
);
115+
}
116+
69117
test_named_addAfterNamed() async {
70118
await _expectSimpleArgumentEdit(
71119
params: '({ int? x, int? y })',

0 commit comments

Comments
 (0)