mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 11:03:19 +00:00
Completion. Issue 55167. Suggest type names for DeclaredVariablePattern, in SwitchPatternCase.
Bug: https://github.com/dart-lang/sdk/issues/55167 Change-Id: I1f00fd0ea589786767443d97e7c74b7f482ba4be Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/359243 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
5acb2132f8
commit
c61aecda75
|
@ -2338,6 +2338,8 @@ class InScopeCompletionPass extends SimpleAstVisitor<void> {
|
|||
|
||||
@override
|
||||
void visitSwitchPatternCase(SwitchPatternCase node) {
|
||||
var coveringNode = state.selection.coveringNode;
|
||||
|
||||
if (offset <= node.keyword.end) {
|
||||
keywordHelper.addKeyword(Keyword.CASE);
|
||||
} else if (offset <= node.colon.offset) {
|
||||
|
@ -2350,6 +2352,39 @@ class InScopeCompletionPass extends SimpleAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
// `case ^ y:`
|
||||
// The user want a type for incomplete DeclaredVariablePattern.
|
||||
var pattern = node.guardedPattern.pattern;
|
||||
if (pattern is ConstantPattern) {
|
||||
if (pattern.expression case SimpleIdentifier identifier) {
|
||||
if (!identifier.isSynthetic && offset < identifier.offset) {
|
||||
state.request.opType.includeConstructorSuggestions = false;
|
||||
state.request.opType.mustBeConst = true;
|
||||
declarationHelper(
|
||||
mustBeType: true,
|
||||
).addLexicalDeclarations(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeclaredVariablePattern `case Name^ y:`
|
||||
// ObjectPattern `case Name^(): `
|
||||
if (coveringNode case NamedType type) {
|
||||
switch (type.parent) {
|
||||
case DeclaredVariablePattern():
|
||||
collector.completionLocation = 'DeclaredVariablePattern_type';
|
||||
state.request.opType.includeConstructorSuggestions = false;
|
||||
type.accept(this);
|
||||
return;
|
||||
case ObjectPattern():
|
||||
collector.completionLocation = 'ObjectPattern_type';
|
||||
state.request.opType.includeConstructorSuggestions = false;
|
||||
type.accept(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
collector.completionLocation = 'SwitchPatternCase_pattern';
|
||||
var previous = node.colon.previous!;
|
||||
var previousKeyword = previous.keyword;
|
||||
|
|
|
@ -52,6 +52,166 @@ suggestions
|
|||
''');
|
||||
}
|
||||
|
||||
Future<void> test_afterCase_declaredVariablePattern_typeX_name() async {
|
||||
// It is essential to import this library.
|
||||
// Currently not-yet imported contributor adds classes.
|
||||
// But we want to exercise InScopeCompletionPass.
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
class A01 {}
|
||||
class A02 {}
|
||||
class B01 {}
|
||||
''');
|
||||
|
||||
await computeSuggestions('''
|
||||
import 'a.dart';
|
||||
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case 0: break;
|
||||
case A0^ y:
|
||||
break;
|
||||
}
|
||||
}
|
||||
''');
|
||||
assertResponse(r'''
|
||||
replacement
|
||||
left: 2
|
||||
suggestions
|
||||
A01
|
||||
kind: class
|
||||
A02
|
||||
kind: class
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_afterCase_final_x_name() async {
|
||||
await computeSuggestions('''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case final ^ y:
|
||||
}
|
||||
}
|
||||
|
||||
class A01 {}
|
||||
class A02 {}
|
||||
class B01 {}
|
||||
''');
|
||||
assertResponse(r'''
|
||||
suggestions
|
||||
A01
|
||||
kind: class
|
||||
A02
|
||||
kind: class
|
||||
B01
|
||||
kind: class
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_afterCase_nameX_includeClass_imported() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
class A01 {}
|
||||
class A02 {}
|
||||
class B01 {}
|
||||
''');
|
||||
await computeSuggestions('''
|
||||
import 'a.dart';
|
||||
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case A0^
|
||||
}
|
||||
}
|
||||
''');
|
||||
assertResponse(r'''
|
||||
replacement
|
||||
left: 2
|
||||
suggestions
|
||||
A01
|
||||
kind: class
|
||||
A01
|
||||
kind: constructorInvocation
|
||||
A02
|
||||
kind: class
|
||||
A02
|
||||
kind: constructorInvocation
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_afterCase_nameX_includeClass_local() async {
|
||||
await computeSuggestions('''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case A0^
|
||||
}
|
||||
}
|
||||
|
||||
class A01 {}
|
||||
class A02 {}
|
||||
class B01 {}
|
||||
''');
|
||||
assertResponse(r'''
|
||||
replacement
|
||||
left: 2
|
||||
suggestions
|
||||
A01
|
||||
kind: class
|
||||
A01
|
||||
kind: constructorInvocation
|
||||
A02
|
||||
kind: class
|
||||
A02
|
||||
kind: constructorInvocation
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_afterCase_nameX_includeClass_notImported() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
class A01 {}
|
||||
class A02 {}
|
||||
class B01 {}
|
||||
''');
|
||||
await computeSuggestions('''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case A0^
|
||||
}
|
||||
}
|
||||
''');
|
||||
// TODO(scheglov): this is wrong, include only const constructors.
|
||||
assertResponse(r'''
|
||||
replacement
|
||||
left: 2
|
||||
suggestions
|
||||
A01
|
||||
kind: class
|
||||
A02
|
||||
kind: class
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_afterCase_nothing_x_name() async {
|
||||
await computeSuggestions('''
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case ^ y:
|
||||
}
|
||||
}
|
||||
|
||||
class A01 {}
|
||||
class A02 {}
|
||||
class B01 {}
|
||||
''');
|
||||
assertResponse(r'''
|
||||
suggestions
|
||||
A01
|
||||
kind: class
|
||||
A02
|
||||
kind: class
|
||||
B01
|
||||
kind: class
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_afterCase_partial() async {
|
||||
await computeSuggestions('''
|
||||
void f(Object x) {
|
||||
|
|
Loading…
Reference in a new issue