rework ArgListContributor to use new task model

R=scheglov@google.com

Review URL: https://codereview.chromium.org/1500793003 .
This commit is contained in:
danrubel 2015-12-03 18:00:50 -05:00
parent 7dfb517618
commit 4379efb6b4
10 changed files with 432 additions and 610 deletions

View file

@ -74,4 +74,13 @@ abstract class DartCompletionRequest extends CompletionRequest {
* should be discarded as it may have changed.
*/
Future<CompilationUnit> resolveDeclarationsInScope();
/**
* Return a [Future] that completes when the element associated with
* the given [identifier] is available or if the identifier cannot be resolved
* (e.g. unknown identifier, completion aborted, etc).
* Any information obtained from [target] prior to calling this method
* should be discarded as it may have changed.
*/
Future resolveIdentifier(SimpleIdentifier identifier);
}

View file

@ -7,6 +7,7 @@ library analysis_server.src.provisional.completion.dart.plugin;
import 'package:analysis_server/src/provisional/completion/completion.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/arglist_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
import 'package:analysis_server/src/services/completion/dart/keyword_contributor.dart';
import 'package:plugin/plugin.dart';
@ -64,6 +65,8 @@ class DartCompletionPlugin implements Plugin {
//
// Register the default DartCompletionContributors
//
registerExtension(DART_COMPLETION_CONTRIBUTOR_EXTENSION_POINT_ID,
() => new ArgListContributor());
registerExtension(DART_COMPLETION_CONTRIBUTOR_EXTENSION_POINT_ID,
() => new KeywordContributor());
}

View file

