Skip to content

Commit 562e907

Browse files
kallentuCommit Queue
authored andcommitted
[analysis_server] Dot shorthands: Completion for ==
Add code completion for dot shorthands and the `==` and `!=` operators. We use the LHS static type as the context type for the RHS dot shorthand. Bug: #61872, #59836 Change-Id: Icf44f1e0fdd030984228aa72e5087318278d73f4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/458963 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Kallen Tu <[email protected]>
1 parent 270bc00 commit 562e907

File tree

4 files changed

+213
-0
lines changed

4 files changed

+213
-0
lines changed

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,21 @@ class _ContextTypeVisitor extends SimpleAstVisitor<DartType> {
626626
@override
627627
DartType? visitBinaryExpression(BinaryExpression node) {
628628
if (node.operator.end <= offset) {
629+
if (node.operator.type == TokenType.EQ_EQ ||
630+
node.operator.type == TokenType.BANG_EQ_EQ) {
631+
// TODO(kallentu): Fix the parser implementation where dot shorthand
632+
// const constructor declarations recover with a wrapping function
633+
// expression invocation and then remove this.
634+
var rightOperand = node.rightOperand;
635+
if (rightOperand is FunctionExpressionInvocation &&
636+
rightOperand.function is DotShorthandMixin) {
637+
rightOperand = rightOperand.function;
638+
}
639+
if (rightOperand is DotShorthandMixin && rightOperand.isDotShorthand) {
640+
return node.leftOperand.staticType;
641+
}
642+
}
643+
629644
return node.rightOperand.correspondingParameter?.type;
630645
}
631646
return _visitParent(node);

pkg/analysis_server/test/services/completion/dart/location/dot_shorthand_constructor_invocation_test.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,44 @@ suggestions
3636
''');
3737
}
3838

39+
Future<void> test_constructor_const_equality() async {
40+
allowedIdentifiers = {'named', 'notConstant'};
41+
await computeSuggestions('''
42+
class C {
43+
const C.named();
44+
C.notConstant();
45+
}
46+
void f() {
47+
print(C() == const .^);
48+
}
49+
''');
50+
assertResponse(r'''
51+
suggestions
52+
named
53+
kind: constructorInvocation
54+
''');
55+
}
56+
57+
Future<void> test_constructor_const_equality_withPrefix() async {
58+
allowedIdentifiers = {'named', 'notConstant'};
59+
await computeSuggestions('''
60+
class C {
61+
const C.named();
62+
C.notConstant();
63+
}
64+
void f() {
65+
print(C.named() == const .n^);
66+
}
67+
''');
68+
assertResponse(r'''
69+
replacement
70+
left: 1
71+
suggestions
72+
named
73+
kind: constructorInvocation
74+
''');
75+
}
76+
3977
Future<void> test_constructor_const_withPrefix() async {
4078
allowedIdentifiers = {'named', 'notConstant'};
4179
await computeSuggestions('''

pkg/analysis_server/test/services/completion/dart/location/dot_shorthand_invocation_test.dart

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,25 @@ suggestions
3434
''');
3535
}
3636

37+
Future<void> test_constructor_class_named_equality_withPrefix() async {
38+
allowedIdentifiers = {'named'};
39+
await computeSuggestions('''
40+
class C {
41+
C.named();
42+
}
43+
void f() {
44+
print(C.named() == .n^);
45+
}
46+
''');
47+
assertResponse(r'''
48+
replacement
49+
left: 1
50+
suggestions
51+
named
52+
kind: constructorInvocation
53+
''');
54+
}
55+
3756
Future<void> test_constructor_class_unnamed() async {
3857
allowedIdentifiers = {'new'};
3958
await computeSuggestions('''
@@ -49,6 +68,21 @@ suggestions
4968
''');
5069
}
5170

71+
Future<void> test_constructor_class_unnamed_equality() async {
72+
allowedIdentifiers = {'new'};
73+
await computeSuggestions('''
74+
class C {}
75+
void f() {
76+
print(C() == .^);
77+
}
78+
''');
79+
assertResponse(r'''
80+
suggestions
81+
new
82+
kind: constructorInvocation
83+
''');
84+
}
85+
5286
Future<void> test_constructor_class_withParentheses() async {
5387
allowedIdentifiers = {'named'};
5488
await computeSuggestions('''
@@ -181,6 +215,21 @@ suggestions
181215
''');
182216
}
183217

218+
Future<void> test_constructor_extensionType_unnamed_equality() async {
219+
allowedIdentifiers = {'new'};
220+
await computeSuggestions('''
221+
extension type C(int x) {}
222+
void f() {
223+
print(C() == .^);
224+
}
225+
''');
226+
assertResponse(r'''
227+
suggestions
228+
new
229+
kind: constructorInvocation
230+
''');
231+
}
232+
184233
Future<void> test_constructor_extensionType_withPrefix_named() async {
185234
allowedIdentifiers = {'named'};
186235
await computeSuggestions('''
@@ -281,6 +330,24 @@ suggestions
281330
''');
282331
}
283332

333+
Future<void> test_method_class_equality() async {
334+
allowedIdentifiers = {'method', 'notStatic'};
335+
await computeSuggestions('''
336+
class C {
337+
static C method() => C();
338+
C notStatic() => C();
339+
}
340+
void f() {
341+
print(C() == .^);
342+
}
343+
''');
344+
assertResponse(r'''
345+
suggestions
346+
method
347+
kind: methodInvocation
348+
''');
349+
}
350+
284351
Future<void> test_method_class_withParentheses() async {
285352
allowedIdentifiers = {'method', 'notStatic'};
286353
await computeSuggestions('''
@@ -338,6 +405,24 @@ suggestions
338405
''');
339406
}
340407

408+
Future<void> test_method_extensionType_equality() async {
409+
allowedIdentifiers = {'method', 'notStatic'};
410+
await computeSuggestions('''
411+
extension type C(int x) {
412+
static C method() => C(1);
413+
C notStatic() => C(1);
414+
}
415+
void f() {
416+
print(C(1) == .^);
417+
}
418+
''');
419+
assertResponse(r'''
420+
suggestions
421+
method
422+
kind: methodInvocation
423+
''');
424+
}
425+
341426
Future<void> test_method_extensionType_withPrefix() async {
342427
allowedIdentifiers = {'method', 'anotherMethod', 'notStatic'};
343428
await computeSuggestions('''

pkg/analysis_server/test/services/completion/dart/location/dot_shorthand_property_access_test.dart

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,44 @@ suggestions
125125
''');
126126
}
127127

128+
Future<void> test_class_equality() async {
129+
allowedIdentifiers = {'getter', 'notStatic'};
130+
await computeSuggestions('''
131+
class C {
132+
static C get getter => C();
133+
C get notStatic => C();
134+
}
135+
void f() {
136+
print(C() == .^);
137+
}
138+
''');
139+
assertResponse(r'''
140+
suggestions
141+
getter
142+
kind: getter
143+
''');
144+
}
145+
146+
Future<void> test_class_equality_withPrefix() async {
147+
allowedIdentifiers = {'getter', 'gNotStatic'};
148+
await computeSuggestions('''
149+
class C {
150+
static C get getter => C();
151+
C get gNotStatic => C();
152+
}
153+
void f() {
154+
print(C() == .g^);
155+
}
156+
''');
157+
assertResponse(r'''
158+
replacement
159+
left: 1
160+
suggestions
161+
getter
162+
kind: getter
163+
''');
164+
}
165+
128166
Future<void> test_class_functionExpression_futureOr() async {
129167
allowedIdentifiers = {'getter'};
130168
await computeSuggestions('''
@@ -201,6 +239,25 @@ suggestions
201239
''');
202240
}
203241

242+
Future<void> test_enum_equality() async {
243+
allowedIdentifiers = {'red', 'blue', 'yellow'};
244+
await computeSuggestions('''
245+
enum E { red, blue, yellow }
246+
void f() {
247+
print(E.red == .^);
248+
}
249+
''');
250+
assertResponse(r'''
251+
suggestions
252+
blue
253+
kind: enumConstant
254+
red
255+
kind: enumConstant
256+
yellow
257+
kind: enumConstant
258+
''');
259+
}
260+
204261
Future<void> test_enum_functionExpression_futureOr() async {
205262
allowedIdentifiers = {'red', 'blue', 'yellow'};
206263
await computeSuggestions('''
@@ -391,6 +448,24 @@ suggestions
391448
''');
392449
}
393450

451+
Future<void> test_extensionType_equality() async {
452+
allowedIdentifiers = {'getter', 'notStatic'};
453+
await computeSuggestions('''
454+
extension type C(int x) {
455+
static C get getter => C(1);
456+
C get notStatic => C(1);
457+
}
458+
void f() {
459+
print(C(1) == .^);
460+
}
461+
''');
462+
assertResponse(r'''
463+
suggestions
464+
getter
465+
kind: getter
466+
''');
467+
}
468+
394469
Future<void> test_extensionType_functionExpression_futureOr() async {
395470
allowedIdentifiers = {'field'};
396471
await computeSuggestions('''

0 commit comments

Comments
 (0)