Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(340)

Unified Diff: pkg/analysis_server/lib/src/services/completion/local_computer.dart

Issue 972933002: add arguments to constructor completions (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: fix tests Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analysis_server/lib/src/services/completion/local_computer.dart
diff --git a/pkg/analysis_server/lib/src/services/completion/local_computer.dart b/pkg/analysis_server/lib/src/services/completion/local_computer.dart
index b907d50f930d4663ec9f67a655c6fe672e81b779..7fc7ce6b4bc7df47171794a57f6c6b5abecfd01b 100644
--- a/pkg/analysis_server/lib/src/services/completion/local_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/local_computer.dart
@@ -16,6 +16,66 @@ import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
+const _DYNAMIC = 'dynamic';
+
+final TypeName _NO_RETURN_TYPE = new TypeName(
+ new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, '', 0)), null);
+
+/**
+ * Create a new protocol Element for inclusion in a completion suggestion.
+ */
+protocol.Element _createElement(protocol.ElementKind kind, SimpleIdentifier id,
+ {String parameters, TypeName returnType, bool isAbstract: false,
+ bool isDeprecated: false}) {
+ String name = id != null ? id.name : '';
+ int flags = protocol.Element.makeFlags(
+ isAbstract: isAbstract,
+ isDeprecated: isDeprecated,
+ isPrivate: Identifier.isPrivateName(name));
+ return new protocol.Element(kind, name, flags,
+ parameters: parameters, returnType: _nameForType(returnType));
+}
+
+/**
+ * Return `true` if the @deprecated annotation is present
+ */
+bool _isDeprecated(AnnotatedNode node) {
+ if (node != null) {
+ NodeList<Annotation> metadata = node.metadata;
+ if (metadata != null) {
+ return metadata.any((Annotation a) {
+ return a.name is SimpleIdentifier && a.name.name == 'deprecated';
+ });
+ }
+ }
+ return false;
+}
+
+/**
+ * Return the name for the given type.
+ */
+String _nameForType(TypeName type) {
+ if (type == _NO_RETURN_TYPE) {
+ return null;
+ }
+ if (type == null) {
+ return _DYNAMIC;
+ }
+ Identifier id = type.name;
+ if (id == null) {
+ return _DYNAMIC;
+ }
+ String name = id.name;
+ if (name == null || name.length <= 0) {
+ return _DYNAMIC;
+ }
+ TypeArgumentList typeArgs = type.typeArguments;
+ if (typeArgs != null) {
+ //TODO (danrubel) include type arguments
+ }
+ return name;
+}
+
/**
* A computer for calculating `completion.getSuggestions` request results
* for the local library in which the completion is requested.
@@ -24,13 +84,13 @@ class LocalComputer extends DartCompletionComputer {
@override
bool computeFast(DartCompletionRequest request) {
OpType optype = request.optype;
+
+ // Collect suggestions from the specific child [AstNode] that contains
+ // the completion offset and all of its parents recursively.
if (optype.includeTopLevelSuggestions) {
_LocalVisitor localVisitor = new _LocalVisitor(request, request.offset,
optype.includeOnlyTypeNameSuggestions,
!optype.includeVoidReturnSuggestions);
-
- // Collect suggestions from the specific child [AstNode] that contains
- // the completion offset and all of its parents recursively.
localVisitor.visit(request.node);
}
if (optype.includeStatementLabelSuggestions ||
@@ -40,6 +100,9 @@ class LocalComputer extends DartCompletionComputer {
optype.includeCaseLabelSuggestions);
labelVisitor.visit(request.node);
}
+ if (optype.includeConstructorSuggestions) {
+ new _ConstructorVisitor(request).visit(request.node);
+ }
// If the unit is not a part and does not reference any parts
// then work is complete
@@ -56,6 +119,183 @@ class LocalComputer extends DartCompletionComputer {
}
/**
+ * A visitor for collecting constructor suggestions.
+ */
+class _ConstructorVisitor extends LocalDeclarationVisitor {
+ final DartCompletionRequest request;
+
+ _ConstructorVisitor(DartCompletionRequest request)
+ : super(request.offset),
+ request = request;
+
+ @override
+ void declaredClass(ClassDeclaration declaration) {
+ bool found = false;
+ for (ClassMember member in declaration.members) {
+ if (member is ConstructorDeclaration) {
+ found = true;
+ _addSuggestion(declaration, member);
+ }
+ }
+ if (!found) {
+ _addSuggestion(declaration, null);
+ }
+ }
+
+ @override
+ void declaredClassTypeAlias(ClassTypeAlias declaration) {
+ // TODO: implement declaredClassTypeAlias
+ }
+
+ @override
+ void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
+ // TODO: implement declaredField
+ }
+
+ @override
+ void declaredFunction(FunctionDeclaration declaration) {
+ // TODO: implement declaredFunction
+ }
+
+ @override
+ void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {
+ // TODO: implement declaredFunctionTypeAlias
+ }
+
+ @override
+ void declaredLabel(Label label, bool isCaseLabel) {
+ // TODO: implement declaredLabel
+ }
+
+ @override
+ void declaredLocalVar(SimpleIdentifier name, TypeName type) {
+ // TODO: implement declaredLocalVar
+ }
+
+ @override
+ void declaredMethod(MethodDeclaration declaration) {
+ // TODO: implement declaredMethod
+ }
+
+ @override
+ void declaredParam(SimpleIdentifier name, TypeName type) {
+ // TODO: implement declaredParam
+ }
+
+ @override
+ void declaredTopLevelVar(
+ VariableDeclarationList varList, VariableDeclaration varDecl) {
+ // TODO: implement declaredTopLevelVar
+ }
+
+ /**
+ * For the given class and constructor,
+ * add a suggestion of the form B(...) or B.name(...).
+ * If the given constructor is `null`
+ * then add a default constructor suggestion.
+ */
+ CompletionSuggestion _addSuggestion(
+ ClassDeclaration classDecl, ConstructorDeclaration constructorDecl) {
+ String completion = classDecl.name.name;
+ if (constructorDecl != null) {
+ SimpleIdentifier elemId = constructorDecl.name;
+ if (elemId != null) {
+ String name = elemId.name;
+ if (name != null && name.length > 0) {
+ completion = '$completion.$name';
+ }
+ }
+ }
+ bool isDeprecated =
+ constructorDecl != null && _isDeprecated(constructorDecl);
+ List<String> parameterNames = new List<String>();
+ List<String> parameterTypes = new List<String>();
+ int requiredParameterCount = 0;
+ bool hasNamedParameters = false;
+ StringBuffer paramBuf = new StringBuffer();
+ paramBuf.write('(');
+ int paramCount = 0;
+ if (constructorDecl != null) {
+ for (FormalParameter param in constructorDecl.parameters.parameters) {
+ if (paramCount > 0) {
+ paramBuf.write(', ');
+ }
+ String paramName;
+ String typeName;
+ if (param is NormalFormalParameter) {
+ paramName = param.identifier.name;
+ typeName = _nameForParamType(param);
+ ++requiredParameterCount;
+ } else if (param is DefaultFormalParameter) {
+ NormalFormalParameter childParam = param.parameter;
+ paramName = childParam.identifier.name;
+ typeName = _nameForParamType(childParam);
+ if (param.kind == ParameterKind.NAMED) {
+ hasNamedParameters = true;
+ }
+ if (paramCount == requiredParameterCount) {
+ paramBuf.write(hasNamedParameters ? '{' : '[');
+ }
+ }
+ parameterNames.add(paramName);
+ parameterTypes.add(typeName);
+ paramBuf.write(typeName);
+ paramBuf.write(' ');
+ paramBuf.write(paramName);
+ ++paramCount;
+ }
+ }
+ if (paramCount > requiredParameterCount) {
+ paramBuf.write(hasNamedParameters ? '}' : ']');
+ }
+ paramBuf.write(')');
+ protocol.Element element = _createElement(
+ protocol.ElementKind.CONSTRUCTOR, null,
+ parameters: paramBuf.toString());
+ element.name = completion;
+ element.returnType = classDecl.name.name;
+ CompletionSuggestion suggestion = new CompletionSuggestion(
+ CompletionSuggestionKind.INVOCATION,
+ isDeprecated ? DART_RELEVANCE_LOW : DART_RELEVANCE_DEFAULT, completion,
+ completion.length, 0, isDeprecated, false,
+ declaringType: classDecl.name.name,
+ element: element,
+ parameterNames: parameterNames,
+ parameterTypes: parameterTypes,
+ requiredParameterCount: requiredParameterCount,
+ hasNamedParameters: hasNamedParameters);
+ request.suggestions.add(suggestion);
+ return suggestion;
+ }
+
+ /**
+ * Determine the name of the type for the given constructor parameter.
+ */
+ String _nameForParamType(NormalFormalParameter param) {
+ if (param is SimpleFormalParameter) {
+ return _nameForType(param.type);
+ }
+ SimpleIdentifier id = param.identifier;
+ if (param is FieldFormalParameter && id != null) {
+ String fieldName = id.name;
+ AstNode classDecl = param.getAncestor((p) => p is ClassDeclaration);
+ if (classDecl is ClassDeclaration) {
+ for (ClassMember member in classDecl.members) {
+ if (member is FieldDeclaration) {
+ for (VariableDeclaration field in member.fields.variables) {
+ if (field.name.name == fieldName) {
+ return _nameForType(member.fields.type);
+ }
+ }
+ }
+ }
+ }
+ }
+ return _DYNAMIC;
+ }
+}
+
+/**
* A visitor for collecting suggestions for break and continue labels.
*/
class _LabelVisitor extends LocalDeclarationVisitor {
@@ -178,11 +418,6 @@ class _LabelVisitor extends LocalDeclarationVisitor {
* that contains the completion offset to the [CompilationUnit].
*/
class _LocalVisitor extends LocalDeclarationVisitor {
- static const DYNAMIC = 'dynamic';
-
- static final TypeName NO_RETURN_TYPE = new TypeName(
- new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, '', 0)), null);
-
final DartCompletionRequest request;
final bool typesOnly;
final bool excludeVoidReturn;
@@ -194,12 +429,12 @@ class _LocalVisitor extends LocalDeclarationVisitor {
@override
void declaredClass(ClassDeclaration declaration) {
bool isDeprecated = _isDeprecated(declaration);
- CompletionSuggestion suggestion = _addSuggestion(
- declaration.name, NO_RETURN_TYPE, isDeprecated, DART_RELEVANCE_DEFAULT);
+ CompletionSuggestion suggestion = _addSuggestion(declaration.name,
+ _NO_RETURN_TYPE, isDeprecated, DART_RELEVANCE_DEFAULT);
if (suggestion != null) {
suggestion.element = _createElement(
protocol.ElementKind.CLASS, declaration.name,
- returnType: NO_RETURN_TYPE,
+ returnType: _NO_RETURN_TYPE,
isAbstract: declaration.isAbstract,
isDeprecated: isDeprecated);
}
@@ -208,12 +443,12 @@ class _LocalVisitor extends LocalDeclarationVisitor {
@override
void declaredClassTypeAlias(ClassTypeAlias declaration) {
bool isDeprecated = _isDeprecated(declaration);
- CompletionSuggestion suggestion = _addSuggestion(
- declaration.name, NO_RETURN_TYPE, isDeprecated, DART_RELEVANCE_DEFAULT);
+ CompletionSuggestion suggestion = _addSuggestion(declaration.name,
+ _NO_RETURN_TYPE, isDeprecated, DART_RELEVANCE_DEFAULT);
if (suggestion != null) {
suggestion.element = _createElement(
protocol.ElementKind.CLASS_TYPE_ALIAS, declaration.name,
- returnType: NO_RETURN_TYPE,
+ returnType: _NO_RETURN_TYPE,
isAbstract: true,
isDeprecated: isDeprecated);
}
@@ -253,7 +488,7 @@ class _LocalVisitor extends LocalDeclarationVisitor {
return;
}
kind = protocol.ElementKind.SETTER;
- returnType = NO_RETURN_TYPE;
+ returnType = _NO_RETURN_TYPE;
defaultRelevance = DART_RELEVANCE_LOCAL_ACCESSOR;
} else {
if (excludeVoidReturn && _isVoid(returnType)) {
@@ -327,7 +562,7 @@ class _LocalVisitor extends LocalDeclarationVisitor {
return;
}
kind = protocol.ElementKind.SETTER;
- returnType = NO_RETURN_TYPE;
+ returnType = _NO_RETURN_TYPE;
defaultRelevance = DART_RELEVANCE_LOCAL_ACCESSOR;
} else {
if (excludeVoidReturn && _isVoid(returnType)) {
@@ -444,36 +679,6 @@ class _LocalVisitor extends LocalDeclarationVisitor {
return null;
}
- /**
- * Create a new protocol Element for inclusion in a completion suggestion.
- */
- protocol.Element _createElement(
- protocol.ElementKind kind, SimpleIdentifier id, {String parameters,
- TypeName returnType, bool isAbstract: false, bool isDeprecated: false}) {
- String name = id.name;
- int flags = protocol.Element.makeFlags(
- isAbstract: isAbstract,
- isDeprecated: isDeprecated,
- isPrivate: Identifier.isPrivateName(name));
- return new protocol.Element(kind, name, flags,
- parameters: parameters, returnType: _nameForType(returnType));
- }
-
- /**
- * Return `true` if the @deprecated annotation is present
- */
- bool _isDeprecated(AnnotatedNode node) {
- if (node != null) {
- NodeList<Annotation> metadata = node.metadata;
- if (metadata != null) {
- return metadata.any((Annotation a) {
- return a.name is SimpleIdentifier && a.name.name == 'deprecated';
- });
- }
- }
- return false;
- }
-
bool _isVoid(TypeName returnType) {
if (returnType != null) {
Identifier id = returnType.name;
@@ -483,29 +688,4 @@ class _LocalVisitor extends LocalDeclarationVisitor {
}
return false;
}
-
- /**
- * Return the name for the given type.
- */
- String _nameForType(TypeName type) {
- if (type == NO_RETURN_TYPE) {
- return null;
- }
- if (type == null) {
- return DYNAMIC;
- }
- Identifier id = type.name;
- if (id == null) {
- return DYNAMIC;
- }
- String name = id.name;
- if (name == null || name.length <= 0) {
- return DYNAMIC;
- }
- TypeArgumentList typeArgs = type.typeArguments;
- if (typeArgs != null) {
- //TODO (danrubel) include type arguments
- }
- return name;
- }
}

Powered by Google App Engine
This is Rietveld 408576698