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

Side by Side Diff: pkg/analysis_server/lib/src/services/completion/prefixed_element_contributor.dart

Issue 1504223005: extract TypeMemberContributor from prefixed element contributor (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: mege Created 5 years 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
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library services.completion.contributor.dart.invocation;
6
7 import 'dart:async';
8
9 import 'package:analysis_server/src/services/completion/dart_completion_manager. dart';
10 import 'package:analysis_server/src/services/completion/local_declaration_visito r.dart';
11 import 'package:analysis_server/src/services/completion/local_suggestion_builder .dart'
12 hide createSuggestion;
13 import 'package:analysis_server/src/services/completion/optype.dart';
14 import 'package:analysis_server/src/services/completion/suggestion_builder.dart' ;
15 import 'package:analysis_server/src/services/completion/suggestion_builder.dart'
16 show createSuggestion;
17 import 'package:analyzer/src/generated/ast.dart';
18 import 'package:analyzer/src/generated/element.dart';
19
20 import '../../protocol_server.dart'
21 show CompletionSuggestion, CompletionSuggestionKind;
22
23 /**
24 * A contributor for calculating invocation / access suggestions
25 * `completion.getSuggestions` request results.
26 */
27 class PrefixedElementContributor extends DartCompletionContributor {
28 SuggestionBuilder builder;
29
30 @override
31 bool computeFast(DartCompletionRequest request) {
32 OpType optype = request.optype;
33 if (optype.isPrefixed) {
34 builder = request.target.containingNode
35 .accept(new _InvocationAstVisitor(request));
36 if (builder != null) {
37 return builder.computeFast(request.target.containingNode);
38 }
39 }
40
41 return true;
42 }
43
44 @override
45 Future<bool> computeFull(DartCompletionRequest request) {
46 if (builder != null) {
47 return builder.computeFull(request.target.containingNode);
48 }
49 return new Future.value(false);
50 }
51 }
52
53 class _ExpressionSuggestionBuilder implements SuggestionBuilder {
54 final DartCompletionRequest request;
55
56 _ExpressionSuggestionBuilder(this.request);
57
58 @override
59 bool computeFast(AstNode node) {
60 return false;
61 }
62
63 @override
64 Future<bool> computeFull(AstNode node) {
65 if (node is MethodInvocation) {
66 node = (node as MethodInvocation).realTarget;
67 } else if (node is PropertyAccess) {
68 node = (node as PropertyAccess).realTarget;
69 }
70 if (node is Identifier) {
71 Element elem = node.bestElement;
72 if (elem is ClassElement || elem is PrefixElement) {
73 elem.accept(new _PrefixedIdentifierSuggestionBuilder(request));
74 return new Future.value(true);
75 }
76 }
77 if (node is Expression) {
78 String containingMethodName;
79 bool isSuper = node is SuperExpression;
80 if (isSuper) {
81 MethodDeclaration containingMethod =
82 node.getAncestor((p) => p is MethodDeclaration);
83 if (containingMethod != null) {
84 SimpleIdentifier id = containingMethod.name;
85 if (id != null) {
86 containingMethodName = id.name;
87 }
88 }
89 }
90 InterfaceTypeSuggestionBuilder.suggestionsFor(request, node.bestType,
91 isSuper: isSuper, containingMethodName: containingMethodName);
92 return new Future.value(true);
93 }
94 return new Future.value(false);
95 }
96 }
97
98 /**
99 * An [AstNode] vistor for determining which suggestion builder
100 * should be used to build invocation/access suggestions.
101 */
102 class _InvocationAstVisitor extends GeneralizingAstVisitor<SuggestionBuilder> {
103 final DartCompletionRequest request;
104
105 _InvocationAstVisitor(this.request);
106
107 @override
108 SuggestionBuilder visitConstructorName(ConstructorName node) {
109 // some PrefixedIdentifier nodes are transformed into
110 // ConstructorName nodes during the resolution process.
111 return new _PrefixedIdentifierSuggestionBuilder(request);
112 }
113
114 @override
115 SuggestionBuilder visitMethodInvocation(MethodInvocation node) {
116 return new _ExpressionSuggestionBuilder(request);
117 }
118
119 @override
120 SuggestionBuilder visitNode(AstNode node) {
121 return null;
122 }
123
124 @override
125 SuggestionBuilder visitPrefixedIdentifier(PrefixedIdentifier node) {
126 // some PrefixedIdentifier nodes are transformed into
127 // ConstructorName nodes during the resolution process.
128 return new _PrefixedIdentifierSuggestionBuilder(request);
129 }
130
131 @override
132 SuggestionBuilder visitPropertyAccess(PropertyAccess node) {
133 return new _ExpressionSuggestionBuilder(request);
134 }
135 }
136
137 /**
138 * An [AstVisitor] which looks for a declaration with the given name
139 * and if found, tries to determine a type for that declaration.
140 */
141 class _LocalBestTypeVisitor extends LocalDeclarationVisitor {
142 /**
143 * The name for the declaration to be found.
144 */
145 final String targetName;
146
147 /**
148 * The best type for the found declaration,
149 * or `null` if no declaration found or failed to determine a type.
150 */
151 DartType typeFound;
152
153 /**
154 * Construct a new instance to search for a declaration
155 */
156 _LocalBestTypeVisitor(this.targetName, int offset) : super(offset);
157
158 @override
159 void declaredClass(ClassDeclaration declaration) {
160 if (declaration.name.name == targetName) {
161 // no type
162 finished();
163 }
164 }
165
166 @override
167 void declaredClassTypeAlias(ClassTypeAlias declaration) {
168 if (declaration.name.name == targetName) {
169 // no type
170 finished();
171 }
172 }
173
174 @override
175 void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
176 if (varDecl.name.name == targetName) {
177 // Type provided by the element in computeFull above
178 finished();
179 }
180 }
181
182 @override
183 void declaredFunction(FunctionDeclaration declaration) {
184 if (declaration.name.name == targetName) {
185 TypeName typeName = declaration.returnType;
186 if (typeName != null) {
187 typeFound = typeName.type;
188 }
189 finished();
190 }
191 }
192
193 @override
194 void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {
195 if (declaration.name.name == targetName) {
196 TypeName typeName = declaration.returnType;
197 if (typeName != null) {
198 typeFound = typeName.type;
199 }
200 finished();
201 }
202 }
203
204 @override
205 void declaredLabel(Label label, bool isCaseLabel) {
206 if (label.label.name == targetName) {
207 // no type
208 finished();
209 }
210 }
211
212 @override
213 void declaredLocalVar(SimpleIdentifier name, TypeName type) {
214 if (name.name == targetName) {
215 typeFound = name.bestType;
216 finished();
217 }
218 }
219
220 @override
221 void declaredMethod(MethodDeclaration declaration) {
222 if (declaration.name.name == targetName) {
223 TypeName typeName = declaration.returnType;
224 if (typeName != null) {
225 typeFound = typeName.type;
226 }
227 finished();
228 }
229 }
230
231 @override
232 void declaredParam(SimpleIdentifier name, TypeName type) {
233 if (name.name == targetName) {
234 // Type provided by the element in computeFull above
235 finished();
236 }
237 }
238
239 @override
240 void declaredTopLevelVar(
241 VariableDeclarationList varList, VariableDeclaration varDecl) {
242 if (varDecl.name.name == targetName) {
243 // Type provided by the element in computeFull above
244 finished();
245 }
246 }
247 }
248
249 /**
250 * An [Element] visitor for determining the appropriate invocation/access
251 * suggestions based upon the element for which the completion is requested.
252 */
253 class _PrefixedIdentifierSuggestionBuilder
254 extends GeneralizingElementVisitor<Future<bool>>
255 implements SuggestionBuilder {
256 final DartCompletionRequest request;
257
258 _PrefixedIdentifierSuggestionBuilder(this.request);
259
260 @override
261 bool computeFast(AstNode node) {
262 return false;
263 }
264
265 @override
266 Future<bool> computeFull(AstNode node) {
267 if (node is PrefixedIdentifier) {
268 SimpleIdentifier prefix = node.prefix;
269 if (prefix != null) {
270 Element element = prefix.bestElement;
271 DartType type = prefix.bestType;
272 if (element is! ClassElement) {
273 if (type == null || type.isDynamic) {
274 //
275 // Given `g. int y = 0;`, the parser interprets `g` as a prefixed
276 // identifier with no type.
277 // If the user is requesting completions for `g`,
278 // then check for a function, getter, or similar with a type.
279 //
280 _LocalBestTypeVisitor visitor =
281 new _LocalBestTypeVisitor(prefix.name, request.offset);
282 if (visitor.visit(prefix)) {
283 type = visitor.typeFound;
284 }
285 }
286 if (type != null && !type.isDynamic) {
287 InterfaceTypeSuggestionBuilder.suggestionsFor(request, type);
288 return new Future.value(true);
289 }
290 }
291 if (element != null) {
292 return element.accept(this);
293 }
294 }
295 }
296 return new Future.value(false);
297 }
298
299 @override
300 Future<bool> visitClassElement(ClassElement element) {
301 if (element != null) {
302 InterfaceType type = element.type;
303 if (type != null) {
304 // Suggested by StaticMemberContributor
305 // StaticClassElementSuggestionBuilder.suggestionsFor(
306 // request, type.element);
307 }
308 }
309 return new Future.value(false);
310 }
311
312 @override
313 Future<bool> visitElement(Element element) {
314 return new Future.value(false);
315 }
316
317 @override
318 Future<bool> visitPrefixElement(PrefixElement element) {
319 bool modified = false;
320
321 // Suggested by LibraryMemberContributor
322
323 // Find the import directive with the given prefix
324 // for (Directive directive in request.unit.directives) {
325 // if (directive is ImportDirective) {
326 // if (directive.prefix != null) {
327 // if (directive.prefix.name == element.name) {
328 // // Suggest elements from the imported library
329 // LibraryElement library = directive.uriElement;
330 // AstNode node = request.target.containingNode;
331 // bool typesOnly = node.parent is TypeName;
332 // bool instCreation =
333 // typesOnly && node.parent.parent is ConstructorName;
334 // LibraryElementSuggestionBuilder.suggestionsFor(
335 // request,
336 // CompletionSuggestionKind.INVOCATION,
337 // library,
338 // typesOnly,
339 // instCreation);
340 // modified = true;
341 // if (directive.deferredKeyword != null) {
342 // FunctionElement loadLibFunct = library.loadLibraryFunction;
343 // request.addSuggestion(createSuggestion(loadLibFunct));
344 // }
345 // }
346 // }
347 // }
348 // }
349 return new Future.value(modified);
350 }
351
352 @override
353 Future<bool> visitPropertyAccessorElement(PropertyAccessorElement element) {
354 if (element != null) {
355 PropertyInducingElement elemVar = element.variable;
356 if (elemVar != null) {
357 InterfaceTypeSuggestionBuilder.suggestionsFor(request, elemVar.type);
358 }
359 return new Future.value(true);
360 }
361 return new Future.value(false);
362 }
363
364 @override
365 Future<bool> visitVariableElement(VariableElement element) {
366 InterfaceTypeSuggestionBuilder.suggestionsFor(request, element.type);
367 return new Future.value(true);
368 }
369 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698