@ -1,427 +0,0 @@
// Copyright (c) 2014, 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.
library services.completion.contributor.dart.arglist;
import 'dart:async';
import 'package:analysis_server/src/protocol_server.dart'
hide Element, ElementKind;
import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
import 'package:analysis_server/src/services/completion/local_declaration_visitor.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
void _addNamedParameterSuggestion(
DartCompletionRequest request, List<String> namedArgs, String name) {
if (name != null && name.length > 0 && !namedArgs.contains(name)) {
request.addSuggestion(new CompletionSuggestion(
CompletionSuggestionKind.NAMED_ARGUMENT,
DART_RELEVANCE_NAMED_PARAMETER,
'$name: ',
name.length + 2,
0,
false,
false));
}
}
/**
* Determine the number of arguments.
*/
int _argCount(DartCompletionRequest request) {
AstNode node = request.target.containingNode;
if (node is ArgumentList) {
return node.arguments.length;
}
return 0;
}
/**
* Determine if the completion target is at the end of the list of arguments.
*/
bool _isAppendingToArgList(DartCompletionRequest request) {
AstNode node = request.target.containingNode;
if (node is ArgumentList) {
var entity = request.target.entity;
if (entity == node.rightParenthesis) {
return true;
}
if (node.arguments.length > 0 && node.arguments.last == entity) {
return entity is SimpleIdentifier;
}
}
return false;
}
/**
* Determine if the completion target is an emtpy argument list.
*/
bool _isEmptyArgList(DartCompletionRequest request) {
AstNode node = request.target.containingNode;
return node is ArgumentList &&
node.leftParenthesis.next == node.rightParenthesis;
}
/**
* Return a collection of currently specified named arguments
*/
Iterable<String> _namedArgs(DartCompletionRequest request) {
AstNode node = request.target.containingNode;
List<String> namedArgs = new List<String>();
if (node is ArgumentList) {
for (Expression arg in node.arguments) {
if (arg is NamedExpression) {
namedArgs.add(arg.name.label.name);
}
}
}
return namedArgs;
}
/**
* A contributor for calculating `completion.getSuggestions` request results
* when the cursor position is inside the arguments to a method call.
*/
class ArgListContributor extends DartCompletionContributor {
_ArgSuggestionBuilder builder;
@override
bool computeFast(DartCompletionRequest request) {
builder =
request.target.containingNode.accept(new _ArgListAstVisitor(request));
return builder == null;
}
@override
Future<bool> computeFull(DartCompletionRequest request) {
if (builder != null) {
return builder.compute(request.target.containingNode);
}
return new Future.value(false);
}
}
/**
* A visitor for determining whether an argument list suggestion is needed
* and instantiating the builder to create the suggestion.
*/
class _ArgListAstVisitor extends GeneralizingAstVisitor<_ArgSuggestionBuilder> {
final DartCompletionRequest request;
_ArgListAstVisitor(this.request);
@override
_ArgSuggestionBuilder visitArgumentList(ArgumentList node) {
Token leftParen = node.leftParenthesis;
if (leftParen != null && request.offset > leftParen.offset) {
AstNode parent = node.parent;
if (parent is MethodInvocation) {
SimpleIdentifier selector = parent.methodName;
if (selector != null) {
String name = selector.name;
if (name != null && name.length > 0) {
if (parent.operator == null) {
/*
* If a local declaration is found, then return null
* indicating that suggestions were added
* and no further action is necessary
*/
if (new _LocalArgSuggestionBuilder(request, request.offset, name)
.visit(node)) {
return null;
}
} else {
// determine target
}
return new _ArgSuggestionBuilder(request, name);
}
}
}
String constructorName;
if (parent is Annotation && parent.name != null) {
constructorName = parent.name.toSource();
}
if (parent is InstanceCreationExpression &&
parent.constructorName != null) {
constructorName = parent.constructorName.toSource();
}
if (constructorName != null && constructorName.length > 0) {
if (new _LocalArgSuggestionBuilder(
request, request.offset, constructorName).visit(node)) {
return null;
}
return new _ArgSuggestionBuilder(request, constructorName);
}
}
return null;
}
@override
_ArgSuggestionBuilder visitNode(AstNode node) {
return null;
}
}
/**
* A [_ArgSuggestionBuilder] determines which method or function is being
* invoked, then builds the argument list suggestion.
* This operation is instantiated during `computeFast`
* and calculates the suggestions during `computeFull`.
*/
class _ArgSuggestionBuilder {
final DartCompletionRequest request;
final String methodName;
_ArgSuggestionBuilder(this.request, this.methodName);
Future<bool> compute(ArgumentList node) {
AstNode parent = node.parent;
if (parent is MethodInvocation) {
SimpleIdentifier methodName = parent.methodName;
if (methodName != null) {
Element methodElem = methodName.bestElement;
if (methodElem is ExecutableElement) {
_addSuggestions(methodElem.parameters);
}
}
}
if (parent is InstanceCreationExpression) {
ConstructorName constructorName = parent.constructorName;
if (constructorName != null) {
ConstructorElement element = constructorName.staticElement;
if (element is ExecutableElement) {
_addSuggestions(element.parameters);
}
}
}
if (parent is Annotation) {
Element element = parent.element;
if (element is ExecutableElement) {
_addSuggestions(element.parameters);
}
}
return new Future.value(false);
}
void _addArgListSuggestion(Iterable<ParameterElement> requiredParam) {
StringBuffer completion = new StringBuffer('(');
List<String> paramNames = new List<String>();
List<String> paramTypes = new List<String>();
for (ParameterElement param in requiredParam) {
String name = param.name;
if (name != null && name.length > 0) {
if (completion.length > 1) {
completion.write(', ');
}
completion.write(name);
paramNames.add(name);
paramTypes.add(_getParamType(param));
}
}
completion.write(')');
CompletionSuggestion suggestion = new CompletionSuggestion(
CompletionSuggestionKind.ARGUMENT_LIST,
DART_RELEVANCE_HIGH,
completion.toString(),
completion.length,
0,
false,
false);
suggestion.parameterNames = paramNames;
suggestion.parameterTypes = paramTypes;
request.addSuggestion(suggestion);
}
void _addDefaultParamSuggestions(Iterable<ParameterElement> parameters) {
Iterable<String> namedArgs = _namedArgs(request);
for (ParameterElement param in parameters) {
if (param.parameterKind == ParameterKind.NAMED) {
_addNamedParameterSuggestion(request, namedArgs, param.name);
}
}
}
void _addSuggestions(Iterable<ParameterElement> parameters) {
if (parameters == null || parameters.length == 0) {
return;
}
Iterable<ParameterElement> requiredParam = parameters.where(
(ParameterElement p) => p.parameterKind == ParameterKind.REQUIRED);
int requiredCount = requiredParam.length;
if (requiredCount > 0 && _isEmptyArgList(request)) {
_addArgListSuggestion(requiredParam);
return;
}
if (_isAppendingToArgList(request)) {
if (requiredCount == 0 || requiredCount < _argCount(request)) {
_addDefaultParamSuggestions(parameters);
}
}
}
String _getParamType(ParameterElement param) {
DartType type = param.type;
if (type != null) {
return type.displayName;
}
return 'dynamic';
}
}
/**
* [_LocalArgSuggestionBuilder] visits an [AstNode] and its parent recursively
* looking for a matching declaration. If found, it adds the appropriate
* suggestions and sets finished to `true`.
*/
class _LocalArgSuggestionBuilder extends LocalDeclarationVisitor {
final DartCompletionRequest request;
final String name;
_LocalArgSuggestionBuilder(this.request, int offset, this.name)
: super(offset);
@override
void declaredClass(ClassDeclaration declaration) {
String className = null;
if (declaration.name != null) {
className = declaration.name.name;
}
if (className != null && className.length > 0) {
for (ClassMember member in declaration.members) {
if (member is ConstructorDeclaration) {
String selector = className;
if (member.name != null) {
selector = '$selector.${member.name.name}';
}
if (selector == name) {
_addSuggestions(member.parameters);
finished();
}
}
}
}
}
@override
void declaredClassTypeAlias(ClassTypeAlias declaration) {}
@override
void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {}
@override
void declaredFunction(FunctionDeclaration declaration) {
SimpleIdentifier selector = declaration.name;
if (selector != null && name == selector.name) {
_addSuggestions(declaration.functionExpression.parameters);
finished();
}
}
@override
void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {}
@override
void declaredLabel(Label label, bool isCaseLabel) {}
@override
void declaredLocalVar(SimpleIdentifier name, TypeName type) {}
@override
void declaredMethod(MethodDeclaration declaration) {
SimpleIdentifier selector = declaration.name;
if (selector != null && name == selector.name) {
_addSuggestions(declaration.parameters);
finished();
}
}
@override
void declaredParam(SimpleIdentifier name, TypeName type) {}
@override
void declaredTopLevelVar(
VariableDeclarationList varList, VariableDeclaration varDecl) {}
void _addArgListSuggestion(Iterable<FormalParameter> requiredParam) {
StringBuffer completion = new StringBuffer('(');
List<String> paramNames = new List<String>();
List<String> paramTypes = new List<String>();
for (FormalParameter param in requiredParam) {
SimpleIdentifier paramId = param.identifier;
if (paramId != null) {
String name = paramId.name;
if (name != null && name.length > 0) {
if (completion.length > 1) {
completion.write(', ');
}
completion.write(name);
paramNames.add(name);
paramTypes.add(_getParamType(param));
}
}
}
completion.write(')');
CompletionSuggestion suggestion = new CompletionSuggestion(
CompletionSuggestionKind.ARGUMENT_LIST,
DART_RELEVANCE_HIGH,
completion.toString(),
completion.length,
0,
false,
false);
suggestion.parameterNames = paramNames;
suggestion.parameterTypes = paramTypes;
request.addSuggestion(suggestion);
}
void _addDefaultParamSuggestions(FormalParameterList parameters) {
Iterable<String> namedArgs = _namedArgs(request);
for (FormalParameter param in parameters.parameters) {
if (param.kind == ParameterKind.NAMED) {
SimpleIdentifier paramId = param.identifier;
if (paramId != null) {
_addNamedParameterSuggestion(request, namedArgs, paramId.name);
}
}
}
}
void _addSuggestions(FormalParameterList parameters) {
if (parameters == null || parameters.parameters.length == 0) {
return;
}
Iterable<FormalParameter> requiredParam = parameters.parameters
.where((FormalParameter p) => p.kind == ParameterKind.REQUIRED);
int requiredCount = requiredParam.length;
if (requiredCount > 0 && _isEmptyArgList(request)) {
_addArgListSuggestion(requiredParam);
return;
}
if (_isAppendingToArgList(request)) {
if (requiredCount == 0 || requiredCount < _argCount(request)) {
_addDefaultParamSuggestions(parameters);
}
}
}
String _getParamType(FormalParameter param) {
TypeName type;
if (param is SimpleFormalParameter) {
type = param.type;
}
if (type != null) {
Identifier id = type.name;
if (id != null) {
String name = id.name;
if (name != null && name.length > 0) {
return name;
}
}
}
return 'dynamic';
}
}

