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

Side by Side Diff: pkg/analysis_services/lib/src/generated/completion.dart

Issue 263213007: New analysis_server snapshot and completion.dart in analysis_services. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 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
(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 // This code was auto-generated, is not intended to be edited, and is subject to
6 // significant change. Please see the README file for more information.
7
8 library services.completion;
9
10 import 'dart:collection';
11 import 'package:analyzer/src/generated/java_core.dart' hide StringUtils;
12 import 'package:analyzer/src/generated/java_engine.dart';
13 import 'package:analyzer/src/generated/java_io.dart';
14 import 'package:analyzer/src/generated/ast.dart';
15 import 'package:analyzer/src/generated/element.dart';
16 import 'package:analyzer/src/generated/engine.dart';
17 import 'package:analyzer/src/generated/error.dart';
18 import 'package:analyzer/src/generated/resolver.dart';
19 import 'package:analyzer/src/generated/scanner.dart';
20 import 'package:analyzer/src/generated/sdk.dart';
21 import 'package:analyzer/src/generated/source_io.dart';
22 import 'package:analyzer/src/generated/utilities_dart.dart';
23 import 'stubs.dart';
24 import 'util.dart';
25
26 class AstNodeClassifier_CompletionEngine_typeOf extends CompletionEngine_AstNode Classifier {
27 final CompletionEngine CompletionEngine_this;
28
29 List<DartType> result;
30
31 AstNodeClassifier_CompletionEngine_typeOf(this.CompletionEngine_this, this.res ult) : super();
32
33 @override
34 Object visitPrefixedIdentifier(PrefixedIdentifier node) => visitSimpleIdentifi er(node.identifier);
35
36 @override
37 Object visitSimpleIdentifier(SimpleIdentifier node) {
38 Element elem = node.bestElement;
39 if (elem != null && elem.kind == ElementKind.GETTER) {
40 PropertyAccessorElement accessor = elem as PropertyAccessorElement;
41 if (accessor.isSynthetic) {
42 PropertyInducingElement var2 = accessor.variable;
43 result[0] = CompletionEngine_this._typeSearch(var2);
44 }
45 }
46 return null;
47 }
48 }
49
50 /**
51 * The analysis engine for code completion.
52 *
53 * Note: During development package-private methods are used to group element-sp ecific completion
54 * utilities.
55 *
56 * TODO: Recognize when completion is requested in the middle of a multi-charact er operator.
57 * Re-write the AST as it would be if an identifier were present at the completi on point then
58 * restart the analysis.
59 */
60 class CompletionEngine {
61 static String _C_DYNAMIC = "dynamic";
62
63 static String _C_FALSE = "false";
64
65 static String _C_NULL = "null";
66
67 static String _C_PARAMNAME = "arg";
68
69 static String _C_TRUE = "true";
70
71 static String _C_VAR = "var";
72
73 static String _C_VOID = "void";
74
75 static bool _isPrivate(Element element) {
76 String name = element.displayName;
77 return Identifier.isPrivateName(name);
78 }
79
80 static bool _isSyntheticIdentifier(Expression expression) => expression is Sim pleIdentifier && expression.isSynthetic;
81
82 CompletionRequestor _requestor;
83
84 final CompletionFactory _factory;
85
86 AssistContext _context;
87
88 Filter _filter;
89
90 CompletionState _state;
91
92 List<LibraryElement> _libraries;
93
94 CompletionEngine(CompletionRequestor requestor, this._factory) {
95 this._requestor = requestor;
96 this._state = new CompletionState();
97 }
98
99 /**
100 * Analyze the source unit in the given context to determine completion propos als at the selection
101 * offset of the context.
102 *
103 * @throws Exception
104 */
105 void complete(AssistContext context) {
106 this._context = context;
107 _requestor.beginReporting();
108 AstNode completionNode = context.coveredNode;
109 if (completionNode != null) {
110 _state.context = completionNode;
111 CompletionEngine_TerminalNodeCompleter visitor = new CompletionEngine_Term inalNodeCompleter(this);
112 completionNode.accept(visitor);
113 }
114 _requestor.endReporting();
115 }
116
117 void _analyzeAnnotationName(SimpleIdentifier identifier) {
118 _filter = _createFilter(identifier);
119 CompletionEngine_NameCollector names = _collectTopLevelElementVisibleAt(iden tifier);
120 for (Element element in names.uniqueElements) {
121 if (element is PropertyAccessorElement) {
122 element = (element as PropertyAccessorElement).variable;
123 }
124 if (element is TopLevelVariableElement) {
125 TopLevelVariableElement variable = element as TopLevelVariableElement;
126 if (_state._isCompileTimeConstantRequired && !variable.isConst) {
127 continue;
128 }
129 _proposeName(element, identifier, names);
130 }
131 if (element is ClassElement) {
132 ClassElement classElement = element as ClassElement;
133 for (ConstructorElement constructor in classElement.constructors) {
134 _pNamedConstructor(classElement, constructor, identifier);
135 }
136 }
137 }
138 }
139
140 void _analyzeConstructorTypeName(SimpleIdentifier identifier) {
141 _filter = _createFilter(identifier);
142 List<Element> types = _findAllTypes(currentLibrary, TopLevelNamesKind.DECLAR ED_AND_IMPORTS);
143 for (Element type in types) {
144 if (type is ClassElement) {
145 _namedConstructorReference(type, identifier);
146 }
147 }
148 List<Element> prefixes = _findAllPrefixes();
149 for (Element prefix in prefixes) {
150 _pName(prefix, identifier);
151 }
152 }
153
154 void _analyzeDeclarationName(VariableDeclaration varDecl) {
155 // We might want to propose multiple names for a declaration based on types someday.
156 // For now, just use whatever is already there.
157 SimpleIdentifier identifier = varDecl.name;
158 _filter = _createFilter(identifier);
159 VariableDeclarationList varList = varDecl.parent as VariableDeclarationList;
160 TypeName type = varList.type;
161 if (identifier.length > 0) {
162 _pName3(identifier.name, ProposalKind.VARIABLE);
163 }
164 if (type == null) {
165 if (varList.keyword == null) {
166 // Interpret as the type name of a typed variable declaration { DivE!; }
167 _analyzeLocalName(identifier);
168 }
169 } else {
170 _pParamName(type.name.name.toLowerCase());
171 }
172 }
173
174 void _analyzeDirectAccess(DartType receiverType, SimpleIdentifier completionNo de) {
175 if (receiverType != null) {
176 // Complete this.!y where this is absent
177 Element rcvrTypeElem = receiverType.element;
178 if (receiverType.isDynamic) {
179 rcvrTypeElem = objectClassElement;
180 }
181 if (rcvrTypeElem is ClassElement) {
182 _directAccess(rcvrTypeElem as ClassElement, completionNode);
183 }
184 }
185 }
186
187 void _analyzeImmediateField(SimpleIdentifier fieldName) {
188 _filter = _createFilter(fieldName);
189 ClassDeclaration classDecl = fieldName.getAncestor((node) => node is ClassDe claration);
190 ClassElement classElement = classDecl.element;
191 for (FieldElement field in classElement.fields) {
192 _pName3(field.displayName, ProposalKind.FIELD);
193 }
194 }
195
196 void _analyzeLiteralReference(BooleanLiteral literal) {
197 // state.setContext(literal);
198 Ident ident = _createIdent(literal.parent);
199 ident.token = literal.literal;
200 _filter = _createFilter(ident);
201 _analyzeLocalName(ident);
202 }
203
204 void _analyzeLocalName(SimpleIdentifier identifier) {
205 // Completion x!
206 _filter = _createFilter(identifier);
207 // TODO Filter out types that have no static members.
208 CompletionEngine_NameCollector names = _collectIdentifiersVisibleAt(identifi er);
209 for (Element element in names.uniqueElements) {
210 if (_state._isSourceDeclarationStatic) {
211 if (element is FieldElement) {
212 if (!element.isStatic) {
213 continue;
214 }
215 } else if (element is PropertyAccessorElement) {
216 if (!element.isStatic) {
217 continue;
218 }
219 }
220 }
221 if (_state._isOptionalArgumentRequired) {
222 if (element is! ParameterElement) {
223 continue;
224 }
225 ParameterElement param = element as ParameterElement;
226 if (!param.parameterKind.isOptional) {
227 continue;
228 }
229 }
230 _proposeName(element, identifier, names);
231 }
232 if (_state._areLiteralsAllowed) {
233 _pNull();
234 _pTrue();
235 _pFalse();
236 }
237 }
238
239 void _analyzeNamedParameter(ArgumentList args, SimpleIdentifier identifier) {
240 // Completion x!
241 _filter = _createFilter(identifier);
242 // prepare parameters
243 List<ParameterElement> parameters = _getParameterElements(args);
244 if (parameters == null) {
245 return;
246 }
247 // remember already used names
248 Set<String> usedNames = new Set();
249 for (Expression arg in args.arguments) {
250 if (arg is NamedExpression) {
251 NamedExpression namedExpr = arg;
252 String name = namedExpr.name.label.name;
253 usedNames.add(name);
254 }
255 }
256 // propose named parameters
257 for (ParameterElement parameterElement in parameters) {
258 // should be named
259 if (parameterElement.parameterKind != ParameterKind.NAMED) {
260 continue;
261 }
262 // filter by name
263 if (_filterDisallows(parameterElement)) {
264 continue;
265 }
266 // may be already used
267 String parameterName = parameterElement.name;
268 if (usedNames.contains(parameterName)) {
269 continue;
270 }
271 // OK, add proposal
272 CompletionProposal prop = _createProposal4(ProposalKind.NAMED_ARGUMENT);
273 prop.setCompletion(parameterName);
274 prop.setParameterName(parameterName);
275 prop.setParameterType(parameterElement.type.displayName);
276 prop.setLocation(identifier.offset);
277 prop.setReplacementLength(identifier.length);
278 prop.setRelevance(CompletionProposal.RELEVANCE_HIGH);
279 _requestor.accept(prop);
280 }
281 }
282
283 void _analyzeNewParameterName(List<FormalParameter> params, SimpleIdentifier t ypeIdent, String identifierName) {
284 String typeName = typeIdent.name;
285 _filter = _createFilter(_createIdent(typeIdent));
286 List<String> names = new List<String>();
287 for (FormalParameter node in params) {
288 names.add(node.identifier.name);
289 }
290 // Find name similar to typeName not in names, ditto for identifierName.
291 if (identifierName == null || identifierName.isEmpty) {
292 String candidate = typeName == null || typeName.isEmpty ? _C_PARAMNAME : t ypeName.toLowerCase();
293 _pParamName(_makeNonconflictingName(candidate, names));
294 } else {
295 _pParamName(_makeNonconflictingName(identifierName, names));
296 if (typeName != null && !typeName.isEmpty) {
297 _pParamName(_makeNonconflictingName(typeName.toLowerCase(), names));
298 }
299 }
300 }
301
302 void _analyzePositionalArgument(ArgumentList args, SimpleIdentifier identifier ) {
303 // Show parameter name only if there is nothing to complete, so that if ther e is only
304 // one match, we won't to force user to choose.
305 if (!StringUtils.isEmpty(identifier.name)) {
306 return;
307 }
308 // prepare parameters
309 List<ParameterElement> parameters = _getParameterElements(args);
310 if (parameters == null) {
311 return;
312 }
313 // show current parameter
314 int argIndex = args.arguments.indexOf(identifier);
315 if (argIndex == -1) {
316 argIndex = 0;
317 }
318 if (argIndex >= 0 && argIndex < parameters.length) {
319 ParameterElement parameter = parameters[argIndex];
320 if (parameter.parameterKind != ParameterKind.NAMED) {
321 String parameterName = parameter.displayName;
322 CompletionProposal prop = _createProposal4(ProposalKind.OPTIONAL_ARGUMEN T);
323 prop.setCompletion(parameterName);
324 prop.setParameterName(parameterName);
325 prop.setParameterType(parameter.type.displayName);
326 prop.setLocation(identifier.offset);
327 prop.setReplacementLength(identifier.length);
328 prop.setRelevance(CompletionProposal.RELEVANCE_HIGH);
329 _requestor.accept(prop);
330 }
331 }
332 }
333
334 void _analyzePrefixedAccess(Expression receiver, SimpleIdentifier completionNo de) {
335 if (receiver is ThisExpression && !_state._isThisAllowed) {
336 return;
337 }
338 DartType receiverType = _typeOf2(receiver);
339 bool forSuper = receiver is SuperExpression;
340 _analyzePrefixedAccess2(receiverType, forSuper, completionNode);
341 }
342
343 void _analyzePrefixedAccess2(DartType receiverType, bool forSuper, SimpleIdent ifier completionNode) {
344 if (receiverType != null) {
345 // Complete x.!y
346 Element rcvrTypeElem = receiverType.element;
347 if (receiverType.isBottom) {
348 receiverType = objectType;
349 }
350 if (receiverType.isDynamic) {
351 receiverType = objectType;
352 }
353 if (receiverType is InterfaceType) {
354 _prefixedAccess(receiverType, forSuper, completionNode);
355 } else if (rcvrTypeElem is TypeParameterElement) {
356 TypeParameterElement typeParamElem = rcvrTypeElem;
357 _analyzePrefixedAccess2(typeParamElem.bound, false, completionNode);
358 }
359 }
360 }
361
362 void _analyzeReceiver(SimpleIdentifier identifier) {
363 // Completion x!.y
364 _filter = _createFilter(identifier);
365 CompletionEngine_NameCollector names = _collectIdentifiersVisibleAt(identifi er);
366 for (Element element in names.uniqueElements) {
367 _proposeName(element, identifier, names);
368 }
369 }
370
371 void _analyzeSuperConstructorInvocation(SuperConstructorInvocation node) {
372 ClassDeclaration enclosingClassNode = node.getAncestor((node) => node is Cla ssDeclaration);
373 if (enclosingClassNode != null) {
374 ClassElement enclosingClassElement = enclosingClassNode.element;
375 if (enclosingClassElement != null) {
376 ClassElement superClassElement = enclosingClassElement.supertype.element ;
377 _constructorReference(superClassElement, node.constructorName);
378 }
379 }
380 }
381
382 void _analyzeTypeName(SimpleIdentifier identifier, SimpleIdentifier nameIdent) {
383 _filter = _createFilter(identifier);
384 String name = nameIdent == null ? "" : nameIdent.name;
385 List<Element> types = _findAllTypes(currentLibrary, TopLevelNamesKind.DECLAR ED_AND_IMPORTS);
386 for (Element type in types) {
387 if (_state._isForMixin) {
388 if (type is! ClassElement) {
389 continue;
390 }
391 ClassElement classElement = type as ClassElement;
392 if (!classElement.isValidMixin) {
393 continue;
394 }
395 }
396 if (type.displayName == name) {
397 continue;
398 }
399 _pName(type, nameIdent);
400 }
401 if (!_state._isForMixin) {
402 ClassDeclaration classDecl = identifier.getAncestor((node) => node is Clas sDeclaration);
403 if (classDecl != null) {
404 ClassElement classElement = classDecl.element;
405 for (TypeParameterElement param in classElement.typeParameters) {
406 _pName(param, nameIdent);
407 }
408 }
409 }
410 List<Element> prefixes = _findAllPrefixes();
411 for (Element prefix in prefixes) {
412 _pName(prefix, nameIdent);
413 }
414 if (_state._isDynamicAllowed) {
415 _pDynamic();
416 }
417 if (_state._isVarAllowed) {
418 _pVar();
419 }
420 if (_state._isVoidAllowed) {
421 _pVoid();
422 }
423 }
424
425 void _constructorReference(ClassElement classElement, SimpleIdentifier identif ier) {
426 // Complete identifier when it refers to a constructor defined in classEleme nt.
427 _filter = _createFilter(identifier);
428 for (ConstructorElement cons in classElement.constructors) {
429 if (_state._isCompileTimeConstantRequired == cons.isConst && _filterAllows (cons)) {
430 _pExecutable2(cons, identifier, false);
431 }
432 }
433 }
434
435 void _directAccess(ClassElement classElement, SimpleIdentifier identifier) {
436 _filter = _createFilter(identifier);
437 CompletionEngine_NameCollector names = _createNameCollector();
438 names.addLocalNames(identifier);
439 names._addNamesDefinedByHierarchy(classElement, false);
440 names._addTopLevelNames2(currentLibrary, TopLevelNamesKind.DECLARED_AND_IMPO RTS);
441 _proposeNames(names, identifier);
442 }
443
444 void _dispatchPrefixAnalysis(InstanceCreationExpression node) {
445 // prepare ClassElement
446 ClassElement classElement;
447 {
448 Element typeElement = _typeOf2(node).element;
449 if (typeElement is! ClassElement) {
450 return;
451 }
452 classElement = typeElement as ClassElement;
453 }
454 // prepare constructor name
455 Identifier typeName = node.constructorName.type.name;
456 SimpleIdentifier identifier = null;
457 if (typeName is SimpleIdentifier) {
458 identifier = typeName;
459 } else if (typeName is PrefixedIdentifier) {
460 identifier = typeName.identifier;
461 }
462 if (identifier == null) {
463 identifier = _createIdent(node);
464 }
465 // analyze constructor name
466 _analyzeConstructorTypeName(identifier);
467 _constructorReference(classElement, identifier);
468 }
469
470 void _dispatchPrefixAnalysis2(MethodInvocation node) {
471 // This might be a library prefix on a top-level function
472 Expression expr = node.realTarget;
473 if (expr is SimpleIdentifier) {
474 SimpleIdentifier ident = expr;
475 if (ident.bestElement is PrefixElement) {
476 _prefixedAccess2(ident, node.methodName);
477 return;
478 } else if (ident.bestElement is ClassElement) {
479 _state._areInstanceReferencesProhibited = true;
480 _state._areStaticReferencesProhibited = false;
481 } else {
482 _state._areInstanceReferencesProhibited = false;
483 _state._areStaticReferencesProhibited = true;
484 }
485 }
486 if (expr == null) {
487 _analyzeLocalName(_createIdent(node));
488 } else {
489 _analyzePrefixedAccess(expr, node.methodName);
490 }
491 }
492
493 void _dispatchPrefixAnalysis3(PrefixedIdentifier node, SimpleIdentifier identi fier) {
494 SimpleIdentifier receiverName = node.prefix;
495 Element receiver = receiverName.bestElement;
496 if (receiver == null) {
497 _prefixedAccess2(receiverName, identifier);
498 return;
499 }
500 while (true) {
501 if (receiver.kind == ElementKind.PREFIX || receiver.kind == ElementKind.IM PORT) {
502 // Complete lib_prefix.name
503 _prefixedAccess2(receiverName, identifier);
504 } else {
505 {
506 DartType receiverType;
507 DartType propType = _typeOf2(receiverName);
508 if (propType == null || propType.isDynamic) {
509 receiverType = _typeOf(receiver);
510 } else {
511 DartType declType = _typeOf(receiver);
512 if (propType.isMoreSpecificThan(declType)) {
513 receiverType = propType;
514 } else {
515 receiverType = declType;
516 }
517 }
518 _analyzePrefixedAccess2(receiverType, false, identifier);
519 break;
520 }
521 }
522 break;
523 }
524 }
525
526 void _fieldReference(ClassElement classElement, SimpleIdentifier identifier) {
527 // Complete identifier when it refers to a constructor defined in classEleme nt.
528 _filter = _createFilter(identifier);
529 for (FieldElement cons in classElement.fields) {
530 if (_filterAllows(cons)) {
531 _pField(cons, identifier, classElement);
532 }
533 }
534 }
535
536 void _namedConstructorReference(ClassElement classElement, SimpleIdentifier id entifier) {
537 // Complete identifier when it refers to a named constructor defined in clas sElement.
538 if (_filter == null) {
539 _filter = _createFilter(identifier);
540 }
541 for (ConstructorElement cons in classElement.constructors) {
542 if (!_isVisible(cons)) {
543 continue;
544 }
545 if (_state._isCompileTimeConstantRequired && !cons.isConst) {
546 continue;
547 }
548 _pNamedConstructor(classElement, cons, identifier);
549 }
550 }
551
552 void _namespacePubReference(NamespaceDirective node, Set<String> packageUris) {
553 // no import URI or package:
554 String prefix = _filter._prefix;
555 List<String> prefixStrings = prefix.split(":");
556 if (!prefix.isEmpty && !"package:".startsWith(prefixStrings[0])) {
557 return;
558 }
559 // if no URI yet, propose package:
560 if (prefix.isEmpty) {
561 _pImportUriWithScheme(node, "package:");
562 return;
563 }
564 // check "packages" folder for package libraries that are not added to Analy sisContext
565 {
566 Source contextSource = _context.source;
567 if (contextSource is FileBasedSource) {
568 FileBasedSource contextFileSource = contextSource;
569 String contextFilePath = contextFileSource.fullName;
570 JavaFile contextFile = new JavaFile(contextFilePath);
571 JavaFile contextFolder = contextFile.getParentFile();
572 JavaFile contextPackages = new JavaFile.relative(contextFolder, "package s");
573 if (contextPackages.isDirectory()) {
574 for (JavaFile packageFolder in contextPackages.listFiles()) {
575 String packageName = packageFolder.getName();
576 String packageLibName = "${packageName}.dart";
577 JavaFile packageFile = new JavaFile.relative(packageFolder, packageL ibName);
578 if (packageFile.exists() && packageFile.isFile()) {
579 packageUris.add("package:${packageName}/${packageLibName}");
580 }
581 }
582 }
583 }
584 }
585 // add known package: URIs
586 for (String uri in packageUris) {
587 if (_filterDisallows2(uri)) {
588 continue;
589 }
590 CompletionProposal prop = _createProposal4(ProposalKind.IMPORT);
591 prop.setCompletion(uri);
592 // put "lib" before "lib/src"
593 if (!uri.contains("/src/")) {
594 prop.setRelevance(CompletionProposal.RELEVANCE_HIGH);
595 }
596 // done
597 _requestor.accept(prop);
598 }
599 }
600
601 void _namespaceReference(NamespaceDirective node, SimpleStringLiteral literal) {
602 String lit = literal.literal.lexeme;
603 if (!lit.isEmpty) {
604 lit = lit.substring(1, Math.max(lit.length - 1, 0));
605 }
606 _filter = _createFilter(new Ident.con2(node, lit, literal.offset + 1));
607 Set<String> packageUris = new Set();
608 List<LibraryElement> libraries = new List<LibraryElement>();
609 List<LibraryElement> librariesInLib = new List<LibraryElement>();
610 String currentLibraryName = currentLibrary.source.fullName;
611 AnalysisContext ac = analysisContext;
612 List<Source> sources = ac.librarySources;
613 for (Source s in sources) {
614 String sName = s.fullName;
615 // skip current library
616 if (currentLibraryName == sName) {
617 continue;
618 }
619 // ".pub-cache/..../unittest-0.8.8/lib/unittest.dart" -> "package:unittest /unittest.dart"
620 {
621 Uri uri = ac.sourceFactory.restoreUri(s);
622 if (uri != null) {
623 String uriString = uri.toString();
624 if (uriString.startsWith("package:")) {
625 packageUris.add(uriString);
626 }
627 }
628 }
629 LibraryElement lib = ac.getLibraryElement(s);
630 if (lib == null) {
631 continue;
632 } else if (_isUnitInLibFolder(lib.definingCompilationUnit)) {
633 librariesInLib.add(lib);
634 } else {
635 libraries.add(lib);
636 }
637 }
638 _namespaceSdkReference(node);
639 _namespacePubReference(node, packageUris);
640 }
641
642 void _namespaceSdkReference(NamespaceDirective node) {
643 String prefix = _filter._prefix;
644 List<String> prefixStrings = prefix.split(":");
645 if (!prefix.isEmpty && !"dart:".startsWith(prefixStrings[0])) {
646 return;
647 }
648 if (prefix.isEmpty) {
649 _pImportUriWithScheme(node, "dart:");
650 return;
651 }
652 // add DartSdk libraries
653 DartSdk dartSdk = analysisContext.sourceFactory.dartSdk;
654 for (SdkLibrary library in dartSdk.sdkLibraries) {
655 String name = library.shortName;
656 // ignore internal
657 if (library.isInternal) {
658 continue;
659 }
660 // ignore implementation
661 if (library.isImplementation) {
662 continue;
663 }
664 // standard libraries name name starting with "dart:"
665 name = StringUtils.removeStart(name, "dart:");
666 // ignore private libraries
667 if (Identifier.isPrivateName(name)) {
668 continue;
669 }
670 // add with "dart:" prefix
671 _pName3("dart:${name}", ProposalKind.IMPORT);
672 }
673 }
674
675 void _operatorAccess(Expression expr, SimpleIdentifier identifier) {
676 _state._requiresOperators();
677 _analyzePrefixedAccess(expr, identifier);
678 }
679
680 void _prefixedAccess(InterfaceType type, bool forSuper, SimpleIdentifier ident ifier) {
681 // Complete identifier when it refers to field or method in classElement.
682 _filter = _createFilter(identifier);
683 CompletionEngine_NameCollector names = _createNameCollector();
684 if (_state._areInstanceReferencesProhibited) {
685 names._addNamesDefinedByType2(type);
686 } else {
687 names._addNamesDefinedByHierarchy2(type, forSuper);
688 }
689 _proposeNames(names, identifier);
690 }
691
692 void _prefixedAccess2(SimpleIdentifier prefixName, SimpleIdentifier identifier ) {
693 if (_filter == null) {
694 _filter = _createFilter(identifier);
695 }
696 CompletionEngine_NameCollector names = _createNameCollector();
697 List<ImportElement> prefixImports = _importsWithName(prefixName);
698 // Library prefixes do not have a unique AST representation so we need to fu dge state vars.
699 bool litsAllowed = _state._areLiteralsAllowed;
700 _state._areLiteralsAllowed = false;
701 names._addTopLevelNames(prefixImports, TopLevelNamesKind.DECLARED_AND_EXPORT S);
702 _state._areLiteralsAllowed = litsAllowed;
703 _proposeNames(names, identifier);
704 }
705
706 List<InterfaceType> _allSubtypes(ClassElement classElement) {
707 // TODO(scheglov) translate it
708 return [];
709 }
710
711 CompletionEngine_NameCollector _collectIdentifiersVisibleAt(AstNode ident) {
712 CompletionEngine_NameCollector names = _createNameCollector();
713 ScopedNameFinder finder = new ScopedNameFinder(_completionLocation());
714 ident.accept(finder);
715 names.addAll(finder.locals.values);
716 Declaration decl = finder.declaration;
717 if (decl != null && decl.parent is ClassDeclaration) {
718 ClassElement classElement = (decl.parent as ClassDeclaration).element;
719 names._addNamesDefinedByHierarchy(classElement, false);
720 }
721 names._addTopLevelNames2(currentLibrary, TopLevelNamesKind.DECLARED_AND_IMPO RTS);
722 return names;
723 }
724
725 CompletionEngine_NameCollector _collectTopLevelElementVisibleAt(AstNode ident) {
726 CompletionEngine_NameCollector names = _createNameCollector();
727 names._addTopLevelNames2(currentLibrary, TopLevelNamesKind.DECLARED_AND_IMPO RTS);
728 return names;
729 }
730
731 int _completionLocation() => _context.selectionOffset;
732
733 int _completionTokenOffset() => _completionLocation() - _filter._prefix.length ;
734
735 List<FormalParameter> _copyWithout(NodeList oldList, AstNode deletion) {
736 List<FormalParameter> newList = new List<FormalParameter>();
737 oldList.accept(new GeneralizingAstVisitor_CompletionEngine_copyWithout(delet ion, newList));
738 return newList;
739 }
740
741 Filter _createFilter(SimpleIdentifier ident) => new Filter.con1(ident, _contex t.selectionOffset);
742
743 Ident _createIdent(AstNode node) => new Ident.con1(node, _completionLocation() );
744
745 CompletionEngine_NameCollector _createNameCollector() => new CompletionEngine_ NameCollector(this);
746
747 CompletionProposal _createProposal(Element element) {
748 String completion = element.displayName;
749 return _createProposal3(element, completion);
750 }
751
752 CompletionProposal _createProposal2(Element element, SimpleIdentifier identifi er) {
753 // Create a completion proposal for the element: variable, field, class, fun ction.
754 if (_filterDisallows(element)) {
755 return null;
756 }
757 CompletionProposal prop = _createProposal(element);
758 Element container = element.enclosingElement;
759 if (container != null) {
760 prop.setDeclaringType(container.displayName);
761 }
762 DartType type = _typeOf(element);
763 if (type != null) {
764 prop.setReturnType(type.name);
765 }
766 if (identifier != null) {
767 prop.setReplacementLengthIdentifier(identifier.length);
768 }
769 return prop;
770 }
771
772 CompletionProposal _createProposal3(Element element, String completion) {
773 ProposalKind kind = _proposalKindOf(element);
774 CompletionProposal prop = _createProposal4(kind);
775 prop.setElement(element);
776 prop.setCompletion(completion);
777 prop.setDeprecated(_isDeprecated(element));
778 if (_isPrivate(element)) {
779 prop.setRelevance(CompletionProposal.RELEVANCE_LOW);
780 }
781 if (_filter._isSameCasePrefix(element.name)) {
782 prop.incRelevance();
783 }
784 return prop;
785 }
786
787 CompletionProposal _createProposal4(ProposalKind kind) => _factory.createCompl etionProposal(kind, _completionTokenOffset());
788
789 List<LibraryElement> _currentLibraryList() {
790 Set<LibraryElement> libraries = new Set<LibraryElement>();
791 LibraryElement curLib = currentLibrary;
792 libraries.add(curLib);
793 Queue<LibraryElement> queue = new Queue<LibraryElement>();
794 queue.addAll(curLib.importedLibraries);
795 _currentLibraryLister(queue, libraries);
796 return new List.from(libraries);
797 }
798
799 void _currentLibraryLister(Queue<LibraryElement> queue, Set<LibraryElement> li braries) {
800 while (!queue.isEmpty) {
801 LibraryElement sourceLib = queue.removeFirst();
802 libraries.add(sourceLib);
803 List<LibraryElement> expLibs = sourceLib.exportedLibraries;
804 for (LibraryElement lib in expLibs) {
805 if (!libraries.contains(lib)) {
806 queue.add(lib);
807 }
808 }
809 }
810 }
811
812 bool _filterAllows(Element element) => _filter._match(element);
813
814 bool _filterDisallows(Element element) => !_filter._match(element);
815
816 bool _filterDisallows2(String name) => !_filter._match2(name);
817
818 List<Element> _findAllNotTypes(List<Element> elements) {
819 elements = [];
820 for (JavaIterator<Element> I = new JavaIterator(elements); I.hasNext;) {
821 Element element = I.next();
822 ElementKind kind = element.kind;
823 if (kind == ElementKind.FUNCTION || kind == ElementKind.TOP_LEVEL_VARIABLE || kind == ElementKind.GETTER || kind == ElementKind.SETTER) {
824 continue;
825 }
826 I.remove();
827 }
828 return new List.from(elements);
829 }
830
831 List<Element> _findAllPrefixes() {
832 LibraryElement lib = _context.compilationUnitElement.enclosingElement;
833 return lib.prefixes;
834 }
835
836 List<Element> _findAllTypes(LibraryElement library, TopLevelNamesKind topKind) {
837 List<Element> elements = _findTopLevelElements(library, topKind);
838 return _findAllTypes2(elements);
839 }
840
841 List<Element> _findAllTypes2(List<Element> elements) {
842 elements = [];
843 for (JavaIterator<Element> I = new JavaIterator(elements); I.hasNext;) {
844 Element element = I.next();
845 ElementKind kind = element.kind;
846 if (kind == ElementKind.CLASS || kind == ElementKind.FUNCTION_TYPE_ALIAS) {
847 continue;
848 }
849 I.remove();
850 }
851 return new List.from(elements);
852 }
853
854 List<Element> _findTopLevelElements(LibraryElement library, TopLevelNamesKind topKind) {
855 List<Element> elements = [];
856 if (topKind == TopLevelNamesKind.DECLARED_AND_IMPORTS) {
857 elements.addAll(CorrectionUtils.getTopLevelElements(library));
858 for (ImportElement imp in library.imports) {
859 elements.addAll(CorrectionUtils.getImportNamespace(imp).values);
860 }
861 _removeNotMatchingFilter(elements);
862 }
863 if (topKind == TopLevelNamesKind.DECLARED_AND_EXPORTS) {
864 elements.addAll(CorrectionUtils.getExportNamespace2(library).values);
865 _removeNotMatchingFilter(elements);
866 }
867 return elements;
868 }
869
870 AnalysisContext get analysisContext => _context.compilationUnitElement.context ;
871
872 LibraryElement get currentLibrary => _context.compilationUnitElement.enclosing Element;
873
874 FunctionType _getFunctionType(Element element) {
875 if (element is ExecutableElement) {
876 ExecutableElement executableElement = element;
877 return executableElement.type;
878 }
879 if (element is VariableElement) {
880 VariableElement variableElement = element;
881 DartType type = variableElement.type;
882 if (type is FunctionType) {
883 return type;
884 }
885 }
886 return null;
887 }
888
889 ClassElement get objectClassElement => typeProvider.objectType.element;
890
891 InterfaceType get objectType => typeProvider.objectType;
892
893 List<ParameterElement> _getParameterElements(ArgumentList args) {
894 List<ParameterElement> parameters = null;
895 AstNode argsParent = args.parent;
896 if (argsParent is MethodInvocation) {
897 MethodInvocation invocation = argsParent;
898 Element nameElement = invocation.methodName.staticElement;
899 FunctionType functionType = _getFunctionType(nameElement);
900 if (functionType != null) {
901 parameters = functionType.parameters;
902 }
903 }
904 if (argsParent is InstanceCreationExpression) {
905 InstanceCreationExpression creation = argsParent;
906 ConstructorElement element = creation.staticElement;
907 if (element != null) {
908 parameters = element.parameters;
909 }
910 }
911 if (argsParent is Annotation) {
912 Annotation annotation = argsParent;
913 Element element = annotation.element;
914 if (element is ConstructorElement) {
915 parameters = element.parameters;
916 }
917 }
918 return parameters;
919 }
920
921 TypeProvider get typeProvider {
922 AnalysisContext analysisContext = _context.compilationUnitElement.context;
923 try {
924 return (analysisContext as InternalAnalysisContext).typeProvider;
925 } on AnalysisException catch (exception) {
926 // TODO(brianwilkerson) Figure out the right thing to do if the core canno t be resolved.
927 return null;
928 }
929 }
930
931 bool get hasErrorBeforeCompletionLocation {
932 List<AnalysisError> errors = _context.errors;
933 if (errors == null || errors.length == 0) {
934 return false;
935 }
936 return errors[0].offset <= _completionLocation();
937 }
938
939 List<ImportElement> _importsWithName(SimpleIdentifier libName) {
940 String name = libName.name;
941 List<ImportElement> imports = [];
942 for (ImportElement imp in currentLibrary.imports) {
943 PrefixElement prefix = imp.prefix;
944 if (prefix != null) {
945 String impName = prefix.displayName;
946 if (name == impName) {
947 imports.add(imp);
948 }
949 }
950 }
951 return new List.from(imports);
952 }
953
954 bool _isCompletingKeyword(Token keyword) {
955 if (keyword == null) {
956 return false;
957 }
958 int completionLoc = _context.selectionOffset;
959 if (completionLoc >= keyword.offset && completionLoc <= keyword.end) {
960 return true;
961 }
962 return false;
963 }
964
965 bool _isCompletionAfter(int loc) => loc <= _completionLocation();
966
967 bool _isCompletionBefore(int loc) => _completionLocation() <= loc;
968
969 bool _isCompletionBetween(int firstLoc, int secondLoc) => _isCompletionAfter(f irstLoc) && _isCompletionBefore(secondLoc);
970
971 bool _isDeprecated(Element element) => element != null && element.isDeprecated ;
972
973 bool _isInCurrentLibrary(Element element) {
974 LibraryElement libElement = currentLibrary;
975 return identical(element.library, libElement);
976 }
977
978 bool _isUnitInLibFolder(CompilationUnitElement cu) {
979 String pathString = cu.source.fullName;
980 if (pathString.indexOf("/lib/") == -1) {
981 return false;
982 }
983 return true;
984 }
985
986 bool _isVisible(Element element) => !_isPrivate(element) || _isInCurrentLibrar y(element);
987
988 String _makeNonconflictingName(String candidate, List<String> names) {
989 String possibility = candidate;
990 int count = 0;
991 loop: while (true) {
992 String name = count == 0 ? possibility : "${possibility}${count}";
993 for (String conflict in names) {
994 if (name == conflict) {
995 count += 1;
996 continue loop;
997 }
998 }
999 return name;
1000 }
1001 }
1002
1003 void _pArgumentList(CompletionProposal proposal, int offset, int len) {
1004 // prepare parameters
1005 List<String> parameterNames = proposal.parameterNames;
1006 if (parameterNames.length == 0) {
1007 return;
1008 }
1009 // fill arguments proposal
1010 CompletionProposal prop = _createProposal4(ProposalKind.ARGUMENT_LIST);
1011 prop.setElement(proposal.element);
1012 prop.setCompletion(proposal.completion).setReturnType(proposal.returnType);
1013 prop.setParameterNames(parameterNames);
1014 prop.setParameterTypes(proposal.parameterTypes);
1015 prop.setParameterStyle(proposal.positionalParameterCount, proposal.hasNamed, proposal.hasPositional);
1016 prop.setReplacementLength(0).setLocation(_completionLocation());
1017 prop.setRelevance(CompletionProposal.RELEVANCE_HIGH);
1018 _requestor.accept(prop);
1019 }
1020
1021 void _pDynamic() {
1022 _pWord(_C_DYNAMIC, ProposalKind.VARIABLE);
1023 }
1024
1025 void _pExecutable(Element element, FunctionType functionType, SimpleIdentifier identifier, bool isPotentialMatch) {
1026 // Create a completion proposal for the element: function, method, getter, s etter, constructor.
1027 String name = element.displayName;
1028 if (name.isEmpty) {
1029 return;
1030 }
1031 if (_filterDisallows(element)) {
1032 return;
1033 }
1034 if (!_isVisible(element)) {
1035 return;
1036 }
1037 // May be we are in argument of function type parameter, propose function re ference.
1038 if (_state._targetParameter != null) {
1039 DartType parameterType = _state._targetParameter.type;
1040 if (parameterType is FunctionType) {
1041 if (functionType.isAssignableTo(parameterType)) {
1042 _pName2(name, element, CompletionProposal.RELEVANCE_HIGH, ProposalKind .METHOD_NAME);
1043 }
1044 }
1045 }
1046 CompletionProposal prop = _createProposal(element);
1047 prop.setPotentialMatch(isPotentialMatch);
1048 if (isPotentialMatch) {
1049 prop.setRelevance(CompletionProposal.RELEVANCE_LOW);
1050 }
1051 _setParameterInfo(functionType, prop);
1052 prop.setCompletion(name).setReturnType(functionType.returnType.displayName);
1053 // If there is already argument list, then update only method name.
1054 if (identifier.parent is MethodInvocation && (identifier.parent as MethodInv ocation).argumentList != null) {
1055 prop.setKind(ProposalKind.METHOD_NAME);
1056 }
1057 Element container = element.enclosingElement;
1058 if (container != null) {
1059 prop.setDeclaringType(container.displayName);
1060 }
1061 _requestor.accept(prop);
1062 }
1063
1064 void _pExecutable2(ExecutableElement element, SimpleIdentifier identifier, boo l isPotentialMatch) {
1065 _pExecutable(element, element.type, identifier, isPotentialMatch);
1066 }
1067
1068 void _pExecutable3(VariableElement element, SimpleIdentifier identifier) {
1069 // Create a completion proposal for the element: top-level variable.
1070 String name = element.displayName;
1071 if (name.isEmpty || _filterDisallows(element)) {
1072 return;
1073 }
1074 CompletionProposal prop = _createProposal(element);
1075 if (element.type != null) {
1076 prop.setReturnType(element.type.name);
1077 }
1078 Element container = element.enclosingElement;
1079 if (container != null) {
1080 prop.setDeclaringType(container.displayName);
1081 }
1082 if (identifier != null) {
1083 prop.setReplacementLengthIdentifier(identifier.length);
1084 }
1085 _requestor.accept(prop);
1086 }
1087
1088 void _pFalse() {
1089 _pWord(_C_FALSE, ProposalKind.VARIABLE);
1090 }
1091
1092 void _pField(FieldElement element, SimpleIdentifier identifier, ClassElement c lassElement) {
1093 // Create a completion proposal for the element: field only.
1094 if (_filterDisallows(element)) {
1095 return;
1096 }
1097 CompletionProposal prop = _createProposal(element);
1098 Element container = element.enclosingElement;
1099 prop.setDeclaringType(container.displayName);
1100 _requestor.accept(prop);
1101 }
1102
1103 /**
1104 * Proposes URI with the given scheme for the given [NamespaceDirective].
1105 */
1106 void _pImportUriWithScheme(NamespaceDirective node, String uriScheme) {
1107 String newUri = "${uriScheme}${new String.fromCharCode(CompletionProposal.CU RSOR_MARKER)}";
1108 if (node.uri.isSynthetic) {
1109 newUri = "'${newUri}'";
1110 if (node.semicolon == null || node.semicolon.isSynthetic) {
1111 newUri += ";";
1112 }
1113 }
1114 if (_context.selectionOffset == node.keyword.end) {
1115 newUri = " ${newUri}";
1116 }
1117 _pName3(newUri, ProposalKind.IMPORT);
1118 }
1119
1120 void _pKeyword(Token keyword) {
1121 _filter = new Filter.con2(keyword.lexeme, keyword.offset, _completionLocatio n());
1122 // This isn't as useful as it might seem. It only works in the case that com pletion
1123 // is requested on an existing recognizable keyword.
1124 // TODO: Add keyword proposal kind
1125 CompletionProposal prop = _createProposal4(ProposalKind.LIBRARY_PREFIX);
1126 prop.setCompletion(keyword.lexeme);
1127 _requestor.accept(prop);
1128 }
1129
1130 void _pName(Element element, SimpleIdentifier identifier) {
1131 CompletionProposal prop = _createProposal2(element, identifier);
1132 if (prop != null) {
1133 _requestor.accept(prop);
1134 }
1135 }
1136
1137 void _pName2(String name, Element element, int relevance, ProposalKind kind) {
1138 if (_filterDisallows2(name)) {
1139 return;
1140 }
1141 CompletionProposal prop = _createProposal4(kind);
1142 prop.setRelevance(relevance);
1143 prop.setCompletion(name);
1144 prop.setElement(element);
1145 _requestor.accept(prop);
1146 }
1147
1148 void _pName3(String name, ProposalKind kind) {
1149 if (_filterDisallows2(name)) {
1150 return;
1151 }
1152 CompletionProposal prop = _createProposal4(kind);
1153 prop.setCompletion(name);
1154 _requestor.accept(prop);
1155 }
1156
1157 void _pNamedConstructor(ClassElement classElement, ConstructorElement element, SimpleIdentifier identifier) {
1158 // Create a completion proposal for the named constructor.
1159 String name = classElement.displayName;
1160 if (!element.displayName.isEmpty) {
1161 name += ".${element.displayName}";
1162 }
1163 if (_filterDisallows2(name)) {
1164 return;
1165 }
1166 CompletionProposal prop = _createProposal3(element, name);
1167 _setParameterInfo(element.type, prop);
1168 prop.setReturnType(element.type.returnType.name);
1169 Element container = element.enclosingElement;
1170 prop.setDeclaringType(container.displayName);
1171 if (identifier != null) {
1172 prop.setReplacementLengthIdentifier(identifier.length);
1173 }
1174 _requestor.accept(prop);
1175 }
1176
1177 void _pNull() {
1178 _pWord(_C_NULL, ProposalKind.VARIABLE);
1179 }
1180
1181 void _pParamName(String name) {
1182 if (_filterDisallows2(name)) {
1183 return;
1184 }
1185 CompletionProposal prop = _createProposal4(ProposalKind.PARAMETER);
1186 prop.setCompletion(name);
1187 _requestor.accept(prop);
1188 }
1189
1190 ProposalKind _proposalKindOf(Element element) {
1191 ProposalKind kind;
1192 while (true) {
1193 if (element.kind == ElementKind.CONSTRUCTOR) {
1194 kind = ProposalKind.CONSTRUCTOR;
1195 } else if (element.kind == ElementKind.FUNCTION) {
1196 kind = ProposalKind.FUNCTION;
1197 } else if (element.kind == ElementKind.METHOD) {
1198 kind = ProposalKind.METHOD;
1199 } else if (element.kind == ElementKind.GETTER) {
1200 kind = ProposalKind.GETTER;
1201 } else if (element.kind == ElementKind.SETTER) {
1202 kind = ProposalKind.SETTER;
1203 } else if (element.kind == ElementKind.CLASS) {
1204 kind = ProposalKind.CLASS;
1205 } else if (element.kind == ElementKind.FIELD) {
1206 kind = ProposalKind.FIELD;
1207 } else if (element.kind == ElementKind.IMPORT) {
1208 kind = ProposalKind.IMPORT;
1209 } else if (element.kind == ElementKind.PARAMETER) {
1210 kind = ProposalKind.PARAMETER;
1211 } else if (element.kind == ElementKind.PREFIX) {
1212 kind = ProposalKind.LIBRARY_PREFIX;
1213 } else if (element.kind == ElementKind.FUNCTION_TYPE_ALIAS) {
1214 kind = ProposalKind.CLASS_ALIAS;
1215 } else if (element.kind == ElementKind.TYPE_PARAMETER) {
1216 kind = ProposalKind.TYPE_PARAMETER;
1217 } else if (element.kind == ElementKind.LOCAL_VARIABLE || element.kind == E lementKind.TOP_LEVEL_VARIABLE) {
1218 kind = ProposalKind.VARIABLE;
1219 } else {
1220 throw new IllegalArgumentException();
1221 }
1222 break;
1223 }
1224 return kind;
1225 }
1226
1227 void _proposeCombinator(Combinator node, SimpleIdentifier identifier) {
1228 _filter = _createFilter(identifier);
1229 NamespaceDirective directive = node.parent as NamespaceDirective;
1230 LibraryElement libraryElement = directive.uriElement;
1231 if (libraryElement != null) {
1232 // prepare Elements with unique names
1233 CompletionEngine_NameCollector nameCollector = _createNameCollector();
1234 Iterable<Element> elements = CorrectionUtils.getExportNamespace2(libraryEl ement).values;
1235 for (Element element in elements) {
1236 if (_filterDisallows(element)) {
1237 continue;
1238 }
1239 nameCollector._mergeName(element);
1240 }
1241 // propose each Element
1242 for (Element element in nameCollector.uniqueElements) {
1243 CompletionProposal proposal = _createProposal(element);
1244 if (proposal.kind == ProposalKind.FUNCTION) {
1245 proposal.setKind(ProposalKind.METHOD_NAME);
1246 }
1247 _requestor.accept(proposal);
1248 }
1249 }
1250 }
1251
1252 void _proposeName(Element element, SimpleIdentifier identifier, CompletionEngi ne_NameCollector names) {
1253 while (true) {
1254 if (element.kind == ElementKind.FUNCTION || element.kind == ElementKind.GE TTER || element.kind == ElementKind.METHOD || element.kind == ElementKind.SETTER ) {
1255 ExecutableElement candidate = element as ExecutableElement;
1256 _pExecutable2(candidate, identifier, names._isPotentialMatch(candidate)) ;
1257 } else if (element.kind == ElementKind.LOCAL_VARIABLE || element.kind == E lementKind.PARAMETER || element.kind == ElementKind.TOP_LEVEL_VARIABLE) {
1258 FunctionType functionType = _getFunctionType(element);
1259 if (functionType != null) {
1260 _pExecutable(element, functionType, identifier, names._isPotentialMatc h(element));
1261 } else {
1262 VariableElement var2 = element as VariableElement;
1263 _pExecutable3(var2, identifier);
1264 }
1265 } else if (element.kind == ElementKind.CLASS) {
1266 _pName(element, identifier);
1267 } else {
1268 }
1269 break;
1270 }
1271 }
1272
1273 void _proposeNames(CompletionEngine_NameCollector names, SimpleIdentifier iden tifier) {
1274 for (Element element in names.uniqueElements) {
1275 _proposeName(element, identifier, names);
1276 }
1277 }
1278
1279 void _pTrue() {
1280 _pWord(_C_TRUE, ProposalKind.VARIABLE);
1281 }
1282
1283 void _pVar() {
1284 _pWord(_C_VAR, ProposalKind.VARIABLE);
1285 }
1286
1287 void _pVoid() {
1288 _pWord(_C_VOID, ProposalKind.VARIABLE);
1289 }
1290
1291 void _pWord(String word, ProposalKind kind) {
1292 if (_filterDisallows2(word)) {
1293 return;
1294 }
1295 CompletionProposal prop = _createProposal4(kind);
1296 prop.setCompletion(word);
1297 _requestor.accept(prop);
1298 }
1299
1300 void _removeNotMatchingFilter(List<Element> elements) {
1301 if (_filter == null) {
1302 return;
1303 }
1304 _filter._makePattern();
1305 _filter._removeNotMatching(elements);
1306 }
1307
1308 void _setParameterInfo(FunctionType functionType, CompletionProposal prop) {
1309 List<String> params = new List<String>();
1310 List<String> types = new List<String>();
1311 bool named = false, positional = false;
1312 int posCount = 0;
1313 for (ParameterElement param in functionType.parameters) {
1314 if (!param.isSynthetic) {
1315 while (true) {
1316 if (param.parameterKind == ParameterKind.REQUIRED) {
1317 posCount += 1;
1318 } else if (param.parameterKind == ParameterKind.NAMED) {
1319 named = true;
1320 } else if (param.parameterKind == ParameterKind.POSITIONAL) {
1321 positional = true;
1322 }
1323 break;
1324 }
1325 params.add(param.displayName);
1326 types.add(param.type.toString());
1327 }
1328 }
1329 prop.setParameterNames(new List.from(params));
1330 prop.setParameterTypes(new List.from(types));
1331 prop.setParameterStyle(posCount, named, positional);
1332 }
1333
1334 SimpleIdentifier _typeDeclarationName(AstNode node) {
1335 AstNode parent = node;
1336 while (parent != null) {
1337 if (parent is ClassDeclaration) {
1338 return (parent as ClassDeclaration).name;
1339 }
1340 if (parent is ClassTypeAlias) {
1341 return (parent as ClassTypeAlias).name;
1342 }
1343 if (parent is FunctionTypeAlias) {
1344 return (parent as FunctionTypeAlias).name;
1345 }
1346 parent = parent.parent;
1347 }
1348 return null;
1349 }
1350
1351 DartType _typeOf(Element receiver) {
1352 DartType receiverType;
1353 while (true) {
1354 if (receiver.kind == ElementKind.FIELD || receiver.kind == ElementKind.PAR AMETER || receiver.kind == ElementKind.LOCAL_VARIABLE || receiver.kind == Elemen tKind.TOP_LEVEL_VARIABLE) {
1355 {
1356 VariableElement receiverElement = receiver as VariableElement;
1357 receiverType = receiverElement.type;
1358 break;
1359 }
1360 } else if (receiver.kind == ElementKind.GETTER) {
1361 PropertyAccessorElement accessor = receiver as PropertyAccessorElement;
1362 if (accessor.isSynthetic) {
1363 PropertyInducingElement inducer = accessor.variable;
1364 DartType inducerType = inducer.type;
1365 if (inducerType == null || inducerType.isDynamic) {
1366 receiverType = _typeSearch(inducer);
1367 if (receiverType != null) {
1368 break;
1369 }
1370 }
1371 }
1372 FunctionType accType = accessor.type;
1373 receiverType = accType == null ? null : accType.returnType;
1374 } else if (receiver.kind == ElementKind.CONSTRUCTOR || receiver.kind == El ementKind.FUNCTION || receiver.kind == ElementKind.METHOD || receiver.kind == El ementKind.SETTER) {
1375 {
1376 ExecutableElement receiverElement = receiver as ExecutableElement;
1377 FunctionType funType = receiverElement.type;
1378 receiverType = funType == null ? null : funType.returnType;
1379 break;
1380 }
1381 } else if (receiver.kind == ElementKind.CLASS) {
1382 {
1383 ClassElement receiverElement = receiver as ClassElement;
1384 receiverType = receiverElement.type;
1385 break;
1386 }
1387 } else if (receiver.kind == ElementKind.DYNAMIC) {
1388 {
1389 receiverType = DynamicTypeImpl.instance;
1390 break;
1391 }
1392 } else if (receiver.kind == ElementKind.FUNCTION_TYPE_ALIAS) {
1393 {
1394 FunctionTypeAliasElement receiverElement = receiver as FunctionTypeAli asElement;
1395 FunctionType funType = receiverElement.type;
1396 receiverType = funType == null ? null : funType.returnType;
1397 break;
1398 }
1399 } else {
1400 {
1401 receiverType = null;
1402 break;
1403 }
1404 }
1405 break;
1406 }
1407 return receiverType;
1408 }
1409
1410 DartType _typeOf2(Expression expr) {
1411 DartType type = expr.bestType;
1412 if (type.isDynamic) {
1413 List<DartType> result = new List<DartType>(1);
1414 CompletionEngine_AstNodeClassifier visitor = new AstNodeClassifier_Complet ionEngine_typeOf(this, result);
1415 expr.accept(visitor);
1416 if (result[0] != null) {
1417 return result[0];
1418 }
1419 }
1420 return type;
1421 }
1422
1423 DartType _typeOfContainingClass(AstNode node) {
1424 AstNode parent = node;
1425 while (parent != null) {
1426 if (parent is ClassDeclaration) {
1427 return (parent as ClassDeclaration).element.type;
1428 }
1429 parent = parent.parent;
1430 }
1431 return DynamicTypeImpl.instance;
1432 }
1433
1434 DartType _typeSearch(PropertyInducingElement varElement) {
1435 // TODO(scheglov) translate it
1436 return null;
1437 }
1438 }
1439
1440 abstract class CompletionEngine_AstNodeClassifier extends GeneralizingAstVisitor <Object> {
1441 @override
1442 Object visitNode(AstNode node) => null;
1443 }
1444
1445 class CompletionEngine_CommentReferenceCompleter extends CompletionEngine_AstNod eClassifier {
1446 final CompletionEngine CompletionEngine_this;
1447
1448 final SimpleIdentifier _identifier;
1449
1450 CompletionEngine_NameCollector _names;
1451
1452 Set<Element> _enclosingElements = new Set();
1453
1454 CompletionEngine_CommentReferenceCompleter(this.CompletionEngine_this, this._i dentifier) {
1455 CompletionEngine_this._filter = CompletionEngine_this._createFilter(_identif ier);
1456 _names = CompletionEngine_this._collectTopLevelElementVisibleAt(_identifier) ;
1457 }
1458
1459 @override
1460 Object visitClassDeclaration(ClassDeclaration node) {
1461 ClassElement classElement = node.element;
1462 _names._addNamesDefinedByHierarchy(classElement, false);
1463 _enclosingElements.add(classElement);
1464 return null;
1465 }
1466
1467 @override
1468 Object visitComment(Comment node) {
1469 node.parent.accept(this);
1470 // propose names
1471 for (Element element in _names.uniqueElements) {
1472 CompletionProposal proposal = CompletionEngine_this._createProposal2(eleme nt, _identifier);
1473 if (proposal != null) {
1474 // we don't want to add arguments, just names
1475 if (element is MethodElement || element is FunctionElement) {
1476 proposal.setKind(ProposalKind.METHOD_NAME);
1477 }
1478 // elevate priority for local elements
1479 if (_enclosingElements.contains(element.enclosingElement)) {
1480 proposal.setRelevance(CompletionProposal.RELEVANCE_HIGH);
1481 }
1482 // propose
1483 CompletionEngine_this._requestor.accept(proposal);
1484 }
1485 }
1486 // done
1487 return null;
1488 }
1489
1490 @override
1491 Object visitConstructorDeclaration(ConstructorDeclaration node) {
1492 _visitExecutableDeclaration(node);
1493 // pass through
1494 return node.parent.accept(this);
1495 }
1496
1497 @override
1498 Object visitFunctionDeclaration(FunctionDeclaration node) {
1499 _visitExecutableDeclaration(node);
1500 return null;
1501 }
1502
1503 @override
1504 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
1505 FunctionTypeAliasElement element = node.element;
1506 _names._mergeNames(element.parameters);
1507 _enclosingElements.add(element);
1508 return null;
1509 }
1510
1511 @override
1512 Object visitMethodDeclaration(MethodDeclaration node) {
1513 _visitExecutableDeclaration(node);
1514 // pass through
1515 return node.parent.accept(this);
1516 }
1517
1518 void _visitExecutableDeclaration(Declaration node) {
1519 ExecutableElement element = node.element as ExecutableElement;
1520 _names._mergeNames(element.parameters);
1521 _enclosingElements.add(element);
1522 }
1523 }
1524
1525 /**
1526 * An IdentifierCompleter is used to classify the parent of the completion node when it has
1527 * previously been determined that the completion node is a SimpleIdentifier.
1528 */
1529 class CompletionEngine_IdentifierCompleter extends CompletionEngine_AstNodeClass ifier {
1530 final CompletionEngine CompletionEngine_this;
1531
1532 SimpleIdentifier _completionNode;
1533
1534 CompletionEngine_IdentifierCompleter(this.CompletionEngine_this, SimpleIdentif ier node) {
1535 _completionNode = node;
1536 }
1537
1538 @override
1539 Object visitAnnotation(Annotation node) {
1540 if (_completionNode is SimpleIdentifier) {
1541 CompletionEngine_this._analyzeAnnotationName(_completionNode);
1542 }
1543 return null;
1544 }
1545
1546 @override
1547 Object visitArgumentList(ArgumentList node) {
1548 if (_completionNode is SimpleIdentifier) {
1549 if (CompletionEngine_this._isCompletionBetween(node.leftParenthesis.end, n ode.rightParenthesis.offset)) {
1550 CompletionEngine_this._analyzeLocalName(_completionNode);
1551 CompletionEngine_this._analyzePositionalArgument(node, _completionNode);
1552 CompletionEngine_this._analyzeNamedParameter(node, _completionNode);
1553 }
1554 }
1555 return null;
1556 }
1557
1558 @override
1559 Object visitAssignmentExpression(AssignmentExpression node) {
1560 if (_completionNode is SimpleIdentifier) {
1561 CompletionEngine_this._analyzeLocalName(_completionNode);
1562 }
1563 return null;
1564 }
1565
1566 @override
1567 Object visitBinaryExpression(BinaryExpression node) {
1568 if (identical(node.leftOperand, _completionNode)) {
1569 CompletionEngine_this._analyzeLocalName(_completionNode);
1570 } else if (identical(node.rightOperand, _completionNode)) {
1571 CompletionEngine_this._analyzeLocalName(_completionNode);
1572 }
1573 return null;
1574 }
1575
1576 @override
1577 Object visitCombinator(Combinator node) {
1578 CompletionEngine_this._proposeCombinator(node, _completionNode);
1579 return null;
1580 }
1581
1582 @override
1583 Object visitCommentReference(CommentReference node) {
1584 AstNode comment = node.parent;
1585 CompletionEngine_CommentReferenceCompleter visitor = new CompletionEngine_Co mmentReferenceCompleter(CompletionEngine_this, _completionNode);
1586 return comment.accept(visitor);
1587 }
1588
1589 @override
1590 Object visitConstructorDeclaration(ConstructorDeclaration node) {
1591 if (identical(node.returnType, _completionNode)) {
1592 CompletionEngine_this._filter = CompletionEngine_this._createFilter(_compl etionNode);
1593 CompletionEngine_this._pName3(_completionNode.name, ProposalKind.CONSTRUCT OR);
1594 }
1595 return null;
1596 }
1597
1598 @override
1599 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
1600 // { A() : this.!x = 1; }
1601 if (identical(node.fieldName, _completionNode)) {
1602 ClassElement classElement = (node.parent as ConstructorDeclaration).elemen t.enclosingElement;
1603 CompletionEngine_this._fieldReference(classElement, node.fieldName);
1604 }
1605 return null;
1606 }
1607
1608 @override
1609 Object visitConstructorName(ConstructorName node) {
1610 if (identical(node.name, _completionNode)) {
1611 // { new A.!c(); }
1612 TypeName typeName = node.type;
1613 if (typeName != null) {
1614 DartType type = typeName.type;
1615 Element typeElement = type.element;
1616 if (typeElement is ClassElement) {
1617 ClassElement classElement = typeElement;
1618 CompletionEngine_this._constructorReference(classElement, node.name);
1619 }
1620 }
1621 }
1622 return null;
1623 }
1624
1625 @override
1626 Object visitDoStatement(DoStatement node) {
1627 if (identical(node.condition, _completionNode)) {
1628 CompletionEngine_this._analyzeLocalName(_completionNode);
1629 }
1630 return null;
1631 }
1632
1633 @override
1634 Object visitExpression(Expression node) {
1635 SimpleIdentifier ident;
1636 if (_completionNode is SimpleIdentifier) {
1637 ident = _completionNode;
1638 } else {
1639 ident = CompletionEngine_this._createIdent(node);
1640 }
1641 CompletionEngine_this._analyzeLocalName(ident);
1642 return null;
1643 }
1644
1645 @override
1646 Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
1647 if (identical(_completionNode, node.expression)) {
1648 CompletionEngine_this._analyzeLocalName(_completionNode);
1649 }
1650 return null;
1651 }
1652
1653 @override
1654 Object visitExpressionStatement(ExpressionStatement node) {
1655 SimpleIdentifier ident;
1656 if (_completionNode is SimpleIdentifier) {
1657 ident = _completionNode;
1658 } else {
1659 ident = CompletionEngine_this._createIdent(node);
1660 }
1661 CompletionEngine_this._analyzeLocalName(ident);
1662 return null;
1663 }
1664
1665 @override
1666 Object visitFieldFormalParameter(FieldFormalParameter node) {
1667 if (identical(_completionNode, node.identifier)) {
1668 CompletionEngine_this._analyzeImmediateField(node.identifier);
1669 }
1670 return null;
1671 }
1672
1673 @override
1674 Object visitForEachStatement(ForEachStatement node) {
1675 if (identical(node.iterator, _completionNode)) {
1676 CompletionEngine_this._analyzeLocalName(_completionNode);
1677 }
1678 return null;
1679 }
1680
1681 @override
1682 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
1683 if (identical(node.name, _completionNode)) {
1684 if (node.returnType == null) {
1685 // This may be an incomplete class type alias
1686 CompletionEngine_this._state._includesUndefinedTypes();
1687 CompletionEngine_this._analyzeTypeName(node.name, CompletionEngine_this. _typeDeclarationName(node));
1688 }
1689 }
1690 return null;
1691 }
1692
1693 @override
1694 Object visitIfStatement(IfStatement node) {
1695 if (identical(node.condition, _completionNode)) {
1696 // { if (!) }
1697 CompletionEngine_this._analyzeLocalName(new Ident.con3(node, _completionNo de.token));
1698 }
1699 return null;
1700 }
1701
1702 @override
1703 Object visitInterpolationExpression(InterpolationExpression node) {
1704 if (node.expression is SimpleIdentifier) {
1705 SimpleIdentifier ident = node.expression as SimpleIdentifier;
1706 CompletionEngine_this._analyzeLocalName(ident);
1707 }
1708 return null;
1709 }
1710
1711 @override
1712 Object visitLibraryIdentifier(LibraryIdentifier node) => null;
1713
1714 @override
1715 Object visitMethodDeclaration(MethodDeclaration node) {
1716 if (identical(_completionNode, node.name)) {
1717 if (node.returnType == null) {
1718 // class Foo {const F!(); }
1719 CompletionEngine_this._analyzeLocalName(_completionNode);
1720 }
1721 }
1722 return null;
1723 }
1724
1725 @override
1726 Object visitMethodInvocation(MethodInvocation node) {
1727 if (identical(node.methodName, _completionNode)) {
1728 // { x.!y() }
1729 Expression expr = node.realTarget;
1730 DartType receiverType;
1731 if (expr == null) {
1732 receiverType = CompletionEngine_this._typeOfContainingClass(node);
1733 CompletionEngine_this._analyzeDirectAccess(receiverType, node.methodName );
1734 } else {
1735 CompletionEngine_this._dispatchPrefixAnalysis2(node);
1736 }
1737 } else if (identical(node.target, _completionNode)) {
1738 // { x!.y() } -- only reached when node.getTarget() is a simple identifier .
1739 if (_completionNode is SimpleIdentifier) {
1740 SimpleIdentifier ident = _completionNode;
1741 CompletionEngine_this._analyzeReceiver(ident);
1742 }
1743 }
1744 return null;
1745 }
1746
1747 @override
1748 Object visitParenthesizedExpression(ParenthesizedExpression node) {
1749 // Incomplete closure: foo((Str!)); We check if "()" is argument for functio n typed parameter.
1750 if (node.parent is ArgumentList) {
1751 ParameterElement parameterElement = node.bestParameterElement;
1752 if (parameterElement != null && parameterElement.type is FunctionType) {
1753 Ident ident = CompletionEngine_this._createIdent(_completionNode);
1754 CompletionEngine_this._analyzeTypeName(_completionNode, ident);
1755 }
1756 }
1757 return super.visitParenthesizedExpression(node);
1758 }
1759
1760 @override
1761 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
1762 if (identical(node.prefix, _completionNode)) {
1763 // { x!.y }
1764 CompletionEngine_this._analyzeLocalName(node.prefix);
1765 } else {
1766 // { v.! }
1767 CompletionEngine_this._dispatchPrefixAnalysis3(node, node.identifier);
1768 }
1769 return null;
1770 }
1771
1772 @override
1773 Object visitPropertyAccess(PropertyAccess node) {
1774 if (node.target != null && node.target.length == 0) {
1775 return null;
1776 }
1777 // { o.!hashCode }
1778 if (identical(node.propertyName, _completionNode)) {
1779 CompletionEngine_this._analyzePrefixedAccess(node.realTarget, node.propert yName);
1780 }
1781 return null;
1782 }
1783
1784 @override
1785 Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
1786 // { A.Fac() : this.!b(); }
1787 if (identical(node.constructorName, _completionNode)) {
1788 ClassElement classElement = node.staticElement.enclosingElement;
1789 CompletionEngine_this._constructorReference(classElement, node.constructor Name);
1790 }
1791 return null;
1792 }
1793
1794 @override
1795 Object visitReturnStatement(ReturnStatement node) {
1796 if (_completionNode is SimpleIdentifier) {
1797 CompletionEngine_this._analyzeLocalName(_completionNode);
1798 }
1799 return null;
1800 }
1801
1802 @override
1803 Object visitSimpleFormalParameter(SimpleFormalParameter node) {
1804 if (identical(node.identifier, _completionNode)) {
1805 if (node.keyword == null && node.type == null) {
1806 Ident ident = CompletionEngine_this._createIdent(node);
1807 CompletionEngine_this._analyzeTypeName(node.identifier, ident);
1808 }
1809 }
1810 return null;
1811 }
1812
1813 @override
1814 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
1815 CompletionEngine_this._analyzeSuperConstructorInvocation(node);
1816 return null;
1817 }
1818
1819 @override
1820 Object visitSwitchCase(SwitchCase node) {
1821 if (identical(_completionNode, node.expression)) {
1822 CompletionEngine_this._analyzeLocalName(_completionNode);
1823 }
1824 return null;
1825 }
1826
1827 @override
1828 Object visitSwitchStatement(SwitchStatement node) {
1829 if (identical(node.expression, _completionNode)) {
1830 CompletionEngine_this._analyzeLocalName(_completionNode);
1831 }
1832 return null;
1833 }
1834
1835 @override
1836 Object visitTypeName(TypeName node) {
1837 AstNode parent = node.parent;
1838 if (parent != null) {
1839 CompletionEngine_TypeNameCompleter visitor = new CompletionEngine_TypeName Completer(CompletionEngine_this, _completionNode, node);
1840 return parent.accept(visitor);
1841 }
1842 return null;
1843 }
1844
1845 @override
1846 Object visitTypeParameter(TypeParameter node) {
1847 // { X<!Y> }
1848 if (CompletionEngine_this._isCompletionBetween(node.offset, node.end)) {
1849 CompletionEngine_this._analyzeTypeName(_completionNode, CompletionEngine_t his._typeDeclarationName(node));
1850 }
1851 return null;
1852 }
1853
1854 @override
1855 Object visitVariableDeclaration(VariableDeclaration node) {
1856 if (identical(node.name, _completionNode)) {
1857 CompletionEngine_this._analyzeDeclarationName(node);
1858 } else if (identical(node.initializer, _completionNode)) {
1859 CompletionEngine_this._analyzeLocalName(node.initializer as SimpleIdentifi er);
1860 }
1861 return null;
1862 }
1863
1864 @override
1865 Object visitWhileStatement(WhileStatement node) {
1866 if (identical(node.condition, _completionNode)) {
1867 CompletionEngine_this._analyzeLocalName(_completionNode);
1868 }
1869 return null;
1870 }
1871 }
1872
1873 class CompletionEngine_NameCollector {
1874 final CompletionEngine CompletionEngine_this;
1875
1876 Map<String, List<Element>> _uniqueNames = new Map<String, List<Element>>();
1877
1878 Set<Element> _potentialMatches;
1879
1880 CompletionEngine_NameCollector(this.CompletionEngine_this);
1881
1882 void addAll(Iterable<SimpleIdentifier> values) {
1883 for (SimpleIdentifier id in values) {
1884 _mergeName(id.bestElement);
1885 }
1886 }
1887
1888 void addLocalNames(SimpleIdentifier identifier) {
1889 AstNode node = identifier;
1890 Declaration decl;
1891 while ((decl = node.getAncestor((node) => node is Declaration)) != null) {
1892 Element declElement = decl.element;
1893 if (declElement is ExecutableElement) {
1894 _addNamesDefinedByExecutable(declElement);
1895 } else {
1896 return;
1897 }
1898 node = decl.parent;
1899 }
1900 }
1901
1902 void _addNamesDefinedByExecutable(ExecutableElement execElement) {
1903 _mergeNames(execElement.parameters);
1904 _mergeNames(execElement.localVariables);
1905 _mergeNames(execElement.functions);
1906 }
1907
1908 void _addNamesDefinedByHierarchy(ClassElement classElement, bool forSuper) {
1909 _addNamesDefinedByHierarchy2(classElement.type, forSuper);
1910 }
1911
1912 void _addNamesDefinedByHierarchy2(InterfaceType type, bool forSuper) {
1913 List<InterfaceType> superTypes = type.element.allSupertypes;
1914 if (!forSuper) {
1915 superTypes = ArrayUtils.add(superTypes, 0, type);
1916 }
1917 _addNamesDefinedByTypes(superTypes);
1918 // Collect names defined by subtypes separately so they can be identified la ter.
1919 CompletionEngine_NameCollector potentialMatchCollector = CompletionEngine_th is._createNameCollector();
1920 if (!type.isObject) {
1921 potentialMatchCollector._addNamesDefinedByTypes(CompletionEngine_this._all Subtypes(type.element));
1922 }
1923 _potentialMatches = new Set<Element>();
1924 for (List<Element> matches in potentialMatchCollector._uniqueNames.values) {
1925 for (Element match in matches) {
1926 _mergeName(match);
1927 _potentialMatches.add(match);
1928 }
1929 }
1930 }
1931
1932 void _addNamesDefinedByType(ClassElement classElement) {
1933 _addNamesDefinedByType2(classElement.type);
1934 }
1935
1936 void _addNamesDefinedByType2(InterfaceType type) {
1937 if (_inPrivateLibrary(type)) {
1938 return;
1939 }
1940 List<PropertyAccessorElement> accessors = type.accessors;
1941 _mergeNames(accessors);
1942 List<MethodElement> methods = type.methods;
1943 _mergeNames(methods);
1944 _mergeNames(type.element.typeParameters);
1945 _filterStaticRefs(accessors);
1946 _filterStaticRefs(methods);
1947 }
1948
1949 void _addNamesDefinedByTypes(List<InterfaceType> types) {
1950 for (InterfaceType type in types) {
1951 _addNamesDefinedByType2(type);
1952 }
1953 }
1954
1955 void _addTopLevelNames(List<ImportElement> imports, TopLevelNamesKind topKind) {
1956 for (ImportElement imp in imports) {
1957 Iterable<Element> elementsCollection = CorrectionUtils.getImportNamespace( imp).values;
1958 List<Element> elements = [];
1959 _addTopLevelNames4(elements);
1960 }
1961 }
1962
1963 void _addTopLevelNames2(LibraryElement library, TopLevelNamesKind topKind) {
1964 List<Element> elements = CompletionEngine_this._findTopLevelElements(library , topKind);
1965 _addTopLevelNames4(elements);
1966 }
1967
1968 void _addTopLevelNames3(List<LibraryElement> libraries, TopLevelNamesKind topK ind) {
1969 for (LibraryElement library in libraries) {
1970 _addTopLevelNames2(library, topKind);
1971 }
1972 }
1973
1974 Iterable<List<Element>> get names => _uniqueNames.values;
1975
1976 Iterable<Element> get uniqueElements {
1977 List<Element> uniqueElements = [];
1978 for (List<Element> uniques in _uniqueNames.values) {
1979 Element element = uniques[0];
1980 uniqueElements.add(element);
1981 }
1982 return uniqueElements;
1983 }
1984
1985 bool _isPotentialMatch(Element element) => _potentialMatches != null && _poten tialMatches.contains(element);
1986
1987 void _remove(Element element) {
1988 String name = element.displayName;
1989 List<Element> list = _uniqueNames[name];
1990 if (list == null) {
1991 return;
1992 }
1993 list.remove(element);
1994 if (list.isEmpty) {
1995 _uniqueNames.remove(name);
1996 }
1997 }
1998
1999 void _addTopLevelNames4(List<Element> elements) {
2000 _mergeNames(CompletionEngine_this._findAllTypes2(elements));
2001 if (!CompletionEngine_this._state._areClassesRequired) {
2002 _mergeNames(CompletionEngine_this._findAllNotTypes(elements));
2003 _mergeNames(CompletionEngine_this._findAllPrefixes());
2004 }
2005 }
2006
2007 void _filterStaticRefs(List<ExecutableElement> elements) {
2008 for (ExecutableElement execElem in elements) {
2009 if (CompletionEngine_this._state._areInstanceReferencesProhibited && !exec Elem.isStatic) {
2010 _remove(execElem);
2011 } else if (CompletionEngine_this._state._areStaticReferencesProhibited && execElem.isStatic) {
2012 _remove(execElem);
2013 } else if (!CompletionEngine_this._state._areOperatorsAllowed && execElem. isOperator) {
2014 _remove(execElem);
2015 } else if (CompletionEngine_this._state._areMethodsProhibited && !execElem .isOperator) {
2016 _remove(execElem);
2017 }
2018 }
2019 }
2020
2021 bool _inPrivateLibrary(InterfaceType type) {
2022 LibraryElement lib = type.element.library;
2023 if (!lib.name.startsWith("_")) {
2024 return false;
2025 }
2026 // allow completion in the same library
2027 if (identical(lib, CompletionEngine_this.currentLibrary)) {
2028 return false;
2029 }
2030 // eliminate types defined in private libraries
2031 return true;
2032 }
2033
2034 void _mergeName(Element element) {
2035 if (element == null) {
2036 return;
2037 }
2038 // ignore private
2039 String name = element.displayName;
2040 if (Identifier.isPrivateName(name)) {
2041 if (!CompletionEngine_this._isInCurrentLibrary(element)) {
2042 return;
2043 }
2044 }
2045 // add to other Element(s) with such name
2046 List<Element> dups = _uniqueNames[name];
2047 if (dups == null) {
2048 dups = new List<Element>();
2049 _uniqueNames[name] = dups;
2050 }
2051 dups.add(element);
2052 }
2053
2054 void _mergeNames(List<Element> elements) {
2055 for (Element element in elements) {
2056 _mergeName(element);
2057 }
2058 }
2059 }
2060
2061 /**
2062 * An StringCompleter is used to classify the parent of the completion node when it has previously
2063 * been determined that the completion node is a SimpleStringLiteral.
2064 */
2065 class CompletionEngine_StringCompleter extends CompletionEngine_AstNodeClassifie r {
2066 final CompletionEngine CompletionEngine_this;
2067
2068 SimpleStringLiteral _completionNode;
2069
2070 CompletionEngine_StringCompleter(this.CompletionEngine_this, SimpleStringLiter al node) {
2071 _completionNode = node;
2072 }
2073
2074 @override
2075 Object visitNamespaceDirective(NamespaceDirective node) {
2076 if (identical(_completionNode, node.uri)) {
2077 CompletionEngine_this._namespaceReference(node, _completionNode);
2078 }
2079 return null;
2080 }
2081 }
2082
2083 /**
2084 * A TerminalNodeCompleter is used to classify the completion node when nothing else is known
2085 * about it.
2086 */
2087 class CompletionEngine_TerminalNodeCompleter extends CompletionEngine_AstNodeCla ssifier {
2088 final CompletionEngine CompletionEngine_this;
2089
2090 CompletionEngine_TerminalNodeCompleter(this.CompletionEngine_this);
2091
2092 @override
2093 Object visitArgumentList(ArgumentList node) {
2094 if (node.arguments.isEmpty && CompletionEngine_this._isCompletionBetween(nod e.leftParenthesis.end, node.rightParenthesis.offset)) {
2095 if (node.parent is MethodInvocation) {
2096 // or node.getParent().accept(this); ?
2097 MethodInvocation invokeNode = node.parent as MethodInvocation;
2098 SimpleIdentifier methodName = invokeNode.methodName;
2099 ProposalCollector proposalRequestor = new ProposalCollector(CompletionEn gine_this._requestor);
2100 try {
2101 CompletionEngine_this._requestor = proposalRequestor;
2102 CompletionEngine_this._dispatchPrefixAnalysis2(invokeNode);
2103 } finally {
2104 CompletionEngine_this._requestor = proposalRequestor.requestor;
2105 }
2106 int offset = methodName.offset;
2107 int len = node.rightParenthesis.end - offset;
2108 String name = methodName.name;
2109 for (CompletionProposal proposal in proposalRequestor.proposals) {
2110 if (proposal.completion == name) {
2111 CompletionEngine_this._pArgumentList(proposal, offset, len);
2112 }
2113 }
2114 } else if (node.parent is InstanceCreationExpression) {
2115 InstanceCreationExpression invokeNode = node.parent as InstanceCreationE xpression;
2116 ConstructorName methodName = invokeNode.constructorName;
2117 ProposalCollector proposalRequestor = new ProposalCollector(CompletionEn gine_this._requestor);
2118 try {
2119 CompletionEngine_this._requestor = proposalRequestor;
2120 CompletionEngine_this._dispatchPrefixAnalysis(invokeNode);
2121 } finally {
2122 CompletionEngine_this._requestor = proposalRequestor.requestor;
2123 }
2124 int offset = methodName.offset;
2125 int len = node.rightParenthesis.end - offset;
2126 for (CompletionProposal proposal in proposalRequestor.proposals) {
2127 if (proposal.element == invokeNode.staticElement) {
2128 CompletionEngine_this._pArgumentList(proposal, offset, len);
2129 }
2130 }
2131 } else if (node.parent is Annotation) {
2132 Annotation annotation = node.parent as Annotation;
2133 Element annotationElement = annotation.element;
2134 if (annotationElement is ConstructorElement) {
2135 ConstructorElement constructorElement = annotationElement;
2136 // we don't need any filter
2137 CompletionEngine_this._filter = new Filter.con2("", -1, 0);
2138 // fill parameters for "pArgumentList"
2139 CompletionProposal prop = CompletionEngine_this._createProposal(constr uctorElement);
2140 CompletionEngine_this._setParameterInfo(constructorElement.type, prop) ;
2141 prop.setCompletion(constructorElement.enclosingElement.name);
2142 // propose the whole parameters list
2143 CompletionEngine_this._pArgumentList(prop, 0, 0);
2144 }
2145 }
2146 }
2147 if (CompletionEngine_this._isCompletionBetween(node.leftParenthesis.end, nod e.rightParenthesis.offset)) {
2148 Ident ident = CompletionEngine_this._createIdent(node);
2149 CompletionEngine_this._analyzeLocalName(ident);
2150 CompletionEngine_this._analyzePositionalArgument(node, ident);
2151 CompletionEngine_this._analyzeNamedParameter(node, ident);
2152 }
2153 return null;
2154 }
2155
2156 @override
2157 Object visitAsExpression(AsExpression node) {
2158 if (CompletionEngine_this._isCompletionAfter(node.asOperator.end)) {
2159 CompletionEngine_this._state._isDynamicAllowed = false;
2160 CompletionEngine_this._state._isVoidAllowed = false;
2161 CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent( node), null);
2162 }
2163 return null;
2164 }
2165
2166 @override
2167 Object visitAssertStatement(AssertStatement node) {
2168 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2169 CompletionEngine_this._pKeyword(node.keyword);
2170 }
2171 return null;
2172 }
2173
2174 @override
2175 Object visitBlock(Block node) {
2176 if (CompletionEngine_this._isCompletionBetween(node.leftBracket.end, node.ri ghtBracket.offset)) {
2177 // { {! stmt; !} }
2178 CompletionEngine_this._analyzeLocalName(CompletionEngine_this._createIdent (node));
2179 }
2180 return null;
2181 }
2182
2183 @override
2184 Object visitBooleanLiteral(BooleanLiteral node) {
2185 CompletionEngine_this._analyzeLiteralReference(node);
2186 return null;
2187 }
2188
2189 @override
2190 Object visitBreakStatement(BreakStatement node) {
2191 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2192 CompletionEngine_this._pKeyword(node.keyword);
2193 }
2194 return null;
2195 }
2196
2197 @override
2198 Object visitCatchClause(CatchClause node) {
2199 if (CompletionEngine_this._isCompletingKeyword(node.onKeyword)) {
2200 CompletionEngine_this._pKeyword(node.onKeyword);
2201 } else if (CompletionEngine_this._isCompletingKeyword(node.catchKeyword)) {
2202 CompletionEngine_this._pKeyword(node.catchKeyword);
2203 }
2204 return null;
2205 }
2206
2207 @override
2208 Object visitClassDeclaration(ClassDeclaration node) {
2209 if (CompletionEngine_this._isCompletingKeyword(node.classKeyword)) {
2210 CompletionEngine_this._pKeyword(node.classKeyword);
2211 } else if (CompletionEngine_this._isCompletingKeyword(node.abstractKeyword)) {
2212 CompletionEngine_this._pKeyword(node.abstractKeyword);
2213 } else if (!node.leftBracket.isSynthetic) {
2214 if (CompletionEngine_this._isCompletionAfter(node.leftBracket.end)) {
2215 if (node.rightBracket.isSynthetic || CompletionEngine_this._isCompletion Before(node.rightBracket.offset)) {
2216 if (!CompletionEngine_this.hasErrorBeforeCompletionLocation) {
2217 CompletionEngine_this._analyzeLocalName(CompletionEngine_this._creat eIdent(node));
2218 }
2219 }
2220 }
2221 }
2222 // TODO { abstract ! class ! A ! extends B implements C, D ! {}}
2223 return null;
2224 }
2225
2226 @override
2227 Object visitClassTypeAlias(ClassTypeAlias node) {
2228 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2229 CompletionEngine_this._pKeyword(node.keyword);
2230 }
2231 // TODO { typedef ! A ! = ! B ! with C, D !; }
2232 return null;
2233 }
2234
2235 @override
2236 Object visitCombinator(Combinator node) {
2237 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2238 CompletionEngine_this._pKeyword(node.keyword);
2239 }
2240 return null;
2241 }
2242
2243 @override
2244 Object visitCompilationUnit(CompilationUnit node) => null;
2245
2246 @override
2247 Object visitConstructorName(ConstructorName node) {
2248 // { new A.!c(); }
2249 TypeName typeName = node.type;
2250 if (typeName != null) {
2251 DartType type = typeName.type;
2252 Element typeElement = type.element;
2253 if (typeElement is ClassElement) {
2254 ClassElement classElement = typeElement;
2255 CompletionEngine_this._constructorReference(classElement, node.name);
2256 }
2257 }
2258 return null;
2259 }
2260
2261 @override
2262 Object visitContinueStatement(ContinueStatement node) {
2263 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2264 CompletionEngine_this._pKeyword(node.keyword);
2265 }
2266 return null;
2267 }
2268
2269 @override
2270 Object visitDirective(Directive node) {
2271 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2272 CompletionEngine_this._pKeyword(node.keyword);
2273 }
2274 return null;
2275 }
2276
2277 @override
2278 Object visitDoStatement(DoStatement node) {
2279 if (CompletionEngine_this._isCompletingKeyword(node.doKeyword)) {
2280 CompletionEngine_this._pKeyword(node.doKeyword);
2281 } else if (CompletionEngine_this._isCompletingKeyword(node.whileKeyword)) {
2282 CompletionEngine_this._pKeyword(node.whileKeyword);
2283 } else if (CompletionEngine_this._isCompletionBetween(node.condition.end, no de.rightParenthesis.offset)) {
2284 CompletionEngine_this._operatorAccess(node.condition, CompletionEngine_thi s._createIdent(node));
2285 }
2286 return null;
2287 }
2288
2289 @override
2290 Object visitDoubleLiteral(DoubleLiteral node) => null;
2291
2292 @override
2293 Object visitExportDirective(ExportDirective node) {
2294 visitNamespaceDirective(node);
2295 return null;
2296 }
2297
2298 @override
2299 Object visitExpression(Expression node) {
2300 CompletionEngine_this._analyzeLocalName(CompletionEngine_this._createIdent(n ode));
2301 return null;
2302 }
2303
2304 @override
2305 Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
2306 if (node.expression != null && node.semicolon != null) {
2307 if (CompletionEngine_this._isCompletionBetween(node.expression.end, node.s emicolon.offset)) {
2308 CompletionEngine_this._operatorAccess(node.expression, CompletionEngine_ this._createIdent(node));
2309 }
2310 }
2311 return null;
2312 }
2313
2314 @override
2315 Object visitExpressionStatement(ExpressionStatement node) {
2316 CompletionEngine_this._analyzeLocalName(CompletionEngine_this._createIdent(n ode));
2317 return null;
2318 }
2319
2320 @override
2321 Object visitExtendsClause(ExtendsClause node) {
2322 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2323 CompletionEngine_this._pKeyword(node.keyword);
2324 } else if (node.superclass == null) {
2325 // { X extends ! }
2326 CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent( node), CompletionEngine_this._typeDeclarationName(node));
2327 } else {
2328 // { X extends ! Y }
2329 CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent( node), CompletionEngine_this._typeDeclarationName(node));
2330 }
2331 return null;
2332 }
2333
2334 @override
2335 Object visitForEachStatement(ForEachStatement node) {
2336 if (CompletionEngine_this._isCompletingKeyword(node.forKeyword)) {
2337 CompletionEngine_this._pKeyword(node.forKeyword);
2338 } else if (CompletionEngine_this._isCompletingKeyword(node.inKeyword)) {
2339 CompletionEngine_this._pKeyword(node.inKeyword);
2340 }
2341 return null;
2342 }
2343
2344 @override
2345 Object visitFormalParameterList(FormalParameterList node) {
2346 if (CompletionEngine_this._isCompletionBetween(node.leftParenthesis.end, nod e.rightParenthesis.offset)) {
2347 NodeList<FormalParameter> params = node.parameters;
2348 if (!params.isEmpty) {
2349 FormalParameter last = params[params.length - 1];
2350 if (CompletionEngine_this._isCompletionBetween(last.end, node.rightParen thesis.offset)) {
2351 List<FormalParameter> newParams = CompletionEngine_this._copyWithout(p arams, last);
2352 CompletionEngine_this._analyzeNewParameterName(newParams, last.identif ier, null);
2353 } else {
2354 Ident ident = CompletionEngine_this._createIdent(node);
2355 CompletionEngine_this._analyzeTypeName(ident, ident);
2356 }
2357 } else {
2358 Ident ident = CompletionEngine_this._createIdent(node);
2359 CompletionEngine_this._analyzeTypeName(ident, ident);
2360 }
2361 }
2362 return null;
2363 }
2364
2365 @override
2366 Object visitForStatement(ForStatement node) {
2367 if (CompletionEngine_this._isCompletingKeyword(node.forKeyword)) {
2368 CompletionEngine_this._pKeyword(node.forKeyword);
2369 }
2370 return null;
2371 }
2372
2373 @override
2374 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
2375 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2376 CompletionEngine_this._pKeyword(node.keyword);
2377 }
2378 return null;
2379 }
2380
2381 @override
2382 Object visitIfStatement(IfStatement node) {
2383 if (CompletionEngine_this._isCompletingKeyword(node.ifKeyword)) {
2384 CompletionEngine_this._pKeyword(node.ifKeyword);
2385 } else if (CompletionEngine_this._isCompletingKeyword(node.elseKeyword)) {
2386 CompletionEngine_this._pKeyword(node.elseKeyword);
2387 } else if (CompletionEngine_this._isCompletionBetween(node.condition.end, no de.rightParenthesis.offset)) {
2388 CompletionEngine_this._operatorAccess(node.condition, CompletionEngine_thi s._createIdent(node));
2389 }
2390 return null;
2391 }
2392
2393 @override
2394 Object visitImplementsClause(ImplementsClause node) {
2395 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2396 CompletionEngine_this._pKeyword(node.keyword);
2397 } else if (node.interfaces.isEmpty) {
2398 // { X implements ! }
2399 CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent( node), CompletionEngine_this._typeDeclarationName(node));
2400 } else {
2401 // { X implements ! Y }
2402 CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent( node), CompletionEngine_this._typeDeclarationName(node));
2403 }
2404 return null;
2405 }
2406
2407 @override
2408 Object visitImportDirective(ImportDirective node) {
2409 if (CompletionEngine_this._isCompletingKeyword(node.asToken)) {
2410 CompletionEngine_this._pKeyword(node.asToken);
2411 } else {
2412 visitNamespaceDirective(node);
2413 }
2414 return null;
2415 }
2416
2417 @override
2418 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
2419 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2420 CompletionEngine_this._pKeyword(node.keyword);
2421 Ident ident = new Ident.con3(node, node.keyword);
2422 CompletionEngine_this._analyzeLocalName(ident);
2423 } else {
2424 Ident ident = CompletionEngine_this._createIdent(node);
2425 CompletionEngine_this._analyzeConstructorTypeName(ident);
2426 }
2427 return null;
2428 }
2429
2430 @override
2431 Object visitIsExpression(IsExpression node) {
2432 Ident ident;
2433 Token isToken = node.isOperator;
2434 int isTokenEnd = isToken.end;
2435 if (isTokenEnd == CompletionEngine_this._completionLocation()) {
2436 Expression expression = node.expression;
2437 int offset = isToken.offset;
2438 // { target.is! } possible name completion, parsed as "target.{synthetic} is!"
2439 if (expression is PrefixedIdentifier) {
2440 PrefixedIdentifier prefIdent = expression;
2441 if (prefIdent.identifier.isSynthetic) {
2442 CompletionEngine_this._analyzePrefixedAccess(prefIdent.prefix, new Ide nt.con2(node, "is", offset));
2443 } else {
2444 CompletionEngine_this._pKeyword(isToken);
2445 }
2446 return null;
2447 }
2448 // { expr is! }
2449 if (!CompletionEngine._isSyntheticIdentifier(expression)) {
2450 CompletionEngine_this._pKeyword(node.isOperator);
2451 return null;
2452 }
2453 // { is! } possible name completion
2454 ident = new Ident.con2(node, "is", offset);
2455 } else if (CompletionEngine_this._isCompletionAfter(isTokenEnd)) {
2456 CompletionEngine_this._state._isDynamicAllowed = false;
2457 CompletionEngine_this._state._isVoidAllowed = false;
2458 CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent( node), null);
2459 return null;
2460 } else {
2461 ident = CompletionEngine_this._createIdent(node);
2462 }
2463 CompletionEngine_this._analyzeLocalName(ident);
2464 return null;
2465 }
2466
2467 @override
2468 Object visitLibraryIdentifier(LibraryIdentifier node) => null;
2469
2470 @override
2471 Object visitMethodInvocation(MethodInvocation node) {
2472 Token period = node.period;
2473 if (period != null && CompletionEngine_this._isCompletionAfter(period.end)) {
2474 // { x.!y() }
2475 CompletionEngine_this._dispatchPrefixAnalysis2(node);
2476 }
2477 return null;
2478 }
2479
2480 @override
2481 Object visitNamespaceDirective(NamespaceDirective node) {
2482 StringLiteral uri = node.uri;
2483 if (uri != null && uri.isSynthetic && node.keyword.end <= CompletionEngine_t his._context.selectionOffset) {
2484 uri.accept(this);
2485 }
2486 return super.visitNamespaceDirective(node);
2487 }
2488
2489 @override
2490 Object visitPartOfDirective(PartOfDirective node) {
2491 if (CompletionEngine_this._isCompletingKeyword(node.ofToken)) {
2492 CompletionEngine_this._pKeyword(node.ofToken);
2493 } else {
2494 visitDirective(node);
2495 }
2496 return null;
2497 }
2498
2499 @override
2500 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
2501 if (CompletionEngine_this._isCompletionAfter(node.period.end)) {
2502 if (CompletionEngine_this._isCompletionBefore(node.identifier.offset)) {
2503 // { x.! } or { x.! y } Note missing/implied semicolon before y; this l ooks like an
2504 // obscure case but it occurs frequently when editing existing code.
2505 CompletionEngine_this._dispatchPrefixAnalysis3(node, node.identifier);
2506 }
2507 }
2508 return null;
2509 }
2510
2511 @override
2512 Object visitPropertyAccess(PropertyAccess node) {
2513 if (node.target != null && node.target.length == 0) {
2514 return null;
2515 }
2516 Expression target = node.realTarget;
2517 // The "1 + str.!.length" is parsed as "(1 + str).!.length",
2518 // but actually user wants "1 + (str.!).length".
2519 // So, if completion inside of period-period ".!." then it is not really a c ascade completion.
2520 Token operator = node.operator;
2521 if (operator.type == TokenType.PERIOD_PERIOD) {
2522 int completionLocation = CompletionEngine_this._completionLocation();
2523 if (completionLocation > operator.offset && completionLocation < operator. end) {
2524 while (target is BinaryExpression) {
2525 target = (target as BinaryExpression).rightOperand;
2526 }
2527 }
2528 }
2529 // do prefixed completion
2530 CompletionEngine_this._analyzePrefixedAccess(target, node.propertyName);
2531 return null;
2532 }
2533
2534 @override
2535 Object visitReturnStatement(ReturnStatement node) {
2536 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2537 CompletionEngine_this._pKeyword(node.keyword);
2538 return null;
2539 }
2540 Expression expression = node.expression;
2541 // return !
2542 if (expression is SimpleIdentifier) {
2543 SimpleIdentifier identifier = expression;
2544 CompletionEngine_this._analyzeLocalName(identifier);
2545 return null;
2546 }
2547 // return expression ! ;
2548 Token semicolon = node.semicolon;
2549 if (expression != null && semicolon != null && CompletionEngine_this._isComp letionBetween(expression.end, semicolon.offset)) {
2550 CompletionEngine_this._operatorAccess(expression, CompletionEngine_this._c reateIdent(node));
2551 return null;
2552 }
2553 return null;
2554 }
2555
2556 @override
2557 Object visitSimpleFormalParameter(SimpleFormalParameter node) {
2558 if (node.keyword != null && CompletionEngine_this._isCompletionBefore(node.k eyword.end)) {
2559 // f() { g(var! z) }
2560 Token token = node.keyword;
2561 Ident ident = new Ident.con3(node, token);
2562 CompletionEngine_this._analyzeTypeName(ident, ident);
2563 }
2564 return null;
2565 }
2566
2567 @override
2568 Object visitSimpleIdentifier(SimpleIdentifier node) {
2569 AstNode parent = node.parent;
2570 if (parent != null) {
2571 CompletionEngine_IdentifierCompleter visitor = new CompletionEngine_Identi fierCompleter(CompletionEngine_this, node);
2572 return parent.accept(visitor);
2573 }
2574 return null;
2575 }
2576
2577 @override
2578 Object visitSimpleStringLiteral(SimpleStringLiteral node) {
2579 AstNode parent = node.parent;
2580 if (parent is Directive) {
2581 CompletionEngine_StringCompleter visitor = new CompletionEngine_StringComp leter(CompletionEngine_this, node);
2582 return parent.accept(visitor);
2583 }
2584 return null;
2585 }
2586
2587 @override
2588 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
2589 CompletionEngine_this._analyzeSuperConstructorInvocation(node);
2590 return null;
2591 }
2592
2593 @override
2594 Object visitSwitchMember(SwitchMember node) {
2595 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2596 CompletionEngine_this._pKeyword(node.keyword);
2597 }
2598 return null;
2599 }
2600
2601 @override
2602 Object visitSwitchStatement(SwitchStatement node) {
2603 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2604 CompletionEngine_this._pKeyword(node.keyword);
2605 }
2606 return null;
2607 }
2608
2609 @override
2610 Object visitTryStatement(TryStatement node) {
2611 if (CompletionEngine_this._isCompletingKeyword(node.tryKeyword)) {
2612 CompletionEngine_this._pKeyword(node.tryKeyword);
2613 }
2614 return null;
2615 }
2616
2617 @override
2618 Object visitTypeArgumentList(TypeArgumentList node) {
2619 if (CompletionEngine_this._isCompletionBetween(node.leftBracket.end, node.ri ghtBracket.offset)) {
2620 CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent( node), null);
2621 }
2622 return null;
2623 }
2624
2625 @override
2626 Object visitTypeParameter(TypeParameter node) {
2627 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2628 CompletionEngine_this._pKeyword(node.keyword);
2629 } else if (node.name.name.isEmpty && CompletionEngine_this._isCompletionBefo re(node.keyword.offset)) {
2630 // { < ! extends X> }
2631 CompletionEngine_this._analyzeTypeName(node.name, CompletionEngine_this._t ypeDeclarationName(node));
2632 }
2633 // { <! X ! extends ! Y !> }
2634 return null;
2635 }
2636
2637 @override
2638 Object visitTypeParameterList(TypeParameterList node) {
2639 // { <X extends A,! B,! > }
2640 if (CompletionEngine_this._isCompletionBetween(node.leftBracket.end, node.ri ghtBracket.offset)) {
2641 CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent( node), CompletionEngine_this._typeDeclarationName(node));
2642 }
2643 return null;
2644 }
2645
2646 @override
2647 Object visitVariableDeclaration(VariableDeclaration node) {
2648 if (CompletionEngine_this._isCompletionAfter(node.equals.end)) {
2649 // { var x =! ...}
2650 CompletionEngine_this._analyzeLocalName(CompletionEngine_this._createIdent (node));
2651 }
2652 return null;
2653 }
2654
2655 @override
2656 Object visitVariableDeclarationList(VariableDeclarationList node) {
2657 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2658 CompletionEngine_this._pKeyword(node.keyword);
2659 CompletionEngine_this._analyzeTypeName(new Ident.con3(node, node.keyword), null);
2660 }
2661 return null;
2662 }
2663
2664 @override
2665 Object visitWhileStatement(WhileStatement node) {
2666 if (CompletionEngine_this._isCompletingKeyword(node.keyword)) {
2667 CompletionEngine_this._pKeyword(node.keyword);
2668 } else if (CompletionEngine_this._isCompletionBetween(node.condition.end, no de.rightParenthesis.offset)) {
2669 CompletionEngine_this._operatorAccess(node.condition, CompletionEngine_thi s._createIdent(node));
2670 }
2671 return null;
2672 }
2673
2674 @override
2675 Object visitWithClause(WithClause node) {
2676 if (CompletionEngine_this._isCompletingKeyword(node.withKeyword)) {
2677 CompletionEngine_this._pKeyword(node.withKeyword);
2678 } else if (node.mixinTypes.isEmpty) {
2679 // { X with ! }
2680 CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent( node), CompletionEngine_this._typeDeclarationName(node));
2681 } else {
2682 // { X with ! Y }
2683 CompletionEngine_this._analyzeTypeName(CompletionEngine_this._createIdent( node), CompletionEngine_this._typeDeclarationName(node));
2684 }
2685 return null;
2686 }
2687 }
2688
2689 /**
2690 * A TypeNameCompleter is used to classify the parent of a SimpleIdentifier afte r it has been
2691 * identified as a TypeName by the IdentifierCompleter.
2692 */
2693 class CompletionEngine_TypeNameCompleter extends CompletionEngine_AstNodeClassif ier {
2694 final CompletionEngine CompletionEngine_this;
2695
2696 final SimpleIdentifier _identifier;
2697
2698 final TypeName _typeName;
2699
2700 CompletionEngine_TypeNameCompleter(this.CompletionEngine_this, this._identifie r, this._typeName);
2701
2702 @override
2703 Object visitAsExpression(AsExpression node) {
2704 if (identical(node.type, _typeName)) {
2705 CompletionEngine_this._state._isDynamicAllowed = false;
2706 CompletionEngine_this._state._isVoidAllowed = false;
2707 CompletionEngine_this._analyzeTypeName(_identifier, null);
2708 }
2709 return null;
2710 }
2711
2712 @override
2713 Object visitCatchClause(CatchClause node) {
2714 if (identical(node.exceptionType, _typeName)) {
2715 CompletionEngine_this._analyzeTypeName(_identifier, null);
2716 }
2717 return null;
2718 }
2719
2720 @override
2721 Object visitClassTypeAlias(ClassTypeAlias node) {
2722 CompletionEngine_this._analyzeTypeName(_identifier, CompletionEngine_this._t ypeDeclarationName(node));
2723 return null;
2724 }
2725
2726 @override
2727 Object visitConstructorName(ConstructorName node) {
2728 if (identical(_typeName, node.type)) {
2729 if (node.period != null) {
2730 if (CompletionEngine_this._isCompletionAfter(node.period.end)) {
2731 // Is this branch reachable? Probably only in IdentifierCompleter.
2732 "".toString();
2733 } else {
2734 // { new Cla!ss.cons() }
2735 Element element = _identifier.bestElement;
2736 if (element is ClassElement) {
2737 CompletionEngine_this._namedConstructorReference(element, _identifie r);
2738 }
2739 }
2740 } else {
2741 // { new ! } { new Na!me(); } { new js!on. }
2742 CompletionEngine_this._analyzeConstructorTypeName(_identifier);
2743 }
2744 }
2745 return null;
2746 }
2747
2748 @override
2749 Object visitExtendsClause(ExtendsClause node) {
2750 CompletionEngine_this._analyzeTypeName(_identifier, CompletionEngine_this._t ypeDeclarationName(node));
2751 return null;
2752 }
2753
2754 @override
2755 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
2756 CompletionEngine_this._analyzeTypeName(_identifier, CompletionEngine_this._t ypeDeclarationName(node));
2757 return null;
2758 }
2759
2760 @override
2761 Object visitImplementsClause(ImplementsClause node) {
2762 CompletionEngine_this._analyzeTypeName(_identifier, CompletionEngine_this._t ypeDeclarationName(node));
2763 return null;
2764 }
2765
2766 @override
2767 Object visitIsExpression(IsExpression node) {
2768 if (identical(_typeName, node.type)) {
2769 Token isToken = node.isOperator;
2770 if (CompletionEngine_this._completionLocation() == isToken.end) {
2771 Expression expression = node.expression;
2772 int offset = isToken.offset;
2773 // { target.is! } possible name completion, parsed as "target.{synthetic } is!"
2774 if (expression is PrefixedIdentifier) {
2775 PrefixedIdentifier prefIdent = expression;
2776 if (prefIdent.identifier.isSynthetic) {
2777 CompletionEngine_this._analyzePrefixedAccess(prefIdent.prefix, new I dent.con2(node, "is", offset));
2778 } else {
2779 CompletionEngine_this._pKeyword(node.isOperator);
2780 }
2781 return null;
2782 }
2783 // { expr is! }
2784 if (!CompletionEngine._isSyntheticIdentifier(expression)) {
2785 CompletionEngine_this._pKeyword(node.isOperator);
2786 return null;
2787 }
2788 // { is! } possible name completion
2789 CompletionEngine_this._analyzeLocalName(new Ident.con2(node, "is", offse t));
2790 } else {
2791 CompletionEngine_this._analyzeTypeName(node.type.name as SimpleIdentifie r, null);
2792 }
2793 }
2794 return null;
2795 }
2796
2797 @override
2798 Object visitMethodDeclaration(MethodDeclaration node) {
2799 if (identical(node.returnType, _typeName)) {
2800 CompletionEngine_this._analyzeTypeName(_identifier, null);
2801 }
2802 return null;
2803 }
2804
2805 @override
2806 Object visitSimpleFormalParameter(SimpleFormalParameter node) {
2807 CompletionEngine_this._analyzeTypeName(_identifier, null);
2808 return null;
2809 }
2810
2811 @override
2812 Object visitTypeArgumentList(TypeArgumentList node) {
2813 if (CompletionEngine_this._isCompletionBetween(node.leftBracket.end, node.ri ghtBracket.offset)) {
2814 CompletionEngine_this._analyzeTypeName(_identifier, null);
2815 }
2816 return null;
2817 }
2818
2819 @override
2820 Object visitTypeParameter(TypeParameter node) {
2821 if (identical(node.bound, _typeName)) {
2822 // { X<A extends !Y> }
2823 CompletionEngine_this._analyzeTypeName(_identifier, CompletionEngine_this. _typeDeclarationName(node));
2824 }
2825 return null;
2826 }
2827
2828 @override
2829 Object visitVariableDeclarationList(VariableDeclarationList node) {
2830 if (node.parent is Statement) {
2831 CompletionEngine_this._analyzeLocalName(_identifier);
2832 } else {
2833 CompletionEngine_this._analyzeTypeName(_identifier, null);
2834 }
2835 return null;
2836 }
2837
2838 @override
2839 Object visitWithClause(WithClause node) {
2840 CompletionEngine_this._analyzeTypeName(_identifier, CompletionEngine_this._t ypeDeclarationName(node));
2841 return null;
2842 }
2843 }
2844
2845 /**
2846 * The factory class used to create completion proposals.
2847 */
2848 class CompletionFactory {
2849 /**
2850 * Create a completion proposal of the given kind.
2851 */
2852 CompletionProposal createCompletionProposal(ProposalKind kind, int insertionPo int) {
2853 CompletionProposalImpl prop = new CompletionProposalImpl();
2854 prop.setKind(kind);
2855 prop.setLocation(insertionPoint);
2856 return prop;
2857 }
2858 }
2859
2860 abstract class CompletionProposal {
2861 static final int RELEVANCE_LOW = 0;
2862
2863 static final int RELEVANCE_DEFAULT = 10;
2864
2865 static final int RELEVANCE_HIGH = 20;
2866
2867 /**
2868 * This character is used to specify location of the cursor after completion.
2869 */
2870 static final int CURSOR_MARKER = 0x2758;
2871
2872 void applyPartitionOffset(int partitionOffset);
2873
2874 String get completion;
2875
2876 String get declaringType;
2877
2878 Element get element;
2879
2880 ProposalKind get kind;
2881
2882 int get location;
2883
2884 String get parameterName;
2885
2886 List<String> get parameterNames;
2887
2888 String get parameterType;
2889
2890 List<String> get parameterTypes;
2891
2892 int get positionalParameterCount;
2893
2894 int get relevance;
2895
2896 int get replacementLength;
2897
2898 int get replacementLengthIdentifier;
2899
2900 String get returnType;
2901
2902 bool get hasNamed;
2903
2904 bool get hasPositional;
2905
2906 CompletionProposal incRelevance();
2907
2908 bool get isDeprecated;
2909
2910 bool get isPotentialMatch;
2911
2912 CompletionProposal setCompletion(String x);
2913
2914 CompletionProposal setDeclaringType(String name);
2915
2916 CompletionProposal setDeprecated(bool deprecated);
2917
2918 CompletionProposal setElement(Element element);
2919
2920 CompletionProposal setKind(ProposalKind x);
2921
2922 CompletionProposal setLocation(int x);
2923
2924 CompletionProposal setParameterName(String paramName);
2925
2926 CompletionProposal setParameterNames(List<String> paramNames);
2927
2928 CompletionProposal setParameterStyle(int count, bool named, bool positional);
2929
2930 CompletionProposal setParameterType(String paramType);
2931
2932 CompletionProposal setParameterTypes(List<String> paramTypes);
2933
2934 CompletionProposal setPotentialMatch(bool isPotentialMatch);
2935
2936 CompletionProposal setRelevance(int n);
2937
2938 CompletionProposal setReplacementLength(int x);
2939
2940 CompletionProposal setReplacementLengthIdentifier(int x);
2941
2942 CompletionProposal setReturnType(String name);
2943 }
2944
2945 class CompletionProposalImpl implements CompletionProposal {
2946 Element _element;
2947
2948 String _completion = "";
2949
2950 String _returnType = "";
2951
2952 String _declaringType = "";
2953
2954 List<String> _parameterNames = StringUtilities.EMPTY_ARRAY;
2955
2956 List<String> _parameterTypes = StringUtilities.EMPTY_ARRAY;
2957
2958 String _parameterName;
2959
2960 String _parameterType;
2961
2962 ProposalKind _kind = ProposalKind.NONE;
2963
2964 int _location = 0;
2965
2966 int _replacementLength = 0;
2967
2968 int _replacementLength2 = 0;
2969
2970 int _positionalParameterCount = 0;
2971
2972 bool _named = false;
2973
2974 bool _positional = false;
2975
2976 bool _deprecated = false;
2977
2978 bool _potential = false;
2979
2980 int _relevance = CompletionProposal.RELEVANCE_DEFAULT;
2981
2982 @override
2983 void applyPartitionOffset(int partitionOffset) {
2984 _location += partitionOffset;
2985 }
2986
2987 @override
2988 String get completion => _completion;
2989
2990 @override
2991 String get declaringType => _declaringType;
2992
2993 @override
2994 Element get element => _element;
2995
2996 @override
2997 ProposalKind get kind => _kind;
2998
2999 @override
3000 int get location => _location;
3001
3002 @override
3003 String get parameterName => _parameterName;
3004
3005 @override
3006 List<String> get parameterNames => _parameterNames;
3007
3008 @override
3009 String get parameterType => _parameterType;
3010
3011 @override
3012 List<String> get parameterTypes => _parameterTypes;
3013
3014 @override
3015 int get positionalParameterCount => _positionalParameterCount;
3016
3017 @override
3018 int get relevance => _relevance;
3019
3020 @override
3021 int get replacementLength => _replacementLength;
3022
3023 @override
3024 int get replacementLengthIdentifier => _replacementLength2;
3025
3026 @override
3027 String get returnType => _returnType;
3028
3029 @override
3030 bool get hasNamed => _named;
3031
3032 @override
3033 bool get hasPositional => _positional;
3034
3035 @override
3036 CompletionProposal incRelevance() {
3037 _relevance++;
3038 return this;
3039 }
3040
3041 @override
3042 bool get isDeprecated => _deprecated;
3043
3044 @override
3045 bool get isPotentialMatch => _potential;
3046
3047 @override
3048 CompletionProposal setCompletion(String x) {
3049 _completion = x;
3050 if (_replacementLength == 0) {
3051 setReplacementLength(x.length);
3052 }
3053 return this;
3054 }
3055
3056 @override
3057 CompletionProposal setDeclaringType(String name) {
3058 _declaringType = name;
3059 return this;
3060 }
3061
3062 @override
3063 CompletionProposal setDeprecated(bool deprecated) {
3064 this._deprecated = deprecated;
3065 return this;
3066 }
3067
3068 @override
3069 CompletionProposal setElement(Element element) {
3070 this._element = element;
3071 return this;
3072 }
3073
3074 @override
3075 CompletionProposal setKind(ProposalKind x) {
3076 _kind = x;
3077 return this;
3078 }
3079
3080 @override
3081 CompletionProposal setLocation(int x) {
3082 _location = x;
3083 return this;
3084 }
3085
3086 @override
3087 CompletionProposal setParameterName(String parameterName) {
3088 this._parameterName = parameterName;
3089 return this;
3090 }
3091
3092 @override
3093 CompletionProposal setParameterNames(List<String> paramNames) {
3094 _parameterNames = paramNames;
3095 return this;
3096 }
3097
3098 @override
3099 CompletionProposal setParameterStyle(int count, bool named, bool positional) {
3100 this._named = named;
3101 this._positional = positional;
3102 this._positionalParameterCount = count;
3103 return this;
3104 }
3105
3106 @override
3107 CompletionProposal setParameterType(String parameterType) {
3108 this._parameterType = parameterType;
3109 return this;
3110 }
3111
3112 @override
3113 CompletionProposal setParameterTypes(List<String> paramTypes) {
3114 _parameterTypes = paramTypes;
3115 return this;
3116 }
3117
3118 @override
3119 CompletionProposal setPotentialMatch(bool isPotentialMatch) {
3120 _potential = isPotentialMatch;
3121 return this;
3122 }
3123
3124 @override
3125 CompletionProposal setRelevance(int n) {
3126 _relevance = n;
3127 return this;
3128 }
3129
3130 @override
3131 CompletionProposal setReplacementLength(int x) {
3132 _replacementLength = x;
3133 return this;
3134 }
3135
3136 @override
3137 CompletionProposal setReplacementLengthIdentifier(int x) {
3138 _replacementLength2 = x;
3139 return this;
3140 }
3141
3142 @override
3143 CompletionProposal setReturnType(String name) {
3144 _returnType = name;
3145 return this;
3146 }
3147 }
3148
3149 /**
3150 * A pathway for reporting completion proposals back to the client.
3151 */
3152 abstract class CompletionRequestor {
3153 /**
3154 * Record the given completion proposal for eventual presentation to the user.
3155 */
3156 accept(CompletionProposal proposal);
3157
3158 void beginReporting();
3159
3160 void endReporting();
3161 }
3162
3163 /**
3164 */
3165 class CompletionState {
3166 bool _isForMixin = false;
3167
3168 bool _isVoidAllowed = false;
3169
3170 bool _isDynamicAllowed = false;
3171
3172 bool _isSourceDeclarationStatic = false;
3173
3174 bool _isThisAllowed = true;
3175
3176 bool _isVarAllowed = false;
3177
3178 bool _areLiteralsAllowed = false;
3179
3180 bool _areLiteralsProhibited = false;
3181
3182 bool _areOperatorsAllowed = false;
3183
3184 bool _areStaticReferencesProhibited = false;
3185
3186 bool _areInstanceReferencesProhibited = false;
3187
3188 bool _areUndefinedTypesProhibited = false;
3189
3190 bool _isCompileTimeConstantRequired = false;
3191
3192 bool _isOptionalArgumentRequired = false;
3193
3194 bool _areMethodsProhibited = false;
3195
3196 bool _areClassesRequired = false;
3197
3198 ParameterElement _targetParameter;
3199
3200 void mustBeInstantiableType() {
3201 _areClassesRequired = true;
3202 _prohibitsLiterals();
3203 }
3204
3205 void _includesLiterals() {
3206 if (!_areLiteralsProhibited) {
3207 _areLiteralsAllowed = true;
3208 }
3209 }
3210
3211 void _includesOperators() {
3212 _areOperatorsAllowed = true;
3213 }
3214
3215 void _includesUndefinedDeclarationTypes() {
3216 if (!_areUndefinedTypesProhibited) {
3217 _isVoidAllowed = true;
3218 _isDynamicAllowed = true;
3219 }
3220 }
3221
3222 void _includesUndefinedTypes() {
3223 _isVarAllowed = true;
3224 _isDynamicAllowed = true;
3225 }
3226
3227 void _mustBeMixin() {
3228 _isForMixin = true;
3229 }
3230
3231 void _prohibitsInstanceReferences() {
3232 _areInstanceReferencesProhibited = true;
3233 }
3234
3235 void _prohibitsLiterals() {
3236 _areLiteralsAllowed = false;
3237 _areLiteralsProhibited = true;
3238 }
3239
3240 void _prohibitsStaticReferences() {
3241 _areStaticReferencesProhibited = true;
3242 }
3243
3244 void _prohibitThis() {
3245 _isThisAllowed = false;
3246 }
3247
3248 void _prohibitsUndefinedTypes() {
3249 _areUndefinedTypesProhibited = true;
3250 }
3251
3252 void _requiresConst(bool isConst) {
3253 _isCompileTimeConstantRequired = isConst;
3254 }
3255
3256 void _requiresOperators() {
3257 _includesOperators();
3258 _areMethodsProhibited = true;
3259 }
3260
3261 void _requiresOptionalArgument() {
3262 _isOptionalArgumentRequired = true;
3263 _prohibitsLiterals();
3264 }
3265
3266 void set context(AstNode base) {
3267 base.accept(new ContextAnalyzer(this, base));
3268 }
3269
3270 void _sourceDeclarationIsStatic(bool state) {
3271 _isSourceDeclarationStatic = state;
3272 if (state) {
3273 if (!_areStaticReferencesProhibited) {
3274 _prohibitsInstanceReferences();
3275 }
3276 }
3277 }
3278 }
3279
3280 /**
3281 */
3282 class ContextAnalyzer extends GeneralizingAstVisitor<Object> {
3283 final CompletionState _state;
3284
3285 final AstNode _completionNode;
3286
3287 AstNode _child;
3288
3289 bool _inExpression = false;
3290
3291 bool _inIdentifier = false;
3292
3293 bool _inTypeName = false;
3294
3295 bool _maybeInvocationArgument = true;
3296
3297 ContextAnalyzer(this._state, this._completionNode);
3298
3299 @override
3300 Object visitAnnotation(Annotation node) {
3301 _state._requiresConst(true);
3302 return super.visitAnnotation(node);
3303 }
3304
3305 @override
3306 Object visitCatchClause(CatchClause node) {
3307 if (identical(node.exceptionType, _child)) {
3308 _state._prohibitsLiterals();
3309 }
3310 return null;
3311 }
3312
3313 @override
3314 Object visitCompilationUnitMember(CompilationUnitMember node) {
3315 if (node is! ClassDeclaration) {
3316 _state._prohibitThis();
3317 }
3318 return super.visitCompilationUnitMember(node);
3319 }
3320
3321 @override
3322 Object visitConstructorInitializer(ConstructorInitializer node) {
3323 _state._prohibitThis();
3324 return super.visitConstructorInitializer(node);
3325 }
3326
3327 @override
3328 Object visitDirective(Directive node) {
3329 _state._prohibitsLiterals();
3330 return super.visitDirective(node);
3331 }
3332
3333 @override
3334 Object visitDoStatement(DoStatement node) {
3335 if (identical(_child, node.condition)) {
3336 _state._includesLiterals();
3337 }
3338 return super.visitDoStatement(node);
3339 }
3340
3341 @override
3342 Object visitExpression(Expression node) {
3343 _inExpression = true;
3344 _state._includesLiterals();
3345 _mayBeSetParameterElement(node);
3346 return super.visitExpression(node);
3347 }
3348
3349 @override
3350 Object visitFieldDeclaration(FieldDeclaration node) {
3351 _state._prohibitThis();
3352 return super.visitFieldDeclaration(node);
3353 }
3354
3355 @override
3356 Object visitForEachStatement(ForEachStatement node) {
3357 if (identical(_child, node.iterator)) {
3358 _state._includesLiterals();
3359 }
3360 return super.visitForEachStatement(node);
3361 }
3362
3363 @override
3364 Object visitFunctionExpression(FunctionExpression node) {
3365 if (node.parent is Declaration) {
3366 // Function expressions that are part of a declaration are not to be treat ed as expressions.
3367 return visitNode(node);
3368 } else {
3369 return visitExpression(node);
3370 }
3371 }
3372
3373 @override
3374 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
3375 if (_inTypeName || node.returnType == null) {
3376 // This may be an incomplete class type alias
3377 _state._includesUndefinedDeclarationTypes();
3378 }
3379 return super.visitFunctionTypeAlias(node);
3380 }
3381
3382 @override
3383 Object visitIdentifier(Identifier node) {
3384 _mayBeSetParameterElement(node);
3385 // Identifiers cannot safely be generalized to expressions, so just walk up one level.
3386 // LibraryIdentifier is never an expression. PrefixedIdentifier may be an ex pression, but
3387 // not in a catch-clause or a declaration. SimpleIdentifier may be an expres sion, but not
3388 // in a constructor name, label, or where PrefixedIdentifier is not.
3389 return visitNode(node);
3390 }
3391
3392 @override
3393 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
3394 _state._requiresConst(node.isConst);
3395 if (identical(_completionNode.parent.parent, _child)) {
3396 _state.mustBeInstantiableType();
3397 }
3398 return super.visitInstanceCreationExpression(node);
3399 }
3400
3401 @override
3402 Object visitMethodDeclaration(MethodDeclaration node) {
3403 _state._sourceDeclarationIsStatic(node.isStatic);
3404 if (identical(_child, node.returnType)) {
3405 _state._includesUndefinedDeclarationTypes();
3406 }
3407 if (node.isStatic) {
3408 _state._prohibitThis();
3409 }
3410 return super.visitMethodDeclaration(node);
3411 }
3412
3413 @override
3414 Object visitNode(AstNode node) {
3415 // Walk UP the tree, not down.
3416 AstNode parent = node.parent;
3417 _updateIfShouldGetTargetParameter(node, parent);
3418 if (parent != null) {
3419 _child = node;
3420 parent.accept(this);
3421 }
3422 return null;
3423 }
3424
3425 @override
3426 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
3427 if (identical(node, _completionNode) || identical(node.identifier, _completi onNode)) {
3428 SimpleIdentifier prefix = node.prefix;
3429 if (_isClassLiteral(prefix)) {
3430 _state._prohibitsInstanceReferences();
3431 } else {
3432 _state._prohibitsStaticReferences();
3433 }
3434 }
3435 return super.visitPrefixedIdentifier(node);
3436 }
3437
3438 @override
3439 Object visitPropertyAccess(PropertyAccess node) {
3440 if (identical(node, _completionNode) || identical(node.propertyName, _comple tionNode)) {
3441 Expression target = node.realTarget;
3442 if (_isClassLiteral(target)) {
3443 _state._prohibitsInstanceReferences();
3444 } else {
3445 _state._prohibitsStaticReferences();
3446 }
3447 }
3448 return super.visitPropertyAccess(node);
3449 }
3450
3451 @override
3452 Object visitSimpleFormalParameter(SimpleFormalParameter node) {
3453 _state._includesUndefinedTypes();
3454 return super.visitSimpleFormalParameter(node);
3455 }
3456
3457 @override
3458 Object visitSimpleIdentifier(SimpleIdentifier node) {
3459 _inIdentifier = true;
3460 return super.visitSimpleIdentifier(node);
3461 }
3462
3463 @override
3464 Object visitSwitchStatement(SwitchStatement node) {
3465 if (identical(_child, node.expression)) {
3466 _state._includesLiterals();
3467 }
3468 return super.visitSwitchStatement(node);
3469 }
3470
3471 @override
3472 Object visitTypeArgumentList(TypeArgumentList node) {
3473 _state._prohibitsUndefinedTypes();
3474 return super.visitTypeArgumentList(node);
3475 }
3476
3477 @override
3478 Object visitTypeName(TypeName node) {
3479 _inTypeName = true;
3480 return super.visitTypeName(node);
3481 }
3482
3483 @override
3484 Object visitVariableDeclaration(VariableDeclaration node) {
3485 if (identical(node.name, _completionNode)) {
3486 _state._prohibitsLiterals();
3487 }
3488 return super.visitVariableDeclaration(node);
3489 }
3490
3491 @override
3492 Object visitVariableDeclarationList(VariableDeclarationList node) {
3493 _state._includesUndefinedDeclarationTypes();
3494 return super.visitVariableDeclarationList(node);
3495 }
3496
3497 @override
3498 Object visitWhileStatement(WhileStatement node) {
3499 if (identical(_child, node.condition)) {
3500 _state._includesLiterals();
3501 }
3502 return super.visitWhileStatement(node);
3503 }
3504
3505 @override
3506 Object visitWithClause(WithClause node) {
3507 _state._mustBeMixin();
3508 return super.visitWithClause(node);
3509 }
3510
3511 bool _isClassLiteral(Expression expression) => expression is Identifier && exp ression.staticElement is ClassElement;
3512
3513 void _mayBeSetParameterElement(Expression node) {
3514 if (!_maybeInvocationArgument) {
3515 return;
3516 }
3517 if (node.parent is ArgumentList) {
3518 if (_state._targetParameter == null) {
3519 _state._targetParameter = node.bestParameterElement;
3520 }
3521 }
3522 }
3523
3524 void _updateIfShouldGetTargetParameter(AstNode node, AstNode parent) {
3525 if (!_maybeInvocationArgument) {
3526 return;
3527 }
3528 // prefix.node
3529 if (parent is PrefixedIdentifier) {
3530 if (identical(parent.identifier, node)) {
3531 return;
3532 }
3533 }
3534 // something unknown
3535 _maybeInvocationArgument = false;
3536 }
3537 }
3538
3539 class Filter {
3540 String _prefix;
3541
3542 String _originalPrefix;
3543
3544 RegExp _pattern;
3545
3546 Filter.con1(SimpleIdentifier ident, int loc) : this.con2(ident.name, ident.off set, loc);
3547
3548 Filter.con2(String name, int pos, int loc) {
3549 int len = loc - pos;
3550 if (len > 0) {
3551 if (len <= name.length) {
3552 _prefix = name.substring(0, len);
3553 } else {
3554 _prefix = name;
3555 }
3556 } else {
3557 _prefix = "";
3558 }
3559 _originalPrefix = _prefix;
3560 _prefix = _prefix.toLowerCase();
3561 }
3562
3563 /**
3564 * @return `true` if the given name starts with the same prefix as used for fi lter.
3565 */
3566 bool _isSameCasePrefix(String name) => name.startsWith(_originalPrefix);
3567
3568 String _makePattern() {
3569 // TODO(scheglov) translate it
3570 return null;
3571 }
3572
3573 bool _match(Element elem) => _match2(elem.displayName);
3574
3575 bool _match2(String name) {
3576 // Return true if the filter passes.
3577 if (name.toLowerCase().startsWith(_prefix)) {
3578 return true;
3579 }
3580 return _matchPattern(name);
3581 }
3582
3583 void _removeNotMatching(List<Element> elements) {
3584 for (JavaIterator<Element> I = new JavaIterator(elements); I.hasNext;) {
3585 Element element = I.next();
3586 if (!_match(element)) {
3587 I.remove();
3588 }
3589 }
3590 }
3591
3592 bool _matchPattern(String name) {
3593 // TODO(scheglov) translate it
3594 return false;
3595 }
3596 }
3597
3598 class GeneralizingAstVisitor_CompletionEngine_copyWithout extends GeneralizingAs tVisitor<Object> {
3599 AstNode deletion;
3600
3601 List<FormalParameter> newList;
3602
3603 GeneralizingAstVisitor_CompletionEngine_copyWithout(this.deletion, this.newLis t) : super();
3604
3605 @override
3606 Object visitNode(AstNode node) {
3607 if (!identical(node, deletion)) {
3608 newList.add(node as FormalParameter);
3609 }
3610 return null;
3611 }
3612 }
3613
3614 /**
3615 * An [Ident] is a wrapper for a String that provides type equivalence with Simp leIdentifier.
3616 */
3617 class Ident extends EphemeralIdentifier {
3618 String _name;
3619
3620 Ident.con1(AstNode parent, int offset) : super(parent, offset);
3621
3622 Ident.con2(AstNode parent, String name, int offset) : super(parent, offset) {
3623 this._name = name;
3624 }
3625
3626 Ident.con3(AstNode parent, Token name) : super(parent, name.offset) {
3627 this._name = name.lexeme;
3628 }
3629
3630 @override
3631 String get name {
3632 if (_name != null) {
3633 return _name;
3634 }
3635 String n = super.name;
3636 if (n != null) {
3637 return n;
3638 }
3639 return "";
3640 }
3641 }
3642
3643 class ProposalCollector implements CompletionRequestor {
3644 final CompletionRequestor requestor;
3645
3646 List<CompletionProposal> _proposals;
3647
3648 ProposalCollector(this.requestor) {
3649 this._proposals = new List<CompletionProposal>();
3650 }
3651
3652 @override
3653 accept(CompletionProposal proposal) {
3654 _proposals.add(proposal);
3655 }
3656
3657 @override
3658 void beginReporting() {
3659 requestor.beginReporting();
3660 }
3661
3662 @override
3663 void endReporting() {
3664 requestor.endReporting();
3665 }
3666
3667 List<CompletionProposal> get proposals => _proposals;
3668 }
3669
3670 /**
3671 * The various kinds of completion proposals. Each specifies the kind of complet ion to be created,
3672 * corresponding to different syntactical elements.
3673 */
3674 class ProposalKind extends Enum<ProposalKind> {
3675 static const ProposalKind NONE = const ProposalKind('NONE', 0);
3676
3677 static const ProposalKind CLASS = const ProposalKind('CLASS', 1);
3678
3679 static const ProposalKind CLASS_ALIAS = const ProposalKind('CLASS_ALIAS', 2);
3680
3681 static const ProposalKind CONSTRUCTOR = const ProposalKind('CONSTRUCTOR', 3);
3682
3683 static const ProposalKind FIELD = const ProposalKind('FIELD', 4);
3684
3685 static const ProposalKind FUNCTION = const ProposalKind('FUNCTION', 5);
3686
3687 static const ProposalKind FUNCTION_ALIAS = const ProposalKind('FUNCTION_ALIAS' , 6);
3688
3689 static const ProposalKind GETTER = const ProposalKind('GETTER', 7);
3690
3691 static const ProposalKind IMPORT = const ProposalKind('IMPORT', 8);
3692
3693 static const ProposalKind LIBRARY_PREFIX = const ProposalKind('LIBRARY_PREFIX' , 9);
3694
3695 static const ProposalKind METHOD = const ProposalKind('METHOD', 10);
3696
3697 static const ProposalKind METHOD_NAME = const ProposalKind('METHOD_NAME', 11);
3698
3699 static const ProposalKind PARAMETER = const ProposalKind('PARAMETER', 12);
3700
3701 static const ProposalKind SETTER = const ProposalKind('SETTER', 13);
3702
3703 static const ProposalKind VARIABLE = const ProposalKind('VARIABLE', 14);
3704
3705 static const ProposalKind TYPE_PARAMETER = const ProposalKind('TYPE_PARAMETER' , 15);
3706
3707 static const ProposalKind ARGUMENT_LIST = const ProposalKind('ARGUMENT_LIST', 16);
3708
3709 static const ProposalKind OPTIONAL_ARGUMENT = const ProposalKind('OPTIONAL_ARG UMENT', 17);
3710
3711 static const ProposalKind NAMED_ARGUMENT = const ProposalKind('NAMED_ARGUMENT' , 18);
3712
3713 static const List<ProposalKind> values = const [
3714 NONE,
3715 CLASS,
3716 CLASS_ALIAS,
3717 CONSTRUCTOR,
3718 FIELD,
3719 FUNCTION,
3720 FUNCTION_ALIAS,
3721 GETTER,
3722 IMPORT,
3723 LIBRARY_PREFIX,
3724 METHOD,
3725 METHOD_NAME,
3726 PARAMETER,
3727 SETTER,
3728 VARIABLE,
3729 TYPE_PARAMETER,
3730 ARGUMENT_LIST,
3731 OPTIONAL_ARGUMENT,
3732 NAMED_ARGUMENT];
3733
3734 const ProposalKind(String name, int ordinal) : super(name, ordinal);
3735 }
3736
3737 class SearchFilter_CompletionEngine_allSubtypes implements SearchFilter {
3738 ClassElement classElement;
3739
3740 SearchFilter_CompletionEngine_allSubtypes(this.classElement);
3741
3742 @override
3743 bool passes(SearchMatch match) {
3744 Element element = match.element;
3745 if (element is ClassElement) {
3746 ClassElement clElem = element;
3747 while (clElem != null) {
3748 InterfaceType ifType = clElem.supertype;
3749 if (ifType == null) {
3750 return false;
3751 }
3752 clElem = ifType.element;
3753 if (identical(clElem, classElement)) {
3754 return true;
3755 }
3756 }
3757 }
3758 return false;
3759 }
3760 }
3761
3762 class TopLevelNamesKind extends Enum<TopLevelNamesKind> {
3763 static const TopLevelNamesKind DECLARED_AND_IMPORTS = const TopLevelNamesKind( 'DECLARED_AND_IMPORTS', 0);
3764
3765 static const TopLevelNamesKind DECLARED_AND_EXPORTS = const TopLevelNamesKind( 'DECLARED_AND_EXPORTS', 1);
3766
3767 static const List<TopLevelNamesKind> values = const [DECLARED_AND_IMPORTS, DEC LARED_AND_EXPORTS];
3768
3769 const TopLevelNamesKind(String name, int ordinal) : super(name, ordinal);
3770 }
OLDNEW
« no previous file with comments | « pkg/analysis_services/lib/src/generated/change.dart ('k') | pkg/analysis_services/lib/src/generated/proposal.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698