| OLD | NEW |
| (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 } |
| OLD | NEW |