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

Side by Side 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, 9 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library services.completion.computer.dart.local; 5 library services.completion.computer.dart.local;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'package:analysis_server/src/protocol.dart' as protocol 9 import 'package:analysis_server/src/protocol.dart' as protocol
10 show Element, ElementKind; 10 show Element, ElementKind;
11 import 'package:analysis_server/src/protocol.dart' hide Element, ElementKind; 11 import 'package:analysis_server/src/protocol.dart' hide Element, ElementKind;
12 import 'package:analysis_server/src/services/completion/dart_completion_manager. dart'; 12 import 'package:analysis_server/src/services/completion/dart_completion_manager. dart';
13 import 'package:analysis_server/src/services/completion/local_declaration_visito r.dart'; 13 import 'package:analysis_server/src/services/completion/local_declaration_visito r.dart';
14 import 'package:analysis_server/src/services/completion/optype.dart'; 14 import 'package:analysis_server/src/services/completion/optype.dart';
15 import 'package:analyzer/src/generated/ast.dart'; 15 import 'package:analyzer/src/generated/ast.dart';
16 import 'package:analyzer/src/generated/scanner.dart'; 16 import 'package:analyzer/src/generated/scanner.dart';
17 import 'package:analyzer/src/generated/utilities_dart.dart'; 17 import 'package:analyzer/src/generated/utilities_dart.dart';
18 18
19 const _DYNAMIC = 'dynamic';
20
21 final TypeName _NO_RETURN_TYPE = new TypeName(
22 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, '', 0)), null);
23
24 /**
25 * Create a new protocol Element for inclusion in a completion suggestion.
26 */
27 protocol.Element _createElement(protocol.ElementKind kind, SimpleIdentifier id,
28 {String parameters, TypeName returnType, bool isAbstract: false,
29 bool isDeprecated: false}) {
30 String name = id != null ? id.name : '';
31 int flags = protocol.Element.makeFlags(
32 isAbstract: isAbstract,
33 isDeprecated: isDeprecated,
34 isPrivate: Identifier.isPrivateName(name));
35 return new protocol.Element(kind, name, flags,
36 parameters: parameters, returnType: _nameForType(returnType));
37 }
38
39 /**
40 * Return `true` if the @deprecated annotation is present
41 */
42 bool _isDeprecated(AnnotatedNode node) {
43 if (node != null) {
44 NodeList<Annotation> metadata = node.metadata;
45 if (metadata != null) {
46 return metadata.any((Annotation a) {
47 return a.name is SimpleIdentifier && a.name.name == 'deprecated';
48 });
49 }
50 }
51 return false;
52 }
53
54 /**
55 * Return the name for the given type.
56 */
57 String _nameForType(TypeName type) {
58 if (type == _NO_RETURN_TYPE) {
59 return null;
60 }
61 if (type == null) {
62 return _DYNAMIC;
63 }
64 Identifier id = type.name;
65 if (id == null) {
66 return _DYNAMIC;
67 }
68 String name = id.name;
69 if (name == null || name.length <= 0) {
70 return _DYNAMIC;
71 }
72 TypeArgumentList typeArgs = type.typeArguments;
73 if (typeArgs != null) {
74 //TODO (danrubel) include type arguments
75 }
76 return name;
77 }
78
19 /** 79 /**
20 * A computer for calculating `completion.getSuggestions` request results 80 * A computer for calculating `completion.getSuggestions` request results
21 * for the local library in which the completion is requested. 81 * for the local library in which the completion is requested.
22 */ 82 */
23 class LocalComputer extends DartCompletionComputer { 83 class LocalComputer extends DartCompletionComputer {
24 @override 84 @override
25 bool computeFast(DartCompletionRequest request) { 85 bool computeFast(DartCompletionRequest request) {
26 OpType optype = request.optype; 86 OpType optype = request.optype;
87
88 // Collect suggestions from the specific child [AstNode] that contains
89 // the completion offset and all of its parents recursively.
27 if (optype.includeTopLevelSuggestions) { 90 if (optype.includeTopLevelSuggestions) {
28 _LocalVisitor localVisitor = new _LocalVisitor(request, request.offset, 91 _LocalVisitor localVisitor = new _LocalVisitor(request, request.offset,
29 optype.includeOnlyTypeNameSuggestions, 92 optype.includeOnlyTypeNameSuggestions,
30 !optype.includeVoidReturnSuggestions); 93 !optype.includeVoidReturnSuggestions);
31
32 // Collect suggestions from the specific child [AstNode] that contains
33 // the completion offset and all of its parents recursively.
34 localVisitor.visit(request.node); 94 localVisitor.visit(request.node);
35 } 95 }
36 if (optype.includeStatementLabelSuggestions || 96 if (optype.includeStatementLabelSuggestions ||
37 optype.includeCaseLabelSuggestions) { 97 optype.includeCaseLabelSuggestions) {
38 _LabelVisitor labelVisitor = new _LabelVisitor(request, 98 _LabelVisitor labelVisitor = new _LabelVisitor(request,
39 optype.includeStatementLabelSuggestions, 99 optype.includeStatementLabelSuggestions,
40 optype.includeCaseLabelSuggestions); 100 optype.includeCaseLabelSuggestions);
41 labelVisitor.visit(request.node); 101 labelVisitor.visit(request.node);
42 } 102 }
103 if (optype.includeConstructorSuggestions) {
104 new _ConstructorVisitor(request).visit(request.node);
105 }
43 106
44 // If the unit is not a part and does not reference any parts 107 // If the unit is not a part and does not reference any parts
45 // then work is complete 108 // then work is complete
46 return !request.unit.directives.any((Directive directive) => 109 return !request.unit.directives.any((Directive directive) =>
47 directive is PartOfDirective || directive is PartDirective); 110 directive is PartOfDirective || directive is PartDirective);
48 } 111 }
49 112
50 @override 113 @override
51 Future<bool> computeFull(DartCompletionRequest request) { 114 Future<bool> computeFull(DartCompletionRequest request) {
52 // TODO: implement computeFull 115 // TODO: implement computeFull
53 // include results from part files that are included in the library 116 // include results from part files that are included in the library
54 return new Future.value(false); 117 return new Future.value(false);
55 } 118 }
56 } 119 }
57 120
58 /** 121 /**
122 * A visitor for collecting constructor suggestions.
123 */
124 class _ConstructorVisitor extends LocalDeclarationVisitor {
125 final DartCompletionRequest request;
126
127 _ConstructorVisitor(DartCompletionRequest request)
128 : super(request.offset),
129 request = request;
130
131 @override
132 void declaredClass(ClassDeclaration declaration) {
133 bool found = false;
134 for (ClassMember member in declaration.members) {
135 if (member is ConstructorDeclaration) {
136 found = true;
137 _addSuggestion(declaration, member);
138 }
139 }
140 if (!found) {
141 _addSuggestion(declaration, null);
142 }
143 }
144
145 @override
146 void declaredClassTypeAlias(ClassTypeAlias declaration) {
147 // TODO: implement declaredClassTypeAlias
148 }
149
150 @override
151 void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
152 // TODO: implement declaredField
153 }
154
155 @override
156 void declaredFunction(FunctionDeclaration declaration) {
157 // TODO: implement declaredFunction
158 }
159
160 @override
161 void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {
162 // TODO: implement declaredFunctionTypeAlias
163 }
164
165 @override
166 void declaredLabel(Label label, bool isCaseLabel) {
167 // TODO: implement declaredLabel
168 }
169
170 @override
171 void declaredLocalVar(SimpleIdentifier name, TypeName type) {
172 // TODO: implement declaredLocalVar
173 }
174
175 @override
176 void declaredMethod(MethodDeclaration declaration) {
177 // TODO: implement declaredMethod
178 }
179
180 @override
181 void declaredParam(SimpleIdentifier name, TypeName type) {
182 // TODO: implement declaredParam
183 }
184
185 @override
186 void declaredTopLevelVar(
187 VariableDeclarationList varList, VariableDeclaration varDecl) {
188 // TODO: implement declaredTopLevelVar
189 }
190
191 /**
192 * For the given class and constructor,
193 * add a suggestion of the form B(...) or B.name(...).
194 * If the given constructor is `null`
195 * then add a default constructor suggestion.
196 */
197 CompletionSuggestion _addSuggestion(
198 ClassDeclaration classDecl, ConstructorDeclaration constructorDecl) {
199 String completion = classDecl.name.name;
200 if (constructorDecl != null) {
201 SimpleIdentifier elemId = constructorDecl.name;
202 if (elemId != null) {
203 String name = elemId.name;
204 if (name != null && name.length > 0) {
205 completion = '$completion.$name';
206 }
207 }
208 }
209 bool isDeprecated =
210 constructorDecl != null && _isDeprecated(constructorDecl);
211 List<String> parameterNames = new List<String>();
212 List<String> parameterTypes = new List<String>();
213 int requiredParameterCount = 0;
214 bool hasNamedParameters = false;
215 StringBuffer paramBuf = new StringBuffer();
216 paramBuf.write('(');
217 int paramCount = 0;
218 if (constructorDecl != null) {
219 for (FormalParameter param in constructorDecl.parameters.parameters) {
220 if (paramCount > 0) {
221 paramBuf.write(', ');
222 }
223 String paramName;
224 String typeName;
225 if (param is NormalFormalParameter) {
226 paramName = param.identifier.name;
227 typeName = _nameForParamType(param);
228 ++requiredParameterCount;
229 } else if (param is DefaultFormalParameter) {
230 NormalFormalParameter childParam = param.parameter;
231 paramName = childParam.identifier.name;
232 typeName = _nameForParamType(childParam);
233 if (param.kind == ParameterKind.NAMED) {
234 hasNamedParameters = true;
235 }
236 if (paramCount == requiredParameterCount) {
237 paramBuf.write(hasNamedParameters ? '{' : '[');
238 }
239 }
240 parameterNames.add(paramName);
241 parameterTypes.add(typeName);
242 paramBuf.write(typeName);
243 paramBuf.write(' ');
244 paramBuf.write(paramName);
245 ++paramCount;
246 }
247 }
248 if (paramCount > requiredParameterCount) {
249 paramBuf.write(hasNamedParameters ? '}' : ']');
250 }
251 paramBuf.write(')');
252 protocol.Element element = _createElement(
253 protocol.ElementKind.CONSTRUCTOR, null,
254 parameters: paramBuf.toString());
255 element.name = completion;
256 element.returnType = classDecl.name.name;
257 CompletionSuggestion suggestion = new CompletionSuggestion(
258 CompletionSuggestionKind.INVOCATION,
259 isDeprecated ? DART_RELEVANCE_LOW : DART_RELEVANCE_DEFAULT, completion,
260 completion.length, 0, isDeprecated, false,
261 declaringType: classDecl.name.name,
262 element: element,
263 parameterNames: parameterNames,
264 parameterTypes: parameterTypes,
265 requiredParameterCount: requiredParameterCount,
266 hasNamedParameters: hasNamedParameters);
267 request.suggestions.add(suggestion);
268 return suggestion;
269 }
270
271 /**
272 * Determine the name of the type for the given constructor parameter.
273 */
274 String _nameForParamType(NormalFormalParameter param) {
275 if (param is SimpleFormalParameter) {
276 return _nameForType(param.type);
277 }
278 SimpleIdentifier id = param.identifier;
279 if (param is FieldFormalParameter && id != null) {
280 String fieldName = id.name;
281 AstNode classDecl = param.getAncestor((p) => p is ClassDeclaration);
282 if (classDecl is ClassDeclaration) {
283 for (ClassMember member in classDecl.members) {
284 if (member is FieldDeclaration) {
285 for (VariableDeclaration field in member.fields.variables) {
286 if (field.name.name == fieldName) {
287 return _nameForType(member.fields.type);
288 }
289 }
290 }
291 }
292 }
293 }
294 return _DYNAMIC;
295 }
296 }
297
298 /**
59 * A visitor for collecting suggestions for break and continue labels. 299 * A visitor for collecting suggestions for break and continue labels.
60 */ 300 */
61 class _LabelVisitor extends LocalDeclarationVisitor { 301 class _LabelVisitor extends LocalDeclarationVisitor {
62 final DartCompletionRequest request; 302 final DartCompletionRequest request;
63 303
64 /** 304 /**
65 * True if statement labels should be included as suggestions. 305 * True if statement labels should be included as suggestions.
66 */ 306 */
67 final bool includeStatementLabels; 307 final bool includeStatementLabels;
68 308
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 protocol.Element.makeFlags(isPrivate: Identifier.isPrivateName(name)); 411 protocol.Element.makeFlags(isPrivate: Identifier.isPrivateName(name));
172 return new protocol.Element(kind, name, flags); 412 return new protocol.Element(kind, name, flags);
173 } 413 }
174 } 414 }
175 415
176 /** 416 /**
177 * A visitor for collecting suggestions from the most specific child [AstNode] 417 * A visitor for collecting suggestions from the most specific child [AstNode]
178 * that contains the completion offset to the [CompilationUnit]. 418 * that contains the completion offset to the [CompilationUnit].
179 */ 419 */
180 class _LocalVisitor extends LocalDeclarationVisitor { 420 class _LocalVisitor extends LocalDeclarationVisitor {
181 static const DYNAMIC = 'dynamic';
182
183 static final TypeName NO_RETURN_TYPE = new TypeName(
184 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, '', 0)), null);
185
186 final DartCompletionRequest request; 421 final DartCompletionRequest request;
187 final bool typesOnly; 422 final bool typesOnly;
188 final bool excludeVoidReturn; 423 final bool excludeVoidReturn;
189 424
190 _LocalVisitor( 425 _LocalVisitor(
191 this.request, int offset, this.typesOnly, this.excludeVoidReturn) 426 this.request, int offset, this.typesOnly, this.excludeVoidReturn)
192 : super(offset); 427 : super(offset);
193 428
194 @override 429 @override
195 void declaredClass(ClassDeclaration declaration) { 430 void declaredClass(ClassDeclaration declaration) {
196 bool isDeprecated = _isDeprecated(declaration); 431 bool isDeprecated = _isDeprecated(declaration);
197 CompletionSuggestion suggestion = _addSuggestion( 432 CompletionSuggestion suggestion = _addSuggestion(declaration.name,
198 declaration.name, NO_RETURN_TYPE, isDeprecated, DART_RELEVANCE_DEFAULT); 433 _NO_RETURN_TYPE, isDeprecated, DART_RELEVANCE_DEFAULT);
199 if (suggestion != null) { 434 if (suggestion != null) {
200 suggestion.element = _createElement( 435 suggestion.element = _createElement(
201 protocol.ElementKind.CLASS, declaration.name, 436 protocol.ElementKind.CLASS, declaration.name,
202 returnType: NO_RETURN_TYPE, 437 returnType: _NO_RETURN_TYPE,
203 isAbstract: declaration.isAbstract, 438 isAbstract: declaration.isAbstract,
204 isDeprecated: isDeprecated); 439 isDeprecated: isDeprecated);
205 } 440 }
206 } 441 }
207 442
208 @override 443 @override
209 void declaredClassTypeAlias(ClassTypeAlias declaration) { 444 void declaredClassTypeAlias(ClassTypeAlias declaration) {
210 bool isDeprecated = _isDeprecated(declaration); 445 bool isDeprecated = _isDeprecated(declaration);
211 CompletionSuggestion suggestion = _addSuggestion( 446 CompletionSuggestion suggestion = _addSuggestion(declaration.name,
212 declaration.name, NO_RETURN_TYPE, isDeprecated, DART_RELEVANCE_DEFAULT); 447 _NO_RETURN_TYPE, isDeprecated, DART_RELEVANCE_DEFAULT);
213 if (suggestion != null) { 448 if (suggestion != null) {
214 suggestion.element = _createElement( 449 suggestion.element = _createElement(
215 protocol.ElementKind.CLASS_TYPE_ALIAS, declaration.name, 450 protocol.ElementKind.CLASS_TYPE_ALIAS, declaration.name,
216 returnType: NO_RETURN_TYPE, 451 returnType: _NO_RETURN_TYPE,
217 isAbstract: true, 452 isAbstract: true,
218 isDeprecated: isDeprecated); 453 isDeprecated: isDeprecated);
219 } 454 }
220 } 455 }
221 456
222 @override 457 @override
223 void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) { 458 void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
224 if (typesOnly) { 459 if (typesOnly) {
225 return; 460 return;
226 } 461 }
(...skipping 19 matching lines...) Expand all
246 protocol.ElementKind kind; 481 protocol.ElementKind kind;
247 int defaultRelevance = DART_RELEVANCE_DEFAULT; 482 int defaultRelevance = DART_RELEVANCE_DEFAULT;
248 if (declaration.isGetter) { 483 if (declaration.isGetter) {
249 kind = protocol.ElementKind.GETTER; 484 kind = protocol.ElementKind.GETTER;
250 defaultRelevance = DART_RELEVANCE_LOCAL_ACCESSOR; 485 defaultRelevance = DART_RELEVANCE_LOCAL_ACCESSOR;
251 } else if (declaration.isSetter) { 486 } else if (declaration.isSetter) {
252 if (excludeVoidReturn) { 487 if (excludeVoidReturn) {
253 return; 488 return;
254 } 489 }
255 kind = protocol.ElementKind.SETTER; 490 kind = protocol.ElementKind.SETTER;
256 returnType = NO_RETURN_TYPE; 491 returnType = _NO_RETURN_TYPE;
257 defaultRelevance = DART_RELEVANCE_LOCAL_ACCESSOR; 492 defaultRelevance = DART_RELEVANCE_LOCAL_ACCESSOR;
258 } else { 493 } else {
259 if (excludeVoidReturn && _isVoid(returnType)) { 494 if (excludeVoidReturn && _isVoid(returnType)) {
260 return; 495 return;
261 } 496 }
262 kind = protocol.ElementKind.FUNCTION; 497 kind = protocol.ElementKind.FUNCTION;
263 defaultRelevance = DART_RELEVANCE_LOCAL_FUNCTION; 498 defaultRelevance = DART_RELEVANCE_LOCAL_FUNCTION;
264 } 499 }
265 CompletionSuggestion suggestion = _addSuggestion( 500 CompletionSuggestion suggestion = _addSuggestion(
266 declaration.name, returnType, isDeprecated, defaultRelevance); 501 declaration.name, returnType, isDeprecated, defaultRelevance);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 int defaultRelevance = DART_RELEVANCE_DEFAULT; 555 int defaultRelevance = DART_RELEVANCE_DEFAULT;
321 if (declaration.isGetter) { 556 if (declaration.isGetter) {
322 kind = protocol.ElementKind.GETTER; 557 kind = protocol.ElementKind.GETTER;
323 parameters = null; 558 parameters = null;
324 defaultRelevance = DART_RELEVANCE_LOCAL_ACCESSOR; 559 defaultRelevance = DART_RELEVANCE_LOCAL_ACCESSOR;
325 } else if (declaration.isSetter) { 560 } else if (declaration.isSetter) {
326 if (excludeVoidReturn) { 561 if (excludeVoidReturn) {
327 return; 562 return;
328 } 563 }
329 kind = protocol.ElementKind.SETTER; 564 kind = protocol.ElementKind.SETTER;
330 returnType = NO_RETURN_TYPE; 565 returnType = _NO_RETURN_TYPE;
331 defaultRelevance = DART_RELEVANCE_LOCAL_ACCESSOR; 566 defaultRelevance = DART_RELEVANCE_LOCAL_ACCESSOR;
332 } else { 567 } else {
333 if (excludeVoidReturn && _isVoid(returnType)) { 568 if (excludeVoidReturn && _isVoid(returnType)) {
334 return; 569 return;
335 } 570 }
336 kind = protocol.ElementKind.METHOD; 571 kind = protocol.ElementKind.METHOD;
337 parameters = declaration.parameters.toSource(); 572 parameters = declaration.parameters.toSource();
338 defaultRelevance = DART_RELEVANCE_LOCAL_METHOD; 573 defaultRelevance = DART_RELEVANCE_LOCAL_METHOD;
339 } 574 }
340 bool isDeprecated = _isDeprecated(declaration); 575 bool isDeprecated = _isDeprecated(declaration);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 } 672 }
438 } 673 }
439 } 674 }
440 request.suggestions.add(suggestion); 675 request.suggestions.add(suggestion);
441 return suggestion; 676 return suggestion;
442 } 677 }
443 } 678 }
444 return null; 679 return null;
445 } 680 }
446 681
447 /**
448 * Create a new protocol Element for inclusion in a completion suggestion.
449 */
450 protocol.Element _createElement(
451 protocol.ElementKind kind, SimpleIdentifier id, {String parameters,
452 TypeName returnType, bool isAbstract: false, bool isDeprecated: false}) {
453 String name = id.name;
454 int flags = protocol.Element.makeFlags(
455 isAbstract: isAbstract,
456 isDeprecated: isDeprecated,
457 isPrivate: Identifier.isPrivateName(name));
458 return new protocol.Element(kind, name, flags,
459 parameters: parameters, returnType: _nameForType(returnType));
460 }
461
462 /**
463 * Return `true` if the @deprecated annotation is present
464 */
465 bool _isDeprecated(AnnotatedNode node) {
466 if (node != null) {
467 NodeList<Annotation> metadata = node.metadata;
468 if (metadata != null) {
469 return metadata.any((Annotation a) {
470 return a.name is SimpleIdentifier && a.name.name == 'deprecated';
471 });
472 }
473 }
474 return false;
475 }
476
477 bool _isVoid(TypeName returnType) { 682 bool _isVoid(TypeName returnType) {
478 if (returnType != null) { 683 if (returnType != null) {
479 Identifier id = returnType.name; 684 Identifier id = returnType.name;
480 if (id != null && id.name == 'void') { 685 if (id != null && id.name == 'void') {
481 return true; 686 return true;
482 } 687 }
483 } 688 }
484 return false; 689 return false;
485 } 690 }
486
487 /**
488 * Return the name for the given type.
489 */
490 String _nameForType(TypeName type) {
491 if (type == NO_RETURN_TYPE) {
492 return null;
493 }
494 if (type == null) {
495 return DYNAMIC;
496 }
497 Identifier id = type.name;
498 if (id == null) {
499 return DYNAMIC;
500 }
501 String name = id.name;
502 if (name == null || name.length <= 0) {
503 return DYNAMIC;
504 }
505 TypeArgumentList typeArgs = type.typeArguments;
506 if (typeArgs != null) {
507 //TODO (danrubel) include type arguments
508 }
509 return name;
510 }
511 } 691 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698