Skip to content

Commit 3b09a49

Browse files
pqCommit Queue
authored and
Commit Queue
committed
[wildcards] ensure bound __ underscores are suggested in completions
See: #56361 Change-Id: Ia1b1a0fef17fb68f476d2ade96a0b5761152336b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/378720 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Phil Quitslund <[email protected]>
1 parent fc7e450 commit 3b09a49

File tree

2 files changed

+99
-14
lines changed

2 files changed

+99
-14
lines changed

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

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ import 'package:analyzer/src/workspace/pub.dart';
2626
/// A helper class that produces candidate suggestions for all of the
2727
/// declarations that are in scope at the completion location.
2828
class DeclarationHelper {
29-
/// The regular expression used to detect an unused identifier (a sequence of
30-
/// one or more underscores with no other characters).
31-
static final RegExp UnusedIdentifier = RegExp(r'^_+$');
32-
3329
/// The completion request being processed.
3430
final DartCompletionRequest request;
3531

@@ -667,7 +663,7 @@ class DeclarationHelper {
667663
required String? prefix,
668664
}) {
669665
// Don't suggest declarations in wildcard prefixed namespaces.
670-
if (prefix == '_') return;
666+
if (_isWildcard(prefix)) return;
671667

672668
var importData = ImportData(
673669
libraryUri: library.source.uri,
@@ -1392,9 +1388,8 @@ class DeclarationHelper {
13921388
return true;
13931389
}
13941390

1395-
/// Returns `true` if the [identifier] is composed of one or more underscore
1396-
/// characters and nothing else.
1397-
bool _isUnused(String identifier) => UnusedIdentifier.hasMatch(identifier);
1391+
/// Returns `true` if the [identifier] is a wildcard (a single `_`).
1392+
bool _isWildcard(String? identifier) => identifier == '_';
13981393

13991394
/// Record that the given [operation] should be performed in the second pass.
14001395
void _recordOperation(NotImportedOperation operation) {
@@ -1631,7 +1626,7 @@ class DeclarationHelper {
16311626
return;
16321627
}
16331628
// Don't suggest wildcard local functions.
1634-
if (element.name == '_') return;
1629+
if (_isWildcard(element.name)) return;
16351630
var matcherScore = state.matcher.score(element.displayName);
16361631
if (matcherScore != -1) {
16371632
var suggestion = LocalFunctionSuggestion(
@@ -1705,7 +1700,7 @@ class DeclarationHelper {
17051700
/// Adds a suggestion for the parameter represented by the [element].
17061701
void _suggestParameter(ParameterElement element) {
17071702
if (visibilityTracker.isVisible(element: element, importData: null)) {
1708-
if (mustBeConstant || _isUnused(element.name)) {
1703+
if (mustBeConstant || _isWildcard(element.name)) {
17091704
return;
17101705
}
17111706
var matcherScore = state.matcher.score(element.displayName);

pkg/analysis_server/test/services/completion/dart/declaration/wildcard_variables_test.dart

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ suggestions
6565
@reflectiveTest
6666
class WildcardForLoopTest extends AbstractCompletionDriverTest {
6767
@override
68-
Set<String> allowedIdentifiers = {'_'};
68+
Set<String> allowedIdentifiers = {'_', '__'};
6969

7070
@override
7171
bool get includeKeywords => false;
@@ -85,6 +85,23 @@ suggestions
8585
''');
8686
}
8787

88+
Future<void> test_forEach_argumentList_underscores() async {
89+
await computeSuggestions('''
90+
void p(Object o) {}
91+
92+
void f() {
93+
for (var __ in []) {
94+
p(^);
95+
}
96+
}
97+
''');
98+
assertResponse('''
99+
suggestions
100+
__
101+
kind: localVariable
102+
''');
103+
}
104+
88105
Future<void> test_forParts_argumentList() async {
89106
await computeSuggestions('''
90107
void p(Object o) {}
@@ -97,14 +114,31 @@ void f() {
97114
''');
98115
assertResponse('''
99116
suggestions
117+
''');
118+
}
119+
120+
Future<void> test_forParts_argumentList_underscores() async {
121+
await computeSuggestions('''
122+
void p(Object o) {}
123+
124+
void f() {
125+
for (var __ = 0; ;) {
126+
p(^);
127+
}
128+
}
129+
''');
130+
assertResponse('''
131+
suggestions
132+
__
133+
kind: localVariable
100134
''');
101135
}
102136
}
103137

104138
@reflectiveTest
105139
class WildcardImportPrefixTest extends AbstractCompletionDriverTest {
106140
@override
107-
Set<String> allowedIdentifiers = {'_', 'isBlank'};
141+
Set<String> allowedIdentifiers = {'_', '__', 'isBlank'};
108142

109143
@override
110144
bool get includeKeywords => false;
@@ -131,6 +165,31 @@ suggestions
131165
''');
132166
}
133167

168+
Future<void> test_argumentList_underscores() async {
169+
newFile('$testPackageLibPath/ext.dart', '''
170+
extension ES on String {
171+
bool get isBlank => false;
172+
}
173+
''');
174+
175+
await computeSuggestions('''
176+
import 'ext.dart' as __;
177+
178+
void p(Object o) {}
179+
180+
void f() {
181+
p(^);
182+
}
183+
''');
184+
assertResponse('''
185+
suggestions
186+
__.ES
187+
kind: extensionInvocation
188+
__
189+
kind: library
190+
''');
191+
}
192+
134193
Future<void> test_stringExtension_argumentList() async {
135194
newFile('$testPackageLibPath/ext.dart', '''
136195
extension ES on String {
@@ -158,7 +217,7 @@ suggestions
158217
@reflectiveTest
159218
class WildcardLocalVariableTest extends AbstractCompletionDriverTest {
160219
@override
161-
Set<String> allowedIdentifiers = {'_', 'b'};
220+
Set<String> allowedIdentifiers = {'_', '__', 'b'};
162221

163222
@override
164223
bool get includeKeywords => false;
@@ -190,14 +249,30 @@ void f() {
190249
''');
191250
assertResponse(r'''
192251
suggestions
252+
''');
253+
}
254+
255+
Future<void> test_argumentList_underscores() async {
256+
await computeSuggestions('''
257+
void p(Object o) {}
258+
259+
void f() {
260+
var __ = 0;
261+
p(^);
262+
}
263+
''');
264+
assertResponse(r'''
265+
suggestions
266+
__
267+
kind: localVariable
193268
''');
194269
}
195270
}
196271

197272
@reflectiveTest
198273
class WildcardParameterTest extends AbstractCompletionDriverTest {
199274
@override
200-
Set<String> allowedIdentifiers = {'_', 'b'};
275+
Set<String> allowedIdentifiers = {'_', '__', 'b'};
201276

202277
@override
203278
bool get includeKeywords => false;
@@ -214,6 +289,21 @@ void f(int _, int b) {
214289
suggestions
215290
b
216291
kind: parameter
292+
''');
293+
}
294+
295+
Future<void> test_argumentList_underscores() async {
296+
await computeSuggestions('''
297+
void p(Object o) {}
298+
299+
void f(int __) {
300+
p(^);
301+
}
302+
''');
303+
assertResponse('''
304+
suggestions
305+
__
306+
kind: parameter
217307
''');
218308
}
219309
}

0 commit comments

Comments
 (0)