View file

@ -0,0 +1,244 @@
// Copyright (c) 2014, 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.
library services.completion.contributor.dart.arglist;
import 'dart:async';
import 'package:analysis_server/src/protocol_server.dart'
hide Element, ElementKind;
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
/**
* Determine the number of arguments.
*/
int _argCount(DartCompletionRequest request) {
AstNode node = request.target.containingNode;
if (node is ArgumentList) {
return node.arguments.length;
}
return 0;
}
String _getParamType(ParameterElement param) {
DartType type = param.type;
if (type != null) {
return type.displayName;
}
return 'dynamic';
}
/**
* If the containing [node] is an argument list
* or named expression in an argument list
* then return the simple identifier for the method, constructor, or annotation
* to which the argument list is associated
*/
SimpleIdentifier _getTargetId(AstNode node) {
if (node is NamedExpression) {
return _getTargetId(node.parent);
}
if (node is ArgumentList) {
AstNode parent = node.parent;
if (parent is MethodInvocation) {
return parent.methodName;
}
if (parent is InstanceCreationExpression) {
ConstructorName constructorName = parent.constructorName;
if (constructorName != null) {
if (constructorName.name != null) {
return constructorName.name;
}
Identifier typeName = constructorName.type.name;
if (typeName is SimpleIdentifier) {
return typeName;
}
if (typeName is PrefixedIdentifier) {
return typeName.identifier;
}
}
}
if (parent is Annotation) {
return parent.constructorName ?? parent.name;
}
}
return null;
}
/**
* Determine if the completion target is at the end of the list of arguments.
*/
bool _isAppendingToArgList(DartCompletionRequest request) {
AstNode node = request.target.containingNode;
if (node is ArgumentList) {
var entity = request.target.entity;
if (entity == node.rightParenthesis) {
return true;
}
if (node.arguments.length > 0 && node.arguments.last == entity) {
return entity is SimpleIdentifier;
}
}
return false;
}
/**
* Determine if the completion target is an emtpy argument list.
*/
bool _isEmptyArgList(DartCompletionRequest request) {
AstNode node = request.target.containingNode;
return node is ArgumentList &&
node.leftParenthesis.next == node.rightParenthesis;
}
/**
* Return a collection of currently specified named arguments
*/
Iterable<String> _namedArgs(DartCompletionRequest request) {
AstNode node = request.target.containingNode;
List<String> namedArgs = new List<String>();
if (node is ArgumentList) {
for (Expression arg in node.arguments) {
if (arg is NamedExpression) {
namedArgs.add(arg.name.label.name);
}
}
}
return namedArgs;
}
/**
* A contributor for calculating `completion.getSuggestions` request results
* when the cursor position is inside the arguments to a method call.
*/
class ArgListContributor extends DartCompletionContributor {
DartCompletionRequest request;
List<CompletionSuggestion> suggestions;
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
this.request = request;
this.suggestions = <CompletionSuggestion>[];
// Determine if the target is in an argument list
// for a method or a constructor or an annotation
// and resolve the identifier
SimpleIdentifier targetId = _getTargetId(request.target.containingNode);
if (targetId == null) {
return EMPTY_LIST;
}
// Resolve the target expression to determine the arguments
await request.resolveIdentifier(targetId);
// Gracefully degrade if the element could not be resolved
// e.g. target changed, completion aborted
targetId = _getTargetId(request.target.containingNode);
if (targetId == null) {
return EMPTY_LIST;
}
Element elem = targetId.bestElement;
if (elem == null) {
return EMPTY_LIST;
}
// Generate argument list suggestion based upon the type of element
if (elem is ClassElement) {
for (ConstructorElement constructor in elem.constructors) {
if (!constructor.isFactory) {
_addSuggestions(constructor.parameters);
return suggestions;
}
}
}
if (elem is ConstructorElement) {
_addSuggestions(elem.parameters);
return suggestions;
}
if (elem is FunctionElement) {
_addSuggestions(elem.parameters);
return suggestions;
}
if (elem is MethodElement) {
_addSuggestions(elem.parameters);
return suggestions;
}
print('${elem.runtimeType} :: $elem');
return EMPTY_LIST;
}
void _addArgListSuggestion(Iterable<ParameterElement> requiredParam) {
StringBuffer completion = new StringBuffer('(');
List<String> paramNames = new List<String>();
List<String> paramTypes = new List<String>();
for (ParameterElement param in requiredParam) {
String name = param.name;
if (name != null && name.length > 0) {
if (completion.length > 1) {
completion.write(', ');
}
completion.write(name);
paramNames.add(name);
paramTypes.add(_getParamType(param));
}
}
completion.write(')');
CompletionSuggestion suggestion = new CompletionSuggestion(
CompletionSuggestionKind.ARGUMENT_LIST,
DART_RELEVANCE_HIGH,
completion.toString(),
completion.length,
0,
false,
false);
suggestion.parameterNames = paramNames;
suggestion.parameterTypes = paramTypes;
suggestions.add(suggestion);
}
void _addDefaultParamSuggestions(Iterable<ParameterElement> parameters) {
Iterable<String> namedArgs = _namedArgs(request);
for (ParameterElement param in parameters) {
if (param.parameterKind == ParameterKind.NAMED) {
_addNamedParameterSuggestion(request, namedArgs, param.name);
}
}
}
void _addNamedParameterSuggestion(
DartCompletionRequest request, List<String> namedArgs, String name) {
if (name != null && name.length > 0 && !namedArgs.contains(name)) {
suggestions.add(new CompletionSuggestion(
CompletionSuggestionKind.NAMED_ARGUMENT,
DART_RELEVANCE_NAMED_PARAMETER,
'$name: ',
name.length + 2,
0,
false,
false));
}
}
void _addSuggestions(Iterable<ParameterElement> parameters) {
if (parameters == null || parameters.length == 0) {
return;
}
Iterable<ParameterElement> requiredParam = parameters.where(
(ParameterElement p) => p.parameterKind == ParameterKind.REQUIRED);
int requiredCount = requiredParam.length;
if (requiredCount > 0 && _isEmptyArgList(request)) {
_addArgListSuggestion(requiredParam);
return;
}
if (_isAppendingToArgList(request)) {
if (requiredCount == 0 || requiredCount < _argCount(request)) {
_addDefaultParamSuggestions(parameters);
}
}
}
}

