Skip to content

Commit a4baaa3

Browse files
committed
Fix a bug in the way RangeFactory deals with trailing commas in a list
Change-Id: Ic9ba9acbbb583068662972fd5cc42d28aa1dfa6d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/155824 Reviewed-by: Konstantin Shcheglov <[email protected]>
1 parent b61e229 commit a4baaa3

File tree

2 files changed

+130
-4
lines changed

2 files changed

+130
-4
lines changed

pkg/analyzer_plugin/lib/utilities/range_factory.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,18 @@ class RangeFactory {
5757
/// trailing comma as appropriate) in the containing [list].
5858
SourceRange nodeInList<T extends AstNode>(NodeList<T> list, T item) {
5959
if (list.length == 1) {
60+
var nextToken = item.endToken.next;
61+
if (nextToken.type == TokenType.COMMA) {
62+
return startEnd(item, nextToken);
63+
}
6064
return node(item);
6165
}
6266
final index = list.indexOf(item);
63-
// Remove trailing comma.
6467
if (index == 0) {
68+
// Remove the trailing comma.
6569
return startStart(item, list[1]);
6670
} else {
67-
// Remove leading comma.
71+
// Remove the leading comma.
6872
return endEnd(list[index - 1], item);
6973
}
7074
}

pkg/analyzer_plugin/test/utilities/range_factory_test.dart

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'package:analyzer/dart/ast/ast.dart';
66
import 'package:analyzer/error/error.dart';
7+
import 'package:analyzer/source/source_range.dart';
78
import 'package:analyzer/src/generated/parser.dart';
89
import 'package:analyzer/src/generated/source.dart';
910
import 'package:analyzer_plugin/utilities/range_factory.dart';
@@ -14,12 +15,22 @@ import '../support/abstract_single_unit.dart';
1415

1516
void main() {
1617
defineReflectiveSuite(() {
17-
defineReflectiveTests(SourceRangesTest);
18+
defineReflectiveTests(RangeFactoryTest);
1819
});
1920
}
2021

2122
@reflectiveTest
22-
class SourceRangesTest extends AbstractSingleUnitTest {
23+
class RangeFactoryTest extends AbstractSingleUnitTest {
24+
/// Assuming that the test code starts with a function whose block body starts
25+
/// with a method invocation, return the list of arguments in that invocation.
26+
NodeList<Expression> get _argumentList {
27+
var f = testUnit.declarations[0] as FunctionDeclaration;
28+
var body = f.functionExpression.body as BlockFunctionBody;
29+
var statement = body.block.statements[0] as ExpressionStatement;
30+
var invocation = statement.expression as MethodInvocation;
31+
return invocation.argumentList.arguments;
32+
}
33+
2334
Future<void> test_elementName() async {
2435
await resolveTestUnit('class ABC {}');
2536
var element = findElement('ABC');
@@ -61,6 +72,117 @@ class SourceRangesTest extends AbstractSingleUnitTest {
6172
expect(range.node(mainName), SourceRange(0, 4));
6273
}
6374

75+
Future<void> test_nodeInList_argumentList_first_named() async {
76+
await resolveTestUnit('''
77+
void f() {
78+
g(a: 1, b: 2);
79+
}
80+
void g({int a, int b}) {}
81+
''');
82+
var list = _argumentList;
83+
expect(range.nodeInList(list, list[0]), SourceRange(15, 6));
84+
}
85+
86+
Future<void> test_nodeInList_argumentList_first_positional() async {
87+
await resolveTestUnit('''
88+
void f() {
89+
g(1, 2);
90+
}
91+
void g(int a, int b) {}
92+
''');
93+
var list = _argumentList;
94+
expect(range.nodeInList(list, list[0]), SourceRange(15, 3));
95+
}
96+
97+
Future<void> test_nodeInList_argumentList_last_named() async {
98+
await resolveTestUnit('''
99+
void f() {
100+
g(a: 1, b: 2);
101+
}
102+
void g({int a, int b}) {}
103+
''');
104+
var list = _argumentList;
105+
expect(range.nodeInList(list, list[1]), SourceRange(19, 6));
106+
}
107+
108+
Future<void> test_nodeInList_argumentList_last_positional() async {
109+
await resolveTestUnit('''
110+
void f() {
111+
g(1, 2);
112+
}
113+
void g(int a, int b) {}
114+
''');
115+
var list = _argumentList;
116+
expect(range.nodeInList(list, list[1]), SourceRange(16, 3));
117+
}
118+
119+
Future<void> test_nodeInList_argumentList_middle_named() async {
120+
await resolveTestUnit('''
121+
void f() {
122+
g(a: 1, b: 2, c: 3);
123+
}
124+
void g({int a, int b, int c}) {}
125+
''');
126+
var list = _argumentList;
127+
expect(range.nodeInList(list, list[1]), SourceRange(19, 6));
128+
}
129+
130+
Future<void> test_nodeInList_argumentList_middle_positional() async {
131+
await resolveTestUnit('''
132+
void f() {
133+
g(1, 2, 3);
134+
}
135+
void g(int a, int b, int c) {}
136+
''');
137+
var list = _argumentList;
138+
expect(range.nodeInList(list, list[1]), SourceRange(16, 3));
139+
}
140+
141+
Future<void> test_nodeInList_argumentList_only_named() async {
142+
await resolveTestUnit('''
143+
void f() {
144+
g(a: 1);
145+
}
146+
void g({int a}) {}
147+
''');
148+
var list = _argumentList;
149+
expect(range.nodeInList(list, list[0]), SourceRange(15, 4));
150+
}
151+
152+
Future<void> test_nodeInList_argumentList_only_named_trailingComma() async {
153+
await resolveTestUnit('''
154+
void f() {
155+
g(a: 1,);
156+
}
157+
void g({int a}) {}
158+
''');
159+
var list = _argumentList;
160+
expect(range.nodeInList(list, list[0]), SourceRange(15, 5));
161+
}
162+
163+
Future<void> test_nodeInList_argumentList_only_positional() async {
164+
await resolveTestUnit('''
165+
void f() {
166+
g(1);
167+
}
168+
void g(int a) {}
169+
''');
170+
var list = _argumentList;
171+
expect(range.nodeInList(list, list[0]), SourceRange(15, 1));
172+
}
173+
174+
Future<void>
175+
test_nodeInList_argumentList_only_positional_trailingComma() async {
176+
await resolveTestUnit('''
177+
void f() {
178+
g(1,);
179+
}
180+
void g(int a) {}
181+
''');
182+
var list = _argumentList;
183+
expect(range.nodeInList(list, list[0]), SourceRange(15, 2));
184+
}
185+
64186
Future<void> test_nodes() async {
65187
await resolveTestUnit(' main() {}');
66188
var mainFunction = testUnit.declarations[0] as FunctionDeclaration;

0 commit comments

Comments
 (0)