Skip to content

Commit a8a3f3f

Browse files
scheglovCommit Queue
authored andcommitted
[CMSR] Improve 'get invocation' implementation.
Change-Id: I871eddc1727ea6a51e169f4031d55ba3bc93527d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/310860 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent f264102 commit a8a3f3f

File tree

4 files changed

+189
-23
lines changed

4 files changed

+189
-23
lines changed

pkg/analysis_server/lib/src/services/refactoring/agnostic/change_method_signature.dart

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,7 @@ class _SignatureUpdater {
895895
}
896896

897897
ArgumentList argumentList;
898-
final invocation = selection.coveringNode.invocation;
898+
final invocation = selection.invocation;
899899
switch (invocation) {
900900
case ConstructorDeclaration constructor:
901901
return ChangeStatusFailureSuperFormalParameter(
@@ -905,6 +905,8 @@ class _SignatureUpdater {
905905
argumentList = instanceCreation.argumentList;
906906
case MethodInvocation invocation:
907907
argumentList = invocation.argumentList;
908+
case RedirectingConstructorInvocation invocation:
909+
argumentList = invocation.argumentList;
908910
case SuperConstructorInvocation invocation:
909911
argumentList = invocation.argumentList;
910912
default:
@@ -1027,15 +1029,7 @@ class _SignatureUpdater {
10271029
}
10281030
}
10291031

1030-
extension on FormalParameterList {
1031-
bool get hasTrailingComma {
1032-
final last = parameters.lastOrNull;
1033-
final nextToken = last?.endToken.next;
1034-
return nextToken != null && nextToken.type == TokenType.COMMA;
1035-
}
1036-
}
1037-
1038-
extension on AstNode {
1032+
extension _AstNodeExtension on AstNode {
10391033
AstNode? get declaration {
10401034
final self = this;
10411035
if (self is FunctionExpression) {
@@ -1076,27 +1070,49 @@ extension on AstNode {
10761070
}
10771071
return null;
10781072
}
1073+
}
1074+
1075+
extension _FormalParameterListExtension on FormalParameterList {
1076+
bool get hasTrailingComma {
1077+
final last = parameters.lastOrNull;
1078+
final nextToken = last?.endToken.next;
1079+
return nextToken != null && nextToken.type == TokenType.COMMA;
1080+
}
1081+
}
10791082

1083+
extension _SelectionExtension on Selection {
10801084
AstNode? get invocation {
1081-
AstNode? self = this;
1082-
if (self is ArgumentList) {
1083-
self = self.parent;
1084-
} else if (self is NamedType && self.parent is ConstructorName) {
1085-
self = self.parent?.parent;
1085+
final node = coveringNode;
1086+
switch (node) {
1087+
case RedirectingConstructorInvocation():
1088+
case SuperConstructorInvocation():
1089+
return node;
10861090
}
1087-
switch (self) {
1088-
case SimpleIdentifier():
1089-
final parent = self.parent;
1090-
if (parent is ConstructorDeclaration) {
1091+
1092+
final parent = node.parent;
1093+
switch (parent) {
1094+
case MethodInvocation():
1095+
if (isCoveredByNode(parent.methodName)) {
10911096
return parent;
1092-
} else if (parent is MethodInvocation) {
1097+
}
1098+
case RedirectingConstructorInvocation():
1099+
if (isCoveredByToken(parent.thisKeyword)) {
10931100
return parent;
10941101
}
1095-
case InstanceCreationExpression():
1096-
case MethodInvocation():
10971102
case SuperConstructorInvocation():
1098-
return self;
1103+
if (isCoveredByToken(parent.superKeyword)) {
1104+
return parent;
1105+
}
1106+
}
1107+
1108+
final parent2 = parent?.parent;
1109+
switch (parent2) {
1110+
case InstanceCreationExpression():
1111+
if (isCoveredByNode(parent2.constructorName)) {
1112+
return parent2;
1113+
}
10991114
}
1115+
11001116
return null;
11011117
}
11021118
}

pkg/analysis_server/lib/src/utilities/selection.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:analyzer/dart/ast/ast.dart';
6+
import 'package:analyzer/dart/ast/token.dart';
67
import 'package:analyzer/dart/ast/visitor.dart';
78
import 'package:analyzer/source/source_range.dart';
89
import 'package:analyzer/src/utilities/extensions/ast.dart';
@@ -25,6 +26,14 @@ class Selection {
2526
Selection(
2627
{required this.offset, required this.length, required this.coveringNode});
2728

29+
bool isCoveredByNode(AstNode node) {
30+
return node.offset <= offset && offset + length <= node.end;
31+
}
32+
33+
bool isCoveredByToken(Token token) {
34+
return token.offset <= offset && offset + length <= token.end;
35+
}
36+
2837
/// Returns the contiguous subset of [coveringNode] children that are at
2938
/// least partially covered by the selection. Touching is not enough.
3039
///

pkg/analysis_server/test/services/refactoring/agnostic/change_method_signature_test.dart

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,68 @@ void f() {
944944
''');
945945
}
946946

947+
Future<void>
948+
test_classConstructor_redirectingConstructorInvocation_named() async {
949+
await _analyzeValidSelection(r'''
950+
class A {
951+
final int a;
952+
^A.named(int a);
953+
A() : this.named(0);
954+
}
955+
''');
956+
957+
final signatureUpdate = MethodSignatureUpdate(
958+
formalParameters: [
959+
FormalParameterUpdate(
960+
id: 0,
961+
kind: FormalParameterKind.requiredNamed,
962+
),
963+
],
964+
formalParametersTrailingComma: TrailingComma.ifPresent,
965+
argumentsTrailingComma: ArgumentsTrailingComma.ifPresent,
966+
);
967+
968+
await _assertUpdate(signatureUpdate, r'''
969+
>>>>>>> /home/test/lib/test.dart
970+
class A {
971+
final int a;
972+
A.named({required int a});
973+
A() : this.named(a: 0);
974+
}
975+
''');
976+
}
977+
978+
Future<void>
979+
test_classConstructor_redirectingConstructorInvocation_unnamed() async {
980+
await _analyzeValidSelection(r'''
981+
class A {
982+
final int a;
983+
^A(int a);
984+
A.named() : this(0);
985+
}
986+
''');
987+
988+
final signatureUpdate = MethodSignatureUpdate(
989+
formalParameters: [
990+
FormalParameterUpdate(
991+
id: 0,
992+
kind: FormalParameterKind.requiredNamed,
993+
),
994+
],
995+
formalParametersTrailingComma: TrailingComma.ifPresent,
996+
argumentsTrailingComma: ArgumentsTrailingComma.ifPresent,
997+
);
998+
999+
await _assertUpdate(signatureUpdate, r'''
1000+
>>>>>>> /home/test/lib/test.dart
1001+
class A {
1002+
final int a;
1003+
A({required int a});
1004+
A.named() : this(a: 0);
1005+
}
1006+
''');
1007+
}
1008+
9471009
Future<void> test_classConstructor_requiredNamed_reorder() async {
9481010
await _analyzeValidSelection(r'''
9491011
class A {
@@ -1158,6 +1220,79 @@ void f() {
11581220
''');
11591221
}
11601222

1223+
Future<void> test_classConstructor_superConstructorInvocation_named() async {
1224+
await _analyzeValidSelection(r'''
1225+
class A {
1226+
final int a;
1227+
^A.named(int a);
1228+
}
1229+
1230+
class B extends A {
1231+
B() : super.named(0);
1232+
}
1233+
''');
1234+
1235+
final signatureUpdate = MethodSignatureUpdate(
1236+
formalParameters: [
1237+
FormalParameterUpdate(
1238+
id: 0,
1239+
kind: FormalParameterKind.requiredNamed,
1240+
),
1241+
],
1242+
formalParametersTrailingComma: TrailingComma.ifPresent,
1243+
argumentsTrailingComma: ArgumentsTrailingComma.ifPresent,
1244+
);
1245+
1246+
await _assertUpdate(signatureUpdate, r'''
1247+
>>>>>>> /home/test/lib/test.dart
1248+
class A {
1249+
final int a;
1250+
A.named({required int a});
1251+
}
1252+
1253+
class B extends A {
1254+
B() : super.named(a: 0);
1255+
}
1256+
''');
1257+
}
1258+
1259+
Future<void>
1260+
test_classConstructor_superConstructorInvocation_unnamed() async {
1261+
await _analyzeValidSelection(r'''
1262+
class A {
1263+
final int a;
1264+
^A(int a);
1265+
}
1266+
1267+
class B extends A {
1268+
B() : super(0);
1269+
}
1270+
''');
1271+
1272+
final signatureUpdate = MethodSignatureUpdate(
1273+
formalParameters: [
1274+
FormalParameterUpdate(
1275+
id: 0,
1276+
kind: FormalParameterKind.requiredNamed,
1277+
),
1278+
],
1279+
formalParametersTrailingComma: TrailingComma.ifPresent,
1280+
argumentsTrailingComma: ArgumentsTrailingComma.ifPresent,
1281+
);
1282+
1283+
await _assertUpdate(signatureUpdate, r'''
1284+
>>>>>>> /home/test/lib/test.dart
1285+
class A {
1286+
final int a;
1287+
A({required int a});
1288+
}
1289+
1290+
class B extends A {
1291+
B() : super(a: 0);
1292+
}
1293+
''');
1294+
}
1295+
11611296
Future<void> test_classMethod_optionalNamed_reorder_less() async {
11621297
await _analyzeValidSelection(r'''
11631298
class A {

pkg/analyzer_plugin/lib/utilities/range_factory.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@ class RangeFactory {
198198
return SourceRange(startOffset, length);
199199
}
200200

201+
/// Return a source range that starts at the given [startOffset], and has
202+
/// the given [length].
203+
SourceRange startOffsetLength(int startOffset, int length) {
204+
return SourceRange(startOffset, length);
205+
}
206+
201207
/// Return a source range that starts at the start of [leftEntity] and ends at
202208
/// the start of [rightEntity].
203209
SourceRange startStart(

0 commit comments

Comments
 (0)