mirror of
https://github.com/dart-lang/sdk
synced 2024-09-22 00:21:20 +00:00
rework ArgListContributor to use new task model
R=scheglov@google.com Review URL: https://codereview.chromium.org/1500793003 .
This commit is contained in:
parent
7dfb517618
commit
4379efb6b4
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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']);
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue