| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library services.completion.computer.dart.toplevel; | 5 library services.completion.computer.dart.toplevel; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/src/protocol_server.dart' hide Element, | 9 import 'package:analysis_server/src/protocol_server.dart' hide Element, |
| 10 ElementKind; | 10 ElementKind; |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 var directive = node.getAncestor((parent) => parent is NamespaceDirective); | 189 var directive = node.getAncestor((parent) => parent is NamespaceDirective); |
| 190 if (directive is NamespaceDirective) { | 190 if (directive is NamespaceDirective) { |
| 191 LibraryElement library = directive.uriElement; | 191 LibraryElement library = directive.uriElement; |
| 192 LibraryElementSuggestionBuilder.suggestionsFor(request, library); | 192 LibraryElementSuggestionBuilder.suggestionsFor(request, library); |
| 193 return new Future.value(true); | 193 return new Future.value(true); |
| 194 } | 194 } |
| 195 | 195 |
| 196 return new Future.value(false); | 196 return new Future.value(false); |
| 197 } | 197 } |
| 198 | 198 |
| 199 void _addElementSuggestion(Element element, bool typesOnly, bool excludeVoidRe
turn, CompletionRelevance relevance) { | 199 void _addElementSuggestion(Element element, bool typesOnly, |
| 200 bool excludeVoidReturn, CompletionRelevance relevance) { |
| 200 | 201 |
| 201 if (element is ExecutableElement) { | 202 if (element is ExecutableElement) { |
| 202 if (element.isOperator) { | 203 if (element.isOperator) { |
| 203 return; | 204 return; |
| 204 } | 205 } |
| 205 if (excludeVoidReturn) { | 206 if (excludeVoidReturn) { |
| 206 DartType returnType = element.returnType; | 207 DartType returnType = element.returnType; |
| 207 if (returnType != null && returnType.isVoid) { | 208 if (returnType != null && returnType.isVoid) { |
| 208 return; | 209 return; |
| 209 } | 210 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 239 if (type != null) { | 240 if (type != null) { |
| 240 String name = type.displayName; | 241 String name = type.displayName; |
| 241 if (name != null && name.length > 0 && name != 'dynamic') { | 242 if (name != null && name.length > 0 && name != 'dynamic') { |
| 242 suggestion.returnType = name; | 243 suggestion.returnType = name; |
| 243 } | 244 } |
| 244 } | 245 } |
| 245 | 246 |
| 246 request.suggestions.add(suggestion); | 247 request.suggestions.add(suggestion); |
| 247 } | 248 } |
| 248 | 249 |
| 249 void _addElementSuggestions(List<Element> elements, bool typesOnly, bool exclu
deVoidReturn) { | 250 void _addElementSuggestions(List<Element> elements, bool typesOnly, |
| 251 bool excludeVoidReturn) { |
| 250 elements.forEach((Element elem) { | 252 elements.forEach((Element elem) { |
| 251 _addElementSuggestion(elem, typesOnly, excludeVoidReturn, CompletionReleva
nce.DEFAULT); | 253 _addElementSuggestion( |
| 254 elem, |
| 255 typesOnly, |
| 256 excludeVoidReturn, |
| 257 CompletionRelevance.DEFAULT); |
| 252 }); | 258 }); |
| 253 } | 259 } |
| 254 | 260 |
| 255 Future<bool> _addImportedElementSuggestions(AstNode node, {bool typesOnly: | 261 Future<bool> _addImportedElementSuggestions(AstNode node, {bool typesOnly: |
| 256 false, bool excludeVoidReturn: false}) { | 262 false, bool excludeVoidReturn: false}) { |
| 257 | 263 |
| 258 // Exclude elements from local library | 264 // Exclude elements from local library |
| 259 // because they are provided by LocalComputer | 265 // because they are provided by LocalComputer |
| 260 Set<LibraryElement> excludedLibs = new Set<LibraryElement>(); | 266 Set<LibraryElement> excludedLibs = new Set<LibraryElement>(); |
| 261 excludedLibs.add(request.unit.element.enclosingElement); | 267 excludedLibs.add(request.unit.element.enclosingElement); |
| 262 | 268 |
| 263 // Include explicitly imported elements | 269 // Include explicitly imported elements |
| 264 Map<String, ClassElement> classMap = new Map<String, ClassElement>(); | 270 Map<String, ClassElement> classMap = new Map<String, ClassElement>(); |
| 265 request.unit.directives.forEach((Directive directive) { | 271 request.unit.directives.forEach((Directive directive) { |
| 266 if (directive is ImportDirective) { | 272 if (directive is ImportDirective) { |
| 267 ImportElement importElem = directive.element; | 273 ImportElement importElem = directive.element; |
| 268 if (importElem != null && importElem.importedLibrary != null) { | 274 if (importElem != null && importElem.importedLibrary != null) { |
| 269 if (directive.prefix == null) { | 275 if (directive.prefix == null) { |
| 270 Namespace importNamespace = | 276 Namespace importNamespace = |
| 271 new NamespaceBuilder().createImportNamespaceForDirective(importE
lem); | 277 new NamespaceBuilder().createImportNamespaceForDirective(importE
lem); |
| 272 // Include top level elements | 278 // Include top level elements |
| 273 importNamespace.definedNames.forEach((String name, Element elem) { | 279 importNamespace.definedNames.forEach((String name, Element elem) { |
| 274 if (elem is ClassElement) { | 280 if (elem is ClassElement) { |
| 275 classMap[name] = elem; | 281 classMap[name] = elem; |
| 276 } | 282 } |
| 277 _addElementSuggestion(elem, typesOnly, excludeVoidReturn, Comple
tionRelevance.DEFAULT); | 283 _addElementSuggestion( |
| 284 elem, |
| 285 typesOnly, |
| 286 excludeVoidReturn, |
| 287 CompletionRelevance.DEFAULT); |
| 278 }); | 288 }); |
| 279 } else { | 289 } else { |
| 280 // Exclude elements from prefixed imports | 290 // Exclude elements from prefixed imports |
| 281 // because they are provided by InvocationComputer | 291 // because they are provided by InvocationComputer |
| 282 excludedLibs.add(importElem.importedLibrary); | 292 excludedLibs.add(importElem.importedLibrary); |
| 283 _addLibraryPrefixSuggestion(importElem); | 293 _addLibraryPrefixSuggestion(importElem); |
| 284 } | 294 } |
| 285 } | 295 } |
| 286 } | 296 } |
| 287 }); | 297 }); |
| 288 | 298 |
| 289 // Include implicitly imported dart:core elements | 299 // Include implicitly imported dart:core elements |
| 290 Source coreUri = request.context.sourceFactory.forUri('dart:core'); | 300 Source coreUri = request.context.sourceFactory.forUri('dart:core'); |
| 291 LibraryElement coreLib = request.context.getLibraryElement(coreUri); | 301 LibraryElement coreLib = request.context.getLibraryElement(coreUri); |
| 292 Namespace coreNamespace = | 302 Namespace coreNamespace = |
| 293 new NamespaceBuilder().createPublicNamespaceForLibrary(coreLib); | 303 new NamespaceBuilder().createPublicNamespaceForLibrary(coreLib); |
| 294 coreNamespace.definedNames.forEach((String name, Element elem) { | 304 coreNamespace.definedNames.forEach((String name, Element elem) { |
| 295 if (elem is ClassElement) { | 305 if (elem is ClassElement) { |
| 296 classMap[name] = elem; | 306 classMap[name] = elem; |
| 297 } | 307 } |
| 298 _addElementSuggestion(elem, typesOnly, excludeVoidReturn, CompletionRele
vance.DEFAULT); | 308 _addElementSuggestion( |
| 309 elem, |
| 310 typesOnly, |
| 311 excludeVoidReturn, |
| 312 CompletionRelevance.DEFAULT); |
| 299 }); | 313 }); |
| 300 | 314 |
| 301 // Build a list of inherited types that are imported | 315 // Build a list of inherited types that are imported |
| 302 // and include any inherited imported members | 316 // and include any inherited imported members |
| 303 var classDecl = node.getAncestor((p) => p is ClassDeclaration); | 317 var classDecl = node.getAncestor((p) => p is ClassDeclaration); |
| 304 if (classDecl is ClassDeclaration) { | 318 if (classDecl is ClassDeclaration) { |
| 305 List<String> inheritedTypes = new List<String>(); | 319 List<String> inheritedTypes = new List<String>(); |
| 306 visitInheritedTypes(classDecl, (ClassDeclaration classDecl) { | 320 visitInheritedTypes(classDecl, (ClassDeclaration classDecl) { |
| 307 // ignored | 321 // ignored |
| 308 }, (String typeName) { | 322 }, (String typeName) { |
| 309 inheritedTypes.add(typeName); | 323 inheritedTypes.add(typeName); |
| 310 }); | 324 }); |
| 311 Set<String> visited = new Set<String>(); | 325 Set<String> visited = new Set<String>(); |
| 312 while (inheritedTypes.length > 0) { | 326 while (inheritedTypes.length > 0) { |
| 313 String name = inheritedTypes.removeLast(); | 327 String name = inheritedTypes.removeLast(); |
| 314 ClassElement elem = classMap[name]; | 328 ClassElement elem = classMap[name]; |
| 315 if (visited.add(name) && elem != null) { | 329 if (visited.add(name) && elem != null) { |
| 316 _addElementSuggestions(elem.accessors, typesOnly, excludeVoidReturn); | 330 _addElementSuggestions(elem.accessors, typesOnly, excludeVoidReturn); |
| 317 _addElementSuggestions(elem.methods, typesOnly, excludeVoidReturn); | 331 _addElementSuggestions(elem.methods, typesOnly, excludeVoidReturn); |
| 318 elem.allSupertypes.forEach((InterfaceType type) { | 332 elem.allSupertypes.forEach((InterfaceType type) { |
| 319 if (visited.add(type.name)) { | 333 if (visited.add(type.name)) { |
| 320 _addElementSuggestions(type.accessors, typesOnly, excludeVoidRetur
n); | 334 _addElementSuggestions( |
| 321 _addElementSuggestions(type.methods, typesOnly, excludeVoidReturn)
; | 335 type.accessors, |
| 336 typesOnly, |
| 337 excludeVoidReturn); |
| 338 _addElementSuggestions( |
| 339 type.methods, |
| 340 typesOnly, |
| 341 excludeVoidReturn); |
| 322 } | 342 } |
| 323 }); | 343 }); |
| 324 } | 344 } |
| 325 } | 345 } |
| 326 } | 346 } |
| 327 | 347 |
| 328 // Add non-imported elements as low relevance | 348 // Add non-imported elements as low relevance |
| 329 var future = request.searchEngine.searchTopLevelDeclarations(''); | 349 var future = request.searchEngine.searchTopLevelDeclarations(''); |
| 330 return future.then((List<SearchMatch> matches) { | 350 return future.then((List<SearchMatch> matches) { |
| 331 Set<String> completionSet = new Set<String>(); | 351 Set<String> completionSet = new Set<String>(); |
| 332 request.suggestions.forEach((CompletionSuggestion suggestion) { | 352 request.suggestions.forEach((CompletionSuggestion suggestion) { |
| 333 completionSet.add(suggestion.completion); | 353 completionSet.add(suggestion.completion); |
| 334 }); | 354 }); |
| 335 matches.forEach((SearchMatch match) { | 355 matches.forEach((SearchMatch match) { |
| 336 if (match.kind == MatchKind.DECLARATION) { | 356 if (match.kind == MatchKind.DECLARATION) { |
| 337 Element element = match.element; | 357 Element element = match.element; |
| 338 if (element.isPublic && | 358 if (element.isPublic && |
| 339 !excludedLibs.contains(element.library) && | 359 !excludedLibs.contains(element.library) && |
| 340 !completionSet.contains(element.displayName)) { | 360 !completionSet.contains(element.displayName)) { |
| 341 if (!typesOnly || element is ClassElement) { | 361 if (!typesOnly || element is ClassElement) { |
| 342 _addElementSuggestion(element, typesOnly, excludeVoidReturn, Compl
etionRelevance.LOW); | 362 _addElementSuggestion( |
| 363 element, |
| 364 typesOnly, |
| 365 excludeVoidReturn, |
| 366 CompletionRelevance.LOW); |
| 343 } | 367 } |
| 344 } | 368 } |
| 345 } | 369 } |
| 346 }); | 370 }); |
| 347 return true; | 371 return true; |
| 348 }); | 372 }); |
| 349 } | 373 } |
| 350 | 374 |
| 351 void _addLibraryPrefixSuggestion(ImportElement importElem) { | 375 void _addLibraryPrefixSuggestion(ImportElement importElem) { |
| 352 String completion = importElem.prefix.displayName; | 376 String completion = importElem.prefix.displayName; |
| 353 if (completion != null && completion.length > 0) { | 377 if (completion != null && completion.length > 0) { |
| 354 CompletionSuggestion suggestion = new CompletionSuggestion( | 378 CompletionSuggestion suggestion = new CompletionSuggestion( |
| 355 CompletionSuggestionKind.LIBRARY_PREFIX, | 379 CompletionSuggestionKind.LIBRARY_PREFIX, |
| 356 CompletionRelevance.DEFAULT, | 380 CompletionRelevance.DEFAULT, |
| 357 completion, | 381 completion, |
| 358 completion.length, | 382 completion.length, |
| 359 0, | 383 0, |
| 360 importElem.isDeprecated, | 384 importElem.isDeprecated, |
| 361 false); | 385 false); |
| 362 LibraryElement lib = importElem.importedLibrary; | 386 LibraryElement lib = importElem.importedLibrary; |
| 363 if (lib != null) { | 387 if (lib != null) { |
| 364 suggestion.element = newElement_fromEngine(lib); | 388 suggestion.element = newElement_fromEngine(lib); |
| 365 } | 389 } |
| 366 request.suggestions.add(suggestion); | 390 request.suggestions.add(suggestion); |
| 367 } | 391 } |
| 368 } | 392 } |
| 369 } | 393 } |
| OLD | NEW |