OLD | NEW |
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.contributor.dart.local; | 5 library services.completion.contributor.dart.local; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import 'package:analysis_server/plugin/protocol/protocol.dart' as protocol | 9 import 'package:analysis_server/plugin/protocol/protocol.dart' as protocol |
10 show Element, ElementKind; | 10 show Element, ElementKind; |
(...skipping 23 matching lines...) Expand all Loading... |
34 // Collect suggestions from the specific child [AstNode] that contains | 34 // Collect suggestions from the specific child [AstNode] that contains |
35 // the completion offset and all of its parents recursively. | 35 // the completion offset and all of its parents recursively. |
36 if (!optype.isPrefixed) { | 36 if (!optype.isPrefixed) { |
37 if (optype.includeReturnValueSuggestions || | 37 if (optype.includeReturnValueSuggestions || |
38 optype.includeTypeNameSuggestions || | 38 optype.includeTypeNameSuggestions || |
39 optype.includeVoidReturnSuggestions) { | 39 optype.includeVoidReturnSuggestions) { |
40 _LocalVisitor localVisitor = | 40 _LocalVisitor localVisitor = |
41 new _LocalVisitor(request, request.offset, optype); | 41 new _LocalVisitor(request, request.offset, optype); |
42 localVisitor.visit(request.target.containingNode); | 42 localVisitor.visit(request.target.containingNode); |
43 } | 43 } |
44 if (optype.includeConstructorSuggestions) { | |
45 new _ConstructorVisitor(request).visit(request.target.containingNode); | |
46 } | |
47 } | 44 } |
48 | 45 |
49 // If target is an argument in an argument list | 46 // If target is an argument in an argument list |
50 // then suggestions may need to be adjusted | 47 // then suggestions may need to be adjusted |
51 return request.target.argIndex == null; | 48 return request.target.argIndex == null; |
52 } | 49 } |
53 | 50 |
54 @override | 51 @override |
55 Future<bool> computeFull(DartCompletionRequest request) { | 52 Future<bool> computeFull(DartCompletionRequest request) { |
56 _updateSuggestions(request); | 53 _updateSuggestions(request); |
57 return new Future.value(false); | 54 return new Future.value(false); |
58 } | 55 } |
59 | 56 |
60 /** | 57 /** |
61 * If target is a function argument, suggest identifiers not invocations | 58 * If target is a function argument, suggest identifiers not invocations |
62 */ | 59 */ |
63 void _updateSuggestions(DartCompletionRequest request) { | 60 void _updateSuggestions(DartCompletionRequest request) { |
64 if (request.target.isFunctionalArgument()) { | 61 if (request.target.isFunctionalArgument()) { |
65 request.convertInvocationsToIdentifiers(); | 62 request.convertInvocationsToIdentifiers(); |
66 } | 63 } |
67 } | 64 } |
68 } | 65 } |
69 | 66 |
70 /** | 67 /** |
71 * A visitor for collecting constructor suggestions. | |
72 */ | |
73 class _ConstructorVisitor extends LocalDeclarationVisitor { | |
74 final DartCompletionRequest request; | |
75 | |
76 _ConstructorVisitor(DartCompletionRequest request) | |
77 : super(request.offset), | |
78 request = request; | |
79 | |
80 @override | |
81 void declaredClass(ClassDeclaration declaration) { | |
82 bool found = false; | |
83 for (ClassMember member in declaration.members) { | |
84 if (member is ConstructorDeclaration) { | |
85 found = true; | |
86 _addSuggestion(declaration, member); | |
87 } | |
88 } | |
89 if (!found) { | |
90 _addSuggestion(declaration, null); | |
91 } | |
92 } | |
93 | |
94 @override | |
95 void declaredClassTypeAlias(ClassTypeAlias declaration) {} | |
96 | |
97 @override | |
98 void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {} | |
99 | |
100 @override | |
101 void declaredFunction(FunctionDeclaration declaration) {} | |
102 | |
103 @override | |
104 void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {} | |
105 | |
106 @override | |
107 void declaredLabel(Label label, bool isCaseLabel) {} | |
108 | |
109 @override | |
110 void declaredLocalVar(SimpleIdentifier name, TypeName type) {} | |
111 | |
112 @override | |
113 void declaredMethod(MethodDeclaration declaration) {} | |
114 | |
115 @override | |
116 void declaredParam(SimpleIdentifier name, TypeName type) {} | |
117 | |
118 @override | |
119 void declaredTopLevelVar( | |
120 VariableDeclarationList varList, VariableDeclaration varDecl) {} | |
121 | |
122 /** | |
123 * For the given class and constructor, | |
124 * add a suggestion of the form B(...) or B.name(...). | |
125 * If the given constructor is `null` | |
126 * then add a default constructor suggestion. | |
127 */ | |
128 CompletionSuggestion _addSuggestion( | |
129 ClassDeclaration classDecl, ConstructorDeclaration constructorDecl) { | |
130 SimpleIdentifier elemId; | |
131 String completion = classDecl.name.name; | |
132 if (constructorDecl != null) { | |
133 elemId = constructorDecl.name; | |
134 if (elemId != null) { | |
135 String name = elemId.name; | |
136 if (name != null && name.length > 0) { | |
137 completion = '$completion.$name'; | |
138 } | |
139 } | |
140 } | |
141 bool deprecated = constructorDecl != null && isDeprecated(constructorDecl); | |
142 List<String> parameterNames = new List<String>(); | |
143 List<String> parameterTypes = new List<String>(); | |
144 int requiredParameterCount = 0; | |
145 bool hasNamedParameters = false; | |
146 StringBuffer paramBuf = new StringBuffer(); | |
147 paramBuf.write('('); | |
148 int paramCount = 0; | |
149 if (constructorDecl != null) { | |
150 for (FormalParameter param in constructorDecl.parameters.parameters) { | |
151 if (paramCount > 0) { | |
152 paramBuf.write(', '); | |
153 } | |
154 String paramName; | |
155 String typeName; | |
156 if (param is NormalFormalParameter) { | |
157 paramName = param.identifier.name; | |
158 typeName = _nameForParamType(param); | |
159 ++requiredParameterCount; | |
160 } else if (param is DefaultFormalParameter) { | |
161 NormalFormalParameter childParam = param.parameter; | |
162 paramName = childParam.identifier.name; | |
163 typeName = _nameForParamType(childParam); | |
164 if (param.kind == ParameterKind.NAMED) { | |
165 hasNamedParameters = true; | |
166 } | |
167 if (paramCount == requiredParameterCount) { | |
168 paramBuf.write(hasNamedParameters ? '{' : '['); | |
169 } | |
170 } | |
171 parameterNames.add(paramName); | |
172 parameterTypes.add(typeName); | |
173 paramBuf.write(typeName); | |
174 paramBuf.write(' '); | |
175 paramBuf.write(paramName); | |
176 ++paramCount; | |
177 } | |
178 } | |
179 if (paramCount > requiredParameterCount) { | |
180 paramBuf.write(hasNamedParameters ? '}' : ']'); | |
181 } | |
182 paramBuf.write(')'); | |
183 protocol.Element element = createElement( | |
184 request.source, protocol.ElementKind.CONSTRUCTOR, elemId, | |
185 parameters: paramBuf.toString()); | |
186 element.returnType = classDecl.name.name; | |
187 CompletionSuggestion suggestion = new CompletionSuggestion( | |
188 CompletionSuggestionKind.INVOCATION, | |
189 deprecated ? DART_RELEVANCE_LOW : DART_RELEVANCE_DEFAULT, | |
190 completion, | |
191 completion.length, | |
192 0, | |
193 deprecated, | |
194 false, | |
195 declaringType: classDecl.name.name, | |
196 element: element, | |
197 parameterNames: parameterNames, | |
198 parameterTypes: parameterTypes, | |
199 requiredParameterCount: requiredParameterCount, | |
200 hasNamedParameters: hasNamedParameters); | |
201 request.addSuggestion(suggestion); | |
202 return suggestion; | |
203 } | |
204 | |
205 /** | |
206 * Determine the name of the type for the given constructor parameter. | |
207 */ | |
208 String _nameForParamType(NormalFormalParameter param) { | |
209 if (param is SimpleFormalParameter) { | |
210 return nameForType(param.type); | |
211 } | |
212 SimpleIdentifier id = param.identifier; | |
213 if (param is FieldFormalParameter && id != null) { | |
214 String fieldName = id.name; | |
215 AstNode classDecl = param.getAncestor((p) => p is ClassDeclaration); | |
216 if (classDecl is ClassDeclaration) { | |
217 for (ClassMember member in classDecl.members) { | |
218 if (member is FieldDeclaration) { | |
219 for (VariableDeclaration field in member.fields.variables) { | |
220 if (field.name.name == fieldName) { | |
221 return nameForType(member.fields.type); | |
222 } | |
223 } | |
224 } | |
225 } | |
226 } | |
227 } | |
228 return DYNAMIC; | |
229 } | |
230 } | |
231 | |
232 /** | |
233 * A visitor for collecting suggestions from the most specific child [AstNode] | 68 * A visitor for collecting suggestions from the most specific child [AstNode] |
234 * that contains the completion offset to the [CompilationUnit]. | 69 * that contains the completion offset to the [CompilationUnit]. |
235 */ | 70 */ |
236 class _LocalVisitor extends LocalDeclarationVisitor { | 71 class _LocalVisitor extends LocalDeclarationVisitor { |
237 final DartCompletionRequest request; | 72 final DartCompletionRequest request; |
238 final OpType optype; | 73 final OpType optype; |
239 int privateMemberRelevance = DART_RELEVANCE_DEFAULT; | 74 int privateMemberRelevance = DART_RELEVANCE_DEFAULT; |
240 | 75 |
241 _LocalVisitor(this.request, int offset, this.optype) : super(offset) { | 76 _LocalVisitor(this.request, int offset, this.optype) : super(offset) { |
242 includeLocalInheritedTypes = !optype.inStaticMethodBody; | 77 includeLocalInheritedTypes = !optype.inStaticMethodBody; |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 bool _isVoid(TypeName returnType) { | 306 bool _isVoid(TypeName returnType) { |
472 if (returnType != null) { | 307 if (returnType != null) { |
473 Identifier id = returnType.name; | 308 Identifier id = returnType.name; |
474 if (id != null && id.name == 'void') { | 309 if (id != null && id.name == 'void') { |
475 return true; | 310 return true; |
476 } | 311 } |
477 } | 312 } |
478 return false; | 313 return false; |
479 } | 314 } |
480 } | 315 } |
OLD | NEW |