Skip to content

Commit 651464c

Browse files
jwrencommit-bot@chromium.org
authored andcommitted
Implement the rest of the ArgumentList ASTNode logic in the context type visitor in feature_computer.dart, tests added in feature_computer_test.dart
Change-Id: I35afea21912a785af427afb317cbff532c29d717 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151364 Commit-Queue: Jaime Wren <jwren@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
1 parent c7d9fa9 commit 651464c

File tree

2 files changed

+184
-33
lines changed

2 files changed

+184
-33
lines changed

pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -301,19 +301,47 @@ class _ContextTypeVisitor extends SimpleAstVisitor<DartType> {
301301
if (range
302302
.endStart(node.leftParenthesis, node.rightParenthesis)
303303
.contains(offset)) {
304-
var parameterElts = node.functionType?.parameters;
305-
if (parameterElts != null && parameterElts.isNotEmpty) {
306-
for (var i = 0; i < node.arguments.length; i++) {
307-
// TODO(jwren) Consider using range between commas to determine the
308-
// contains conditional:
304+
final paramElts = node.functionType?.parameters;
305+
if (paramElts == null || paramElts.isEmpty) {
306+
return null;
307+
}
308+
309+
// Required parameters
310+
final positionalParamElts =
311+
paramElts.where((param) => !param.isNamed)?.toList(growable: false);
312+
var i = 0;
313+
if (positionalParamElts.isNotEmpty) {
314+
for (;
315+
i < node.arguments.length && i < positionalParamElts.length;
316+
i++) {
317+
// We don't need to compare offsets between commas, tests show that
318+
// such tests aren't needed, also the commas and their respective
319+
// offsets aren't accessible with existing getters and setters.
320+
if (node.arguments[i].contains(offset)) {
321+
return positionalParamElts[i].type;
322+
}
323+
}
324+
// The case where the user is filling out the required parameters
325+
if (i < positionalParamElts.length) {
326+
return positionalParamElts[i].type;
327+
}
328+
}
329+
// Named and positional parameters
330+
if (positionalParamElts.length < paramElts.length) {
331+
for (; i < node.arguments.length && i < paramElts.length; i++) {
309332
if (node.arguments[i].contains(offset)) {
310-
// TODO(jwren) Re-implement this as this method should handle named
311-
// parameters:
312-
return parameterElts[i].type;
333+
if (node.arguments[i] is NamedExpression) {
334+
var namedExpression = node.arguments[i] as NamedExpression;
335+
var needle = paramElts
336+
.where((paramElt) =>
337+
paramElt.isNamed &&
338+
paramElt.name == namedExpression.name.label.name)
339+
?.first;
340+
return needle?.type;
341+
}
313342
}
314343
}
315344
}
316-
// In the case where the user is filling out the required parameters
317345
}
318346
return null;
319347
}
@@ -542,6 +570,14 @@ class _ContextTypeVisitor extends SimpleAstVisitor<DartType> {
542570
return null;
543571
}
544572

573+
@override
574+
DartType visitLabel(Label node) {
575+
if (node.colon.end <= offset) {
576+
return _visitParent(node);
577+
}
578+
return null;
579+
}
580+
545581
@override
546582
DartType visitListLiteral(ListLiteral node) {
547583
if (range.endStart(node.leftBracket, node.rightBracket).contains(offset)) {
@@ -574,10 +610,10 @@ class _ContextTypeVisitor extends SimpleAstVisitor<DartType> {
574610

575611
@override
576612
DartType visitNamedExpression(NamedExpression node) {
577-
if (node.name.end < offset) {
613+
if (node.name.end <= offset) {
578614
return _visitParent(node);
579615
}
580-
return super.visitNamedExpression(node);
616+
return null;
581617
}
582618

583619
@override

pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart

Lines changed: 137 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,39 @@ class FeatureComputerTest extends AbstractSingleUnitTest {
4242
}
4343
}
4444

45-
Future<void> test_argumentList_first() async {
45+
Future<void> test_argumentList_named() async {
4646
await assertContextType('''
47-
void f(int i, String str, bool b) {}
47+
void f({int i, String s, bool b}) {}
4848
void g(int j) {
49-
f(^j);
49+
f(i:^);
5050
}
5151
''', 'int');
5252
}
5353

54-
@failingTest
55-
Future<void> test_argumentList_implicitFirst() async {
54+
Future<void> test_argumentList_named2() async {
5655
await assertContextType('''
57-
void f(int i, String str, bool b) {}
56+
void f({int i, String s, bool b}) {}
5857
void g(int j) {
59-
f(^);
58+
f(s:^);
59+
}
60+
''', 'String');
61+
}
62+
63+
Future<void> test_argumentList_named_with_requiredPositional() async {
64+
await assertContextType('''
65+
void f(String s, {int i}) {}
66+
void g(int j) {
67+
f('str', i: ^);
68+
}
69+
''', 'int');
70+
}
71+
72+
Future<void>
73+
test_argumentList_named_with_requiredPositional_defaultValue() async {
74+
await assertContextType('''
75+
void f(String s, {int i = 0}) {}
76+
void g(int j) {
77+
f('str', i: ^);
6078
}
6179
''', 'int');
6280
}
@@ -70,46 +88,116 @@ void g() {
7088
''', null);
7189
}
7290

73-
Future<void> test_argumentList_noParameters_whitespage() async {
91+
Future<void> test_argumentList_noParameters_whitespace() async {
7492
await assertContextType('''
7593
void f() {}
7694
void g() {
77-
f( ^ );
95+
f( ^ );
7896
}
7997
''', null);
8098
}
8199

82-
@failingTest
83-
Future<void> test_argumentList_secondArg() async {
100+
Future<void> test_argumentList_noParameters_whitespace_left() async {
84101
await assertContextType('''
85-
void f(int i, String str, bool b) {}
102+
void f() {}
103+
void g() {
104+
f( ^);
105+
}
106+
''', null);
107+
}
108+
109+
Future<void> test_argumentList_noParameters_whitespace_right() async {
110+
await assertContextType('''
111+
void f() {}
112+
void g() {
113+
f(^ );
114+
}
115+
''', null);
116+
}
117+
118+
Future<void> test_argumentList_positional() async {
119+
await assertContextType('''
120+
void f([int i]) {}
86121
void g(int j) {
87-
f(1, ^);
122+
f(i:^);
88123
}
89-
''', 'String');
124+
''', 'int');
125+
}
126+
127+
Future<void> test_argumentList_positional_completionInLabel() async {
128+
await assertContextType('''
129+
void f([int i = 2]) {}
130+
void g(int j) {
131+
f(^i:);
132+
}
133+
''', null);
134+
}
135+
136+
Future<void> test_argumentList_positional_completionInLabel2() async {
137+
await assertContextType('''
138+
void f(String s, bool b, [int i = 2]) {}
139+
void g(int j) {
140+
f(i^:);
141+
}
142+
''', null);
143+
}
144+
145+
Future<void> test_argumentList_positional_whitespace() async {
146+
await assertContextType('''
147+
void f([int i]) {}
148+
void g(int j) {
149+
f(i: ^ );
150+
}
151+
''', 'int');
90152
}
91153

92-
Future<void> test_argumentList_secondArg2() async {
154+
Future<void> test_argumentList_positional_with_requiredPositional() async {
155+
await assertContextType('''
156+
void f(String s, bool b, [int i]) {}
157+
void g(int j) {
158+
f('', 3, i:^);
159+
}
160+
''', 'int');
161+
}
162+
163+
Future<void>
164+
test_argumentList_positional_with_requiredPositional_defaultValue() async {
165+
await assertContextType('''
166+
void f(String s, bool b, [int i = 2]) {}
167+
void g(int j) {
168+
f('', 3, i:^);
169+
}
170+
''', 'int');
171+
}
172+
173+
Future<void> test_argumentList_requiredPositional_first() async {
93174
await assertContextType('''
94175
void f(int i, String str, bool b) {}
95176
void g(int j) {
96-
f(1, w^);
177+
f(^j);
97178
}
98-
''', 'String');
179+
''', 'int');
99180
}
100181

101-
@failingTest
102-
Future<void> test_argumentList_thirdArg() async {
182+
Future<void> test_argumentList_requiredPositional_first_implicit() async {
183+
await assertContextType('''
184+
void f(int i, String str, bool b) {}
185+
void g() {
186+
f(^);
187+
}
188+
''', 'int');
189+
}
190+
191+
Future<void> test_argumentList_requiredPositional_last() async {
103192
await assertContextType('''
104193
void f(int i, String str, bool b) {}
105194
void g(int j) {
106-
f(1, '2', ^);
195+
f(1, '2', t^);
107196
}
108197
''', 'bool');
109198
}
110199

111-
@failingTest
112-
Future<void> test_argumentList_thirdArg2() async {
200+
Future<void> test_argumentList_requiredPositional_last_implicit() async {
113201
await assertContextType('''
114202
void f(int i, String str, bool b, num n) {}
115203
void g(int j) {
@@ -118,6 +206,33 @@ void g(int j) {
118206
''', 'bool');
119207
}
120208

209+
Future<void> test_argumentList_requiredPositional_middle() async {
210+
await assertContextType('''
211+
void f(int i, String str, bool b) {}
212+
void g(int j) {
213+
f(1, w^);
214+
}
215+
''', 'String');
216+
}
217+
218+
Future<void> test_argumentList_requiredPositional_middle2() async {
219+
await assertContextType('''
220+
void f(int i, String str, bool b) {}
221+
void g(int j) {
222+
f(1, ^, );
223+
}
224+
''', 'String');
225+
}
226+
227+
Future<void> test_argumentList_requiredPositional_middle_implicit() async {
228+
await assertContextType('''
229+
void f(int i, String str, bool b) {}
230+
void g(int j) {
231+
f(1, ^ );
232+
}
233+
''', 'String');
234+
}
235+
121236
Future<void> test_assertInitializer_with_identifier() async {
122237
await assertContextType('''
123238
class C {

0 commit comments

Comments
 (0)