View file

@ -89,6 +89,15 @@ class DartCompletionRequestImpl extends CompletionRequestImpl
int offset)
: super(context, resourceProvider, searchEngine, source, offset);
@override
CompletionTarget get target {
if (_target == null) {
CompilationUnit unit = context.computeResult(source, PARSED_UNIT);
_target = new CompletionTarget.forOffset(unit, offset);
}
return _target;
}
@override
Future<CompilationUnit> resolveDeclarationsInScope() async {
CompilationUnit unit = target.unit;
@ -131,11 +140,46 @@ class DartCompletionRequestImpl extends CompletionRequestImpl
}
@override
CompletionTarget get target {
if (_target == null) {
CompilationUnit unit = context.computeResult(source, PARSED_UNIT);
_target = new CompletionTarget.forOffset(unit, offset);
Future resolveIdentifier(SimpleIdentifier identifier) async {
if (identifier.bestElement != null) {
return;
}
return _target;
//TODO(danrubel) resolve the expression or containing method
// rather than the entire complilation unit
CompilationUnit unit = target.unit;
// Determine the library source
Source librarySource;
if (unit.directives.any((d) => d is PartOfDirective)) {
List<Source> libraries = context.getLibrariesContaining(source);
if (libraries.isEmpty) {
return;
}
librarySource = libraries[0];
} else {
librarySource = source;
}
// Resolve declarations in the target unit
CompilationUnit resolvedUnit =
await new AnalysisFutureHelper<CompilationUnit>(
context,
new LibrarySpecificUnit(librarySource, source),
RESOLVED_UNIT).computeAsync();
// TODO(danrubel) determine if the underlying source has been modified
// in a way that invalidates the completion request
// and return null
// Gracefully degrade if unit cannot be resolved
if (resolvedUnit == null) {
return;
}
// Recompute the target for the newly resolved unit
_target = new CompletionTarget.forOffset(resolvedUnit, offset);
_haveResolveDeclarationsInScope = true;
}
}

View file

@ -10,7 +10,6 @@ import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:analysis_server/src/provisional/completion/completion_core.dart'
show AnalysisRequest, CompletionContributor, CompletionRequest;
import 'package:analysis_server/src/provisional/completion/dart/completion_target.dart';
import 'package:analysis_server/src/services/completion/arglist_contributor.dart';
import 'package:analysis_server/src/services/completion/combinator_contributor.dart';
import 'package:analysis_server/src/services/completion/completion_core.dart';
import 'package:analysis_server/src/services/completion/completion_manager.dart';
@ -100,7 +99,7 @@ class DartCompletionManager extends CompletionManager {
new LocalReferenceContributor(),
new ImportedReferenceContributor(),
//new KeywordContributor(),
new ArgListContributor(),
//new ArgListContributor(),
new CombinatorContributor(),
new PrefixedElementContributor(),
new UriContributor(),
@ -110,10 +109,7 @@ class DartCompletionManager extends CompletionManager {
];
}
if (newContributors == null) {
newContributors = <CompletionContributor>[
// TODO(danrubel) initialize using plugin API
//new newImpl.DartCompletionManager(),
];
newContributors = <CompletionContributor>[];
}
if (contributionSorter == null) {
contributionSorter = defaultContributionSorter;

View file

@ -5,13 +5,13 @@
library test.services.completion.dart.arglist;
import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:analysis_server/src/services/completion/arglist_contributor.dart';
import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/arglist_contributor.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:unittest/unittest.dart';
import '../../utils.dart';
import 'completion_test_util.dart';
import '../../../utils.dart';
import 'completion_contributor_util.dart';
main() {
initializeTestEnvironment();
@ -19,9 +19,9 @@ main() {
}
@reflectiveTest
class ArgListContributorTest extends AbstractCompletionTest {
class ArgListContributorTest extends DartCompletionContributorTest {
void assertNoOtherSuggestions(Iterable<CompletionSuggestion> expected) {
for (CompletionSuggestion suggestion in request.suggestions) {
for (CompletionSuggestion suggestion in suggestions) {
if (!expected.contains(suggestion)) {
failedCompletion('did not expect completion: '
'${suggestion.completion}\n $suggestion');
@ -34,7 +34,7 @@ class ArgListContributorTest extends AbstractCompletionTest {
CompletionSuggestionKind csKind = CompletionSuggestionKind.ARGUMENT_LIST;
CompletionSuggestion cs = getSuggest(csKind: csKind);
if (cs == null) {
failedCompletion('expected completion $csKind', request.suggestions);
failedCompletion('expected completion $csKind', suggestions);
}
assertSuggestArgumentList_params(
paramNames, paramTypes, cs.parameterNames, cs.parameterTypes);
@ -86,59 +86,51 @@ class ArgListContributorTest extends AbstractCompletionTest {
}
@override
void setUpContributor() {
contributor = new ArgListContributor();
DartCompletionContributor createContributor() {
return new ArgListContributor();
}
test_Annotation_local_constructor_named_param() {
test_Annotation_local_constructor_named_param() async {
addTestSource('''
class A { A({int one, String two: 'defaultValue'}) { } }
@A(^) main() { }''');
computeFast();
return computeFull((bool result) {
assertSuggestArguments(namedArguments: ['one', 'two']);
});
await computeSuggestions();
assertSuggestArguments(namedArguments: ['one', 'two']);
}
test_Annotation_imported_constructor_named_param() {
addSource('/libA.dart', '''
test_Annotation_imported_constructor_named_param() async {
addSource(
'/libA.dart',
'''
library libA; class A { A({int one, String two: 'defaultValue'}) { } }''');
addTestSource('import "/libA.dart"; @A(^) main() { }');
computeFast();
return computeFull((bool result) {
assertSuggestArguments(namedArguments: ['one','two']);
});
await computeSuggestions();
assertSuggestArguments(namedArguments: ['one', 'two']);
}
test_ArgumentList_getter() {
test_ArgumentList_getter() async {
addTestSource('class A {int get foo => 7; main() {foo(^)}');
computeFast();
return computeFull((bool result) {
assertNoSuggestions();
});
await computeSuggestions();
assertNoSuggestions();
}
test_ArgumentList_imported_constructor_named_param() {
test_ArgumentList_imported_constructor_named_param() async {
//
addSource('/libA.dart', 'library libA; class A{A({int one}){}}');
addTestSource('import "/libA.dart"; main() { new A(^);}');
computeFast();
return computeFull((bool result) {
assertSuggestArguments(namedArguments: ['one']);
});
await computeSuggestions();
assertSuggestArguments(namedArguments: ['one']);
}
test_ArgumentList_imported_constructor_named_param2() {
test_ArgumentList_imported_constructor_named_param2() async {
//
addSource('/libA.dart', 'library libA; class A{A.foo({int one}){}}');
addTestSource('import "/libA.dart"; main() { new A.foo(^);}');
computeFast();
return computeFull((bool result) {
assertSuggestArguments(namedArguments: ['one']);
});
await computeSuggestions();
assertSuggestArguments(namedArguments: ['one']);
}
test_ArgumentList_imported_function_0() {
test_ArgumentList_imported_function_0() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addSource(
'/libA.dart',
@ -152,13 +144,11 @@ library libA; class A { A({int one, String two: 'defaultValue'}) { } }''');
class B { }
String bar() => true;
void main() {expect(a^)}''');
computeFast();
return computeFull((bool result) {
assertNoSuggestions();
});
await computeSuggestions();
assertNoSuggestions();
}
test_ArgumentList_imported_function_1() {
test_ArgumentList_imported_function_1() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addSource(
'/libA.dart',
@ -172,13 +162,11 @@ library libA; class A { A({int one, String two: 'defaultValue'}) { } }''');
class B { }
String bar() => true;
void main() {expect(^)}''');
computeFast();
return computeFull((bool result) {
assertSuggestArgumentList(['arg'], ['String']);
});
await computeSuggestions();
assertSuggestArgumentList(['arg'], ['String']);
}
test_ArgumentList_imported_function_2() {
test_ArgumentList_imported_function_2() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addSource(
'/libA.dart',
@ -192,13 +180,11 @@ library libA; class A { A({int one, String two: 'defaultValue'}) { } }''');
class B { }
String bar() => true;
void main() {expect(^)}''');
computeFast();
return computeFull((bool result) {
assertSuggestArgumentList(['arg1', 'arg2'], ['String', 'int']);
});
await computeSuggestions();
assertSuggestArgumentList(['arg1', 'arg2'], ['String', 'int']);
}
test_ArgumentList_imported_function_3() {
test_ArgumentList_imported_function_3() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addSource(
'/libA.dart',
@ -212,13 +198,11 @@ library libA; class A { A({int one, String two: 'defaultValue'}) { } }''');
class B { }
String bar() => true;
void main() {expect(^)}''');
computeFast();
return computeFull((bool result) {
assertSuggestArgumentList(['arg1', 'arg2'], ['String', 'int']);
});
await computeSuggestions();
assertSuggestArgumentList(['arg1', 'arg2'], ['String', 'int']);
}
test_ArgumentList_imported_function_3a() {
test_ArgumentList_imported_function_3a() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addSource(
'/libA.dart',
@ -232,13 +216,11 @@ library libA; class A { A({int one, String two: 'defaultValue'}) { } }''');
class B { }
String bar() => true;
void main() {expect('hello', ^)}''');
computeFast();
return computeFull((bool result) {
assertNoSuggestions();
});
await computeSuggestions();
assertNoSuggestions();
}
test_ArgumentList_imported_function_3b() {
test_ArgumentList_imported_function_3b() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addSource(
'/libA.dart',
@ -252,13 +234,11 @@ library libA; class A { A({int one, String two: 'defaultValue'}) { } }''');
class B { }
String bar() => true;
void main() {expect('hello', ^x)}''');
computeFast();
return computeFull((bool result) {
assertNoSuggestions();
});
await computeSuggestions();
assertNoSuggestions();
}
test_ArgumentList_imported_function_3c() {
test_ArgumentList_imported_function_3c() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addSource(
'/libA.dart',
@ -272,13 +252,11 @@ library libA; class A { A({int one, String two: 'defaultValue'}) { } }''');
class B { }
String bar() => true;
void main() {expect('hello', x^)}''');
computeFast();
return computeFull((bool result) {
assertNoSuggestions();
});
await computeSuggestions();
assertNoSuggestions();
}
test_ArgumentList_imported_function_3d() {
test_ArgumentList_imported_function_3d() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addSource(
'/libA.dart',
@ -292,71 +270,57 @@ library libA; class A { A({int one, String two: 'defaultValue'}) { } }''');
class B { }
String bar() => true;
void main() {expect('hello', x ^)}''');
computeFast();
return computeFull((bool result) {
assertNoSuggestions();
});
await computeSuggestions();
assertNoSuggestions();
}
test_ArgumentList_imported_function_named_param() {
test_ArgumentList_imported_function_named_param() async {
//
addTestSource('main() { int.parse("16", ^);}');
computeFast();
return computeFull((bool result) {
assertSuggestArguments(namedArguments: ['radix', 'onError']);
});
await computeSuggestions();
assertSuggestArguments(namedArguments: ['radix', 'onError']);
}
test_ArgumentList_imported_function_named_param1() {
test_ArgumentList_imported_function_named_param1() async {
//
addTestSource('main() { int.parse("16", r^);}');
computeFast();
return computeFull((bool result) {
assertSuggestArguments(namedArguments: ['radix', 'onError']);
});
await computeSuggestions();
assertSuggestArguments(namedArguments: ['radix', 'onError']);
}
test_ArgumentList_imported_function_named_param2() {
test_ArgumentList_imported_function_named_param2() async {
//
addTestSource('main() { int.parse("16", radix: 7, ^);}');
computeFast();
return computeFull((bool result) {
assertSuggestArguments(namedArguments: ['onError']);
});
await computeSuggestions();
assertSuggestArguments(namedArguments: ['onError']);
}
test_ArgumentList_imported_function_named_param2a() {
test_ArgumentList_imported_function_named_param2a() async {
//
addTestSource('main() { int.parse("16", radix: ^);}');
computeFast();
return computeFull((bool result) {
assertNoSuggestions();
});
await computeSuggestions();
assertNoSuggestions();
}
test_ArgumentList_local_constructor_named_param() {
test_ArgumentList_local_constructor_named_param() async {
//
addTestSource('''
class A { A({int one, String two: 'defaultValue'}) { } }
main() { new A(^);}''');
computeFast();
return computeFull((bool result) {
assertSuggestArguments(namedArguments: ['one', 'two']);
});
await computeSuggestions();
assertSuggestArguments(namedArguments: ['one', 'two']);
}
test_ArgumentList_local_constructor_named_param2() {
test_ArgumentList_local_constructor_named_param2() async {
//
addTestSource('''
class A { A.foo({int one, String two: 'defaultValue'}) { } }
main() { new A.foo(^);}''');
computeFast();
return computeFull((bool result) {
assertSuggestArguments(namedArguments: ['one', 'two']);
});
await computeSuggestions();
assertSuggestArguments(namedArguments: ['one', 'two']);
}
test_ArgumentList_local_function_1() {
test_ArgumentList_local_function_1() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addTestSource('''
import '/libA.dart'
@ -364,13 +328,11 @@ main() { new A.foo(^);}''');
class B { }
String bar() => true;
void main() {expect(^)}''');
computeFast();
return computeFull((bool result) {
assertSuggestArgumentList(['arg'], ['dynamic']);
});
await computeSuggestions();
assertSuggestArgumentList(['arg'], ['dynamic']);
}
test_ArgumentList_local_function_2() {
test_ArgumentList_local_function_2() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addTestSource('''
import '/libA.dart'
@ -378,13 +340,11 @@ main() { new A.foo(^);}''');
class B { }
String bar() => true;
void main() {expect(^)}''');
computeFast();
return computeFull((bool result) {
assertSuggestArgumentList(['arg1', 'arg2'], ['dynamic', 'int']);
});
await computeSuggestions();
assertSuggestArgumentList(['arg1', 'arg2'], ['dynamic', 'int']);
}
test_ArgumentList_local_function_3() {
test_ArgumentList_local_function_3() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addTestSource('''
import '/libA.dart'
@ -392,13 +352,11 @@ main() { new A.foo(^);}''');
class B { }
String bar() => true;
void main() {expect(^)}''');
computeFast();
return computeFull((bool result) {
assertSuggestArgumentList(['arg1', 'arg2'], ['dynamic', 'int']);
});
await computeSuggestions();
assertSuggestArgumentList(['arg1', 'arg2'], ['dynamic', 'int']);
}
test_ArgumentList_local_function_3a() {
test_ArgumentList_local_function_3a() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addTestSource('''
import '/libA.dart'
@ -406,13 +364,11 @@ main() { new A.foo(^);}''');
class B { }
String bar() => true;
void main() {expect('hello', ^)}''');
computeFast();
return computeFull((bool result) {
assertNoSuggestions();
});
await computeSuggestions();
assertNoSuggestions();
}
test_ArgumentList_local_function_3b() {
test_ArgumentList_local_function_3b() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addTestSource('''
import '/libA.dart'
@ -420,13 +376,11 @@ main() { new A.foo(^);}''');
class B { }
String bar() => true;
void main() {expect('hello', ^x)}''');
computeFast();
return computeFull((bool result) {
assertNoSuggestions();
});
await computeSuggestions();
assertNoSuggestions();
}
test_ArgumentList_local_function_3c() {
test_ArgumentList_local_function_3c() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addTestSource('''
import '/libA.dart'
@ -434,13 +388,11 @@ main() { new A.foo(^);}''');
class B { }
String bar() => true;
void main() {expect('hello', x^)}''');
computeFast();
return computeFull((bool result) {
assertNoSuggestions();
});
await computeSuggestions();
assertNoSuggestions();
}
test_ArgumentList_local_function_3d() {
test_ArgumentList_local_function_3d() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addTestSource('''
import '/libA.dart'
@ -448,57 +400,47 @@ main() { new A.foo(^);}''');
class B { }
String bar() => true;
void main() {expect('hello', x ^)}''');
computeFast();
return computeFull((bool result) {
assertNoSuggestions();
});
await computeSuggestions();
assertNoSuggestions();
}
test_ArgumentList_local_function_named_param() {
test_ArgumentList_local_function_named_param() async {
//
addTestSource('''
f(v,{int radix, int onError(String s)}){}
main() { f("16", ^);}''');
computeFast();
return computeFull((bool result) {
assertSuggestArguments(namedArguments: ['radix', 'onError']);
});
await computeSuggestions();
assertSuggestArguments(namedArguments: ['radix', 'onError']);
}
test_ArgumentList_local_function_named_param1() {
test_ArgumentList_local_function_named_param1() async {
//
addTestSource('''
f(v,{int radix, int onError(String s)}){}
main() { f("16", r^);}''');
computeFast();
return computeFull((bool result) {
assertSuggestArguments(namedArguments: ['radix', 'onError']);
});
await computeSuggestions();
assertSuggestArguments(namedArguments: ['radix', 'onError']);
}
test_ArgumentList_local_function_named_param2() {
test_ArgumentList_local_function_named_param2() async {
//
addTestSource('''
f(v,{int radix, int onError(String s)}){}
main() { f("16", radix: 7, ^);}''');
computeFast();
return computeFull((bool result) {
assertSuggestArguments(namedArguments: ['onError']);
});
await computeSuggestions();
assertSuggestArguments(namedArguments: ['onError']);
}
test_ArgumentList_local_function_named_param2a() {
test_ArgumentList_local_function_named_param2a() async {
//
addTestSource('''
f(v,{int radix, int onError(String s)}){}
main() { f("16", radix: ^);}''');
computeFast();
return computeFull((bool result) {
assertNoSuggestions();
});
await computeSuggestions();
assertNoSuggestions();
}
test_ArgumentList_local_method_0() {
test_ArgumentList_local_method_0() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addSource(
'/libA.dart',
@ -512,13 +454,11 @@ main() { f("16", radix: ^);}''');
expect() { }
void foo() {expect(^)}}
String bar() => true;''');
computeFast();
return computeFull((bool result) {
assertNoSuggestions();
});
await computeSuggestions();
assertNoSuggestions();
}
test_ArgumentList_local_method_2() {
test_ArgumentList_local_method_2() async {
// ArgumentList MethodInvocation ExpressionStatement Block
addSource(
'/libA.dart',
@ -532,9 +472,7 @@ main() { f("16", radix: ^);}''');
expect(arg, int blat) { }
void foo() {expect(^)}}
String bar() => true;''');
computeFast();
return computeFull((bool result) {
assertSuggestArgumentList(['arg', 'blat'], ['dynamic', 'int']);
});
await computeSuggestions();
assertSuggestArgumentList(['arg', 'blat'], ['dynamic', 'int']);
}
}

View file

@ -61,6 +61,21 @@ abstract class DartCompletionContributorTest extends AbstractContextTest {
expect(suggestion.hasNamedParameters, isNotNull);
}
void assertNoSuggestions({CompletionSuggestionKind kind: null}) {
if (kind == null) {
if (suggestions.length > 0) {
failedCompletion('Expected no suggestions', suggestions);
}
return;
}
CompletionSuggestion suggestion = suggestions.firstWhere(
(CompletionSuggestion cs) => cs.kind == kind,
orElse: () => null);
if (suggestion != null) {
failedCompletion('did not expect completion: $completion\n $suggestion');
}
}
void assertNotSuggested(String completion) {
CompletionSuggestion suggestion = suggestions.firstWhere(
(CompletionSuggestion cs) => cs.completion == completion,

View file

@ -7,6 +7,7 @@ library test.services.completion.dart;
import 'package:unittest/unittest.dart';
import '../../../utils.dart';
import 'arglist_contributor_test.dart' as arglist_test;
import 'common_usage_sorter_test.dart' as common_usage_test;
import 'inherited_contributor_test.dart' as inherited_contributor_test;
import 'keyword_contributor_test.dart' as keyword_test;
@ -15,6 +16,7 @@ import 'keyword_contributor_test.dart' as keyword_test;
main() {
initializeTestEnvironment();
group('dart/completion', () {
arglist_test.main();
common_usage_test.main();
inherited_contributor_test.main();
keyword_test.main();

View file

@ -7,7 +7,6 @@ library test.services.completion;
import 'package:unittest/unittest.dart';
import '../../utils.dart';
import 'arglist_contributor_test.dart' as arglist_test;
import 'combinator_contributor_test.dart' as combinator_test;
import 'completion_computer_test.dart' as completion_computer_test;
import 'completion_manager_test.dart' as completion_manager_test;
@ -25,7 +24,6 @@ import 'uri_contributor_test.dart' as uri_contributor_test;
main() {
initializeTestEnvironment();
group('completion', () {
arglist_test.main();
combinator_test.main();
completion_computer_test.main();
completion_manager_test.main();