mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:10:22 +00:00
Include type parameters into suggested code completions.
R=brianwilkerson@google.com Bug: https://buganizer.corp.google.com/issues/120659839 Change-Id: I51ec6142b97b079c4db55ef1f2081354ee16dda5 Reviewed-on: https://dart-review.googlesource.com/c/91858 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
2efd22271e
commit
8c891ec25e
5 changed files with 177 additions and 11 deletions
|
@ -317,14 +317,30 @@ class _LocalVisitor extends LocalDeclarationVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void declaredTypeParameter(TypeParameter node) {
|
||||
if (optype.includeTypeNameSuggestions) {
|
||||
_addLocalSuggestion(
|
||||
null,
|
||||
node.name,
|
||||
null,
|
||||
protocol.ElementKind.TYPE_PARAMETER,
|
||||
isDeprecated: isDeprecated(node),
|
||||
kind: CompletionSuggestionKind.IDENTIFIER,
|
||||
relevance: DART_RELEVANCE_TYPE_PARAMETER,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _addLocalSuggestion(Comment documentationComment, SimpleIdentifier id,
|
||||
TypeAnnotation typeName, protocol.ElementKind elemKind,
|
||||
{bool isAbstract: false,
|
||||
bool isDeprecated: false,
|
||||
ClassOrMixinDeclaration classDecl,
|
||||
CompletionSuggestionKind kind,
|
||||
FormalParameterList param,
|
||||
int relevance: DART_RELEVANCE_DEFAULT}) {
|
||||
CompletionSuggestionKind kind = targetIsFunctionalArgument
|
||||
kind ??= targetIsFunctionalArgument
|
||||
? CompletionSuggestionKind.IDENTIFIER
|
||||
: optype.suggestKind;
|
||||
CompletionSuggestion suggestion = createLocalSuggestion(
|
||||
|
|
|
@ -163,19 +163,13 @@ interface A<X> default B<X extends !1List!2> {}''',
|
|||
<String>["1+DateTime", "2+List"],
|
||||
failingTests: '12');
|
||||
|
||||
buildTests(
|
||||
'testCommentSnippets030',
|
||||
'''
|
||||
buildTests('testCommentSnippets030', '''
|
||||
class Bar<T extends Foo> {const Bar(!1T!2 k);T!3 m(T!4 a, T!5 b){}final T!6 f = null;}''',
|
||||
<String>["1+T", "2+T", "3+T", "4+T", "5+T", "6+T"],
|
||||
failingTests: '123456');
|
||||
<String>["1+T", "2+T", "3+T", "4+T", "5+T", "6+T"]);
|
||||
|
||||
buildTests(
|
||||
'testCommentSnippets031',
|
||||
'''
|
||||
buildTests('testCommentSnippets031', '''
|
||||
class Bar<T extends Foo> {m(x){if (x is !1) return;if (x is!!!2)}}''',
|
||||
<String>["1+Bar", "1+T", "2+T", "2+Bar"],
|
||||
failingTests: '12');
|
||||
<String>["1+Bar", "1+T", "2+T", "2+Bar"]);
|
||||
|
||||
buildTests(
|
||||
'testCommentSnippets032',
|
||||
|
|
|
@ -57,6 +57,20 @@ class LocalReferenceContributorTest extends DartCompletionContributorTest {
|
|||
return cs;
|
||||
}
|
||||
|
||||
CompletionSuggestion assertSuggestTypeParameter(String name,
|
||||
{int relevance: DART_RELEVANCE_TYPE_PARAMETER}) {
|
||||
CompletionSuggestion cs = assertSuggest(name,
|
||||
csKind: CompletionSuggestionKind.IDENTIFIER, relevance: relevance);
|
||||
expect(cs.returnType, isNull);
|
||||
Element element = cs.element;
|
||||
expect(element, isNotNull);
|
||||
expect(element.kind, equals(ElementKind.TYPE_PARAMETER));
|
||||
expect(element.name, equals(name));
|
||||
expect(element.parameters, isNull);
|
||||
expect(element.returnType, isNull);
|
||||
return cs;
|
||||
}
|
||||
|
||||
@override
|
||||
DartCompletionContributor createContributor() {
|
||||
return new LocalReferenceContributor();
|
||||
|
@ -2301,6 +2315,108 @@ main() {
|
|||
assertSuggestEnumConst('F.four');
|
||||
}
|
||||
|
||||
test_expression_localVariable() async {
|
||||
addTestSource('''
|
||||
void f() {
|
||||
var v = 0;
|
||||
^
|
||||
}
|
||||
''');
|
||||
await computeSuggestions();
|
||||
assertSuggestLocalVariable('v', 'int');
|
||||
}
|
||||
|
||||
test_expression_parameter() async {
|
||||
addTestSource('''
|
||||
void f(int a) {
|
||||
^
|
||||
}
|
||||
''');
|
||||
await computeSuggestions();
|
||||
assertSuggestParameter('a', 'int');
|
||||
}
|
||||
|
||||
test_expression_typeParameter_classDeclaration() async {
|
||||
addTestSource('''
|
||||
class A<T> {
|
||||
void m() {
|
||||
^
|
||||
}
|
||||
}
|
||||
class B<U> {}
|
||||
''');
|
||||
await computeSuggestions();
|
||||
assertSuggestTypeParameter('T');
|
||||
assertNotSuggested('U');
|
||||
}
|
||||
|
||||
test_expression_typeParameter_classTypeAlias() async {
|
||||
addTestSource('''
|
||||
class A<U> {}
|
||||
class B<T> = A<^>;
|
||||
''');
|
||||
await computeSuggestions();
|
||||
assertSuggestTypeParameter('T');
|
||||
assertNotSuggested('U');
|
||||
}
|
||||
|
||||
test_expression_typeParameter_functionDeclaration() async {
|
||||
addTestSource('''
|
||||
void f<T>() {
|
||||
^
|
||||
}
|
||||
void g<U>() {}
|
||||
''');
|
||||
await computeSuggestions();
|
||||
assertSuggestTypeParameter('T');
|
||||
assertNotSuggested('U');
|
||||
}
|
||||
|
||||
test_expression_typeParameter_functionDeclaration_local() async {
|
||||
addTestSource('''
|
||||
void f() {
|
||||
void g2<U>() {}
|
||||
void g<T>() {
|
||||
^
|
||||
}
|
||||
}
|
||||
''');
|
||||
await computeSuggestions();
|
||||
assertSuggestTypeParameter('T');
|
||||
assertNotSuggested('U');
|
||||
}
|
||||
|
||||
test_expression_typeParameter_functionTypeAlias() async {
|
||||
addTestSource('''
|
||||
typedef void F<T>(^);
|
||||
''');
|
||||
await computeSuggestions();
|
||||
assertSuggestTypeParameter('T');
|
||||
}
|
||||
|
||||
test_expression_typeParameter_genericTypeAlias() async {
|
||||
addTestSource('''
|
||||
typedef F<T> = void Function<U>(^);
|
||||
''');
|
||||
await computeSuggestions();
|
||||
assertSuggestTypeParameter('T');
|
||||
assertSuggestTypeParameter('U');
|
||||
}
|
||||
|
||||
test_expression_typeParameter_methodDeclaration() async {
|
||||
addTestSource('''
|
||||
class A {
|
||||
void m<T>() {
|
||||
^
|
||||
}
|
||||
void m2<U>() {}
|
||||
}
|
||||
''');
|
||||
await computeSuggestions();
|
||||
assertSuggestTypeParameter('T');
|
||||
assertNotSuggested('U');
|
||||
}
|
||||
|
||||
test_ExpressionStatement_identifier() async {
|
||||
// SimpleIdentifier ExpressionStatement Block
|
||||
addSource('/home/test/lib/a.dart', '''
|
||||
|
@ -4600,6 +4716,16 @@ class X{}''');
|
|||
assertNoSuggestions();
|
||||
}
|
||||
|
||||
test_type_typeParameter_classDeclaration() async {
|
||||
addTestSource('''
|
||||
class A<T> {
|
||||
^ m() {}
|
||||
}
|
||||
''');
|
||||
await computeSuggestions();
|
||||
assertSuggestTypeParameter('T');
|
||||
}
|
||||
|
||||
test_TypeArgumentList() async {
|
||||
// SimpleIdentifier BinaryExpression ExpressionStatement
|
||||
addSource('/home/test/lib/a.dart', '''
|
||||
|
|
|
@ -48,6 +48,8 @@ abstract class LocalDeclarationVisitor extends GeneralizingAstVisitor {
|
|||
void declaredTopLevelVar(
|
||||
VariableDeclarationList varList, VariableDeclaration varDecl);
|
||||
|
||||
void declaredTypeParameter(TypeParameter node) {}
|
||||
|
||||
/**
|
||||
* Throw an exception indicating that [LocalDeclarationVisitor] should
|
||||
* stop visiting. This is caught in [visit] which then exits normally.
|
||||
|
@ -100,10 +102,15 @@ abstract class LocalDeclarationVisitor extends GeneralizingAstVisitor {
|
|||
node.declarations.forEach((Declaration declaration) {
|
||||
if (declaration is ClassDeclaration) {
|
||||
declaredClass(declaration);
|
||||
_visitTypeParameters(declaration, declaration.typeParameters);
|
||||
} else if (declaration is EnumDeclaration) {
|
||||
declaredEnum(declaration);
|
||||
} else if (declaration is FunctionDeclaration) {
|
||||
declaredFunction(declaration);
|
||||
_visitTypeParameters(
|
||||
declaration,
|
||||
declaration.functionExpression.typeParameters,
|
||||
);
|
||||
} else if (declaration is TopLevelVariableDeclaration) {
|
||||
var varList = declaration.variables;
|
||||
if (varList != null) {
|
||||
|
@ -113,10 +120,17 @@ abstract class LocalDeclarationVisitor extends GeneralizingAstVisitor {
|
|||
}
|
||||
} else if (declaration is ClassTypeAlias) {
|
||||
declaredClassTypeAlias(declaration);
|
||||
_visitTypeParameters(declaration, declaration.typeParameters);
|
||||
} else if (declaration is FunctionTypeAlias) {
|
||||
declaredFunctionTypeAlias(declaration);
|
||||
_visitTypeParameters(declaration, declaration.typeParameters);
|
||||
} else if (declaration is GenericTypeAlias) {
|
||||
declaredGenericTypeAlias(declaration);
|
||||
_visitTypeParameters(declaration, declaration.typeParameters);
|
||||
_visitTypeParameters(
|
||||
declaration.functionType,
|
||||
declaration.functionType.typeParameters,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -224,6 +238,7 @@ abstract class LocalDeclarationVisitor extends GeneralizingAstVisitor {
|
|||
});
|
||||
} else if (member is MethodDeclaration) {
|
||||
declaredMethod(member);
|
||||
_visitTypeParameters(member, member.typeParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -271,6 +286,10 @@ abstract class LocalDeclarationVisitor extends GeneralizingAstVisitor {
|
|||
String name = id.name;
|
||||
if (name != null && name.length > 0) {
|
||||
declaredFunction(declaration);
|
||||
_visitTypeParameters(
|
||||
declaration,
|
||||
declaration.functionExpression.typeParameters,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -278,6 +297,16 @@ abstract class LocalDeclarationVisitor extends GeneralizingAstVisitor {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _visitTypeParameters(AstNode node, TypeParameterList typeParameters) {
|
||||
if (typeParameters == null) return;
|
||||
|
||||
if (node.offset < offset && offset < node.end) {
|
||||
for (var typeParameter in typeParameters.typeParameters) {
|
||||
declaredTypeParameter(typeParameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,3 +26,4 @@ const int DART_RELEVANCE_LOW = 500;
|
|||
const int DART_RELEVANCE_NAMED_PARAMETER = 1060;
|
||||
const int DART_RELEVANCE_NAMED_PARAMETER_REQUIRED = 1065;
|
||||
const int DART_RELEVANCE_PARAMETER = 1059;
|
||||
const int DART_RELEVANCE_TYPE_PARAMETER = 1058;
|
||||
|
|
Loading…
Reference in a new issue