mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 14:32:24 +00:00
Support code completion in cast patterns
Change-Id: I429957a44bdc09a0936c10123b58b3514b23e016 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/279563 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
b2c26d0aae
commit
2ca588fce8
6 changed files with 183 additions and 18 deletions
|
@ -96,12 +96,16 @@ abstract class AbstractCompletionDriverTest
|
|||
final actual = buffer.toString();
|
||||
|
||||
if (actual != expected) {
|
||||
// TODO(brianwilkerson) Improve the output to make it easier to debug. For
|
||||
// example, print the type of the covering node and the `entity` used to
|
||||
// compute the suggestions.
|
||||
var target = driver.server.server.completionState.currentRequest?.target;
|
||||
var where = '';
|
||||
if (target != null) {
|
||||
var containingNode = target.containingNode.runtimeType;
|
||||
var entity = target.entity;
|
||||
where = ' (containingNode = $containingNode, entity = $entity)';
|
||||
}
|
||||
TextExpectationsCollector.add(actual);
|
||||
fail('''
|
||||
The actual suggestions do not match the expected suggestions.
|
||||
The actual suggestions do not match the expected suggestions$where.
|
||||
|
||||
To accept the current state change the expectation to
|
||||
|
||||
|
|
|
@ -5849,7 +5849,6 @@ class C<T> {
|
|||
assertNotSuggested('String');
|
||||
}
|
||||
|
||||
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49759')
|
||||
Future<void> test_SwitchStatement_case_var() async {
|
||||
// SwitchStatement Block BlockFunctionBody MethodDeclaration
|
||||
addTestSource('''
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:analysis_server/src/protocol_server.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../../../../client/completion_driver_test.dart';
|
||||
import '../completion_printer.dart' as printer;
|
||||
|
||||
void main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(CastPatternTest1);
|
||||
defineReflectiveTests(CastPatternTest2);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class CastPatternTest1 extends AbstractCompletionDriverTest
|
||||
with CastPatternTestCases {
|
||||
@override
|
||||
TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class CastPatternTest2 extends AbstractCompletionDriverTest
|
||||
with CastPatternTestCases {
|
||||
@override
|
||||
TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
|
||||
}
|
||||
|
||||
mixin CastPatternTestCases on AbstractCompletionDriverTest {
|
||||
@override
|
||||
Future<void> setUp() async {
|
||||
await super.setUp();
|
||||
|
||||
printerConfiguration = printer.Configuration(
|
||||
filter: (suggestion) {
|
||||
final completion = suggestion.completion;
|
||||
return suggestion.kind == CompletionSuggestionKind.KEYWORD ||
|
||||
['A0', 'B0'].any(completion.startsWith);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> test_partialType() async {
|
||||
await computeSuggestions('''
|
||||
void f(Object x) {
|
||||
switch (x) {
|
||||
case i as A^
|
||||
}
|
||||
}
|
||||
class A01 {}
|
||||
class A02 {}
|
||||
class B01 {}
|
||||
''');
|
||||
if (isProtocolVersion2) {
|
||||
assertResponse('''
|
||||
replacement
|
||||
left: 1
|
||||
suggestions
|
||||
A01
|
||||
kind: class
|
||||
A02
|
||||
kind: class
|
||||
''');
|
||||
} else {
|
||||
assertResponse('''
|
||||
replacement
|
||||
left: 1
|
||||
suggestions
|
||||
A01
|
||||
kind: class
|
||||
A02
|
||||
kind: class
|
||||
B01
|
||||
kind: class
|
||||
''');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,7 +37,9 @@ mixin SwitchPatternCaseTestCases on AbstractCompletionDriverTest {
|
|||
// TODO(brianwilkerson) Include more than keywords in these tests.
|
||||
printerConfiguration = printer.Configuration(
|
||||
filter: (suggestion) {
|
||||
return suggestion.kind == CompletionSuggestionKind.KEYWORD;
|
||||
final completion = suggestion.completion;
|
||||
return suggestion.kind == CompletionSuggestionKind.KEYWORD ||
|
||||
['A0', 'B0'].any(completion.startsWith);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -50,33 +52,38 @@ void f(Object o) {
|
|||
return;
|
||||
}
|
||||
}
|
||||
class A01 {}
|
||||
''');
|
||||
assertResponse('''
|
||||
suggestions
|
||||
assert
|
||||
kind: keyword
|
||||
break
|
||||
kind: keyword
|
||||
return
|
||||
kind: keyword
|
||||
if
|
||||
kind: keyword
|
||||
A01
|
||||
kind: class
|
||||
final
|
||||
kind: keyword
|
||||
for
|
||||
kind: keyword
|
||||
throw
|
||||
kind: keyword
|
||||
A01
|
||||
kind: constructorInvocation
|
||||
assert
|
||||
kind: keyword
|
||||
const
|
||||
kind: keyword
|
||||
do
|
||||
kind: keyword
|
||||
dynamic
|
||||
kind: keyword
|
||||
final
|
||||
kind: keyword
|
||||
for
|
||||
kind: keyword
|
||||
if
|
||||
kind: keyword
|
||||
late
|
||||
kind: keyword
|
||||
return
|
||||
kind: keyword
|
||||
switch
|
||||
kind: keyword
|
||||
throw
|
||||
kind: keyword
|
||||
try
|
||||
kind: keyword
|
||||
var
|
||||
|
@ -296,6 +303,51 @@ suggestions
|
|||
kind: keyword
|
||||
when
|
||||
kind: keyword
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_noColon_afterDeclarationAndAs() async {
|
||||
await computeSuggestions('''
|
||||
void f(Object x) {
|
||||
switch (x) {
|
||||
case var i as ^
|
||||
}
|
||||
}
|
||||
class A01 {}
|
||||
class A02 {}
|
||||
class B01 {}
|
||||
''');
|
||||
assertResponse('''
|
||||
suggestions
|
||||
A01
|
||||
kind: class
|
||||
A02
|
||||
kind: class
|
||||
B01
|
||||
kind: class
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_noColon_afterReferenceAndAs() async {
|
||||
await computeSuggestions('''
|
||||
void f(Object x) {
|
||||
const i = 0;
|
||||
switch (x) {
|
||||
case i as ^
|
||||
}
|
||||
}
|
||||
class A01 {}
|
||||
class A02 {}
|
||||
class B01 {}
|
||||
''');
|
||||
assertResponse('''
|
||||
suggestions
|
||||
A01
|
||||
kind: class
|
||||
A02
|
||||
kind: class
|
||||
B01
|
||||
kind: class
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:test_reflective_loader/test_reflective_loader.dart';
|
|||
|
||||
import 'block_test.dart' as block;
|
||||
import 'case_clause_test.dart' as case_clause;
|
||||
import 'cast_pattern_test.dart' as cast_pattern;
|
||||
import 'class_body_test.dart' as class_body;
|
||||
import 'compilation_unit_test.dart' as compilation_unit;
|
||||
import 'directive_uri_test.dart' as directive_uri;
|
||||
|
@ -26,6 +27,7 @@ void main() {
|
|||
defineReflectiveSuite(() {
|
||||
block.main();
|
||||
case_clause.main();
|
||||
cast_pattern.main();
|
||||
class_body.main();
|
||||
compilation_unit.main();
|
||||
directive_uri.main();
|
||||
|
|
|
@ -350,6 +350,14 @@ class _OpTypeAstVisitor extends GeneralizingAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitCastPattern(CastPattern node) {
|
||||
if (identical(entity, node.type)) {
|
||||
optype.completionLocation = 'CastPattern_type';
|
||||
optype.includeTypeNameSuggestions = true;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitCatchClause(CatchClause node) {
|
||||
if (identical(entity, node.exceptionType)) {
|
||||
|
@ -1317,6 +1325,25 @@ class _OpTypeAstVisitor extends GeneralizingAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitSwitchPatternCase(SwitchPatternCase node) {
|
||||
if (identical(entity, node.colon)) {
|
||||
var guardedPattern = node.guardedPattern;
|
||||
var pattern = guardedPattern.pattern;
|
||||
if (guardedPattern.whenClause == null &&
|
||||
pattern is DeclaredVariablePattern &&
|
||||
pattern.name.lexeme == 'as') {
|
||||
optype.completionLocation = 'CastPattern_type';
|
||||
optype.includeTypeNameSuggestions = true;
|
||||
}
|
||||
} else if (node.statements.contains(entity)) {
|
||||
optype.completionLocation = 'SwitchMember_statement';
|
||||
optype.includeReturnValueSuggestions = true;
|
||||
optype.includeTypeNameSuggestions = true;
|
||||
optype.includeVoidReturnSuggestions = true;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitSwitchStatement(SwitchStatement node) {
|
||||
if (identical(entity, node.expression)) {
|
||||
|
|
Loading…
Reference in a new issue