| 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 final DartCompletionRequest request; | 45 final DartCompletionRequest request; |
| 46 | 46 |
| 47 _ImportedVisitor(this.request); | 47 _ImportedVisitor(this.request); |
| 48 | 48 |
| 49 @override | 49 @override |
| 50 Future<bool> visitBlock(Block node) { | 50 Future<bool> visitBlock(Block node) { |
| 51 return _addImportedElementSuggestions(); | 51 return _addImportedElementSuggestions(); |
| 52 } | 52 } |
| 53 | 53 |
| 54 @override | 54 @override |
| 55 Future<bool> visitCascadeExpression(CascadeExpression node) { |
| 56 // Make suggestions for the target, but not for the selector |
| 57 // InvocationComputer makes selector suggestions |
| 58 Expression target = node.target; |
| 59 if (target != null && request.offset <= target.end) { |
| 60 return _addImportedElementSuggestions(); |
| 61 } |
| 62 return new Future.value(false); |
| 63 } |
| 64 |
| 65 @override |
| 55 Future<bool> visitCombinator(Combinator node) { | 66 Future<bool> visitCombinator(Combinator node) { |
| 56 return _addCombinatorSuggestions(node); | 67 return _addCombinatorSuggestions(node); |
| 57 } | 68 } |
| 58 | 69 |
| 59 @override | 70 @override |
| 60 Future<bool> visitExpressionStatement(ExpressionStatement node) { | 71 Future<bool> visitExpressionStatement(ExpressionStatement node) { |
| 61 Expression expression = node.expression; | 72 Expression expression = node.expression; |
| 62 // A pre-variable declaration (e.g. C ^) is parsed as an expression | 73 // A pre-variable declaration (e.g. C ^) is parsed as an expression |
| 63 // statement. Do not make suggestions for the variable name. | 74 // statement. Do not make suggestions for the variable name. |
| 64 if (expression is SimpleIdentifier && request.offset <= expression.end) { | 75 if (expression is SimpleIdentifier && request.offset <= expression.end) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 76 Future<bool> visitPrefixedIdentifier(PrefixedIdentifier node) { | 87 Future<bool> visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 77 // Make suggestions for the prefix, but not for the selector | 88 // Make suggestions for the prefix, but not for the selector |
| 78 // InvocationComputer makes selector suggestions | 89 // InvocationComputer makes selector suggestions |
| 79 if (request.offset <= node.prefix.end) { | 90 if (request.offset <= node.prefix.end) { |
| 80 return _addImportedElementSuggestions(); | 91 return _addImportedElementSuggestions(); |
| 81 } | 92 } |
| 82 return new Future.value(false); | 93 return new Future.value(false); |
| 83 } | 94 } |
| 84 | 95 |
| 85 @override | 96 @override |
| 86 Future<bool> visitCascadeExpression(CascadeExpression node) { | |
| 87 // Make suggestions for the target, but not for the selector | |
| 88 // InvocationComputer makes selector suggestions | |
| 89 Expression target = node.target; | |
| 90 if (target != null && request.offset <= target.end) { | |
| 91 return _addImportedElementSuggestions(); | |
| 92 } | |
| 93 return new Future.value(false); | |
| 94 } | |
| 95 | |
| 96 @override | |
| 97 Future<bool> visitSimpleIdentifier(SimpleIdentifier node) { | 97 Future<bool> visitSimpleIdentifier(SimpleIdentifier node) { |
| 98 return node.parent.accept(this); | 98 return node.parent.accept(this); |
| 99 } | 99 } |
| 100 | 100 |
| 101 @override |
| 102 Future<bool> visitTypeName(TypeName node) { |
| 103 return _addImportedElementSuggestions(typesOnly: true); |
| 104 } |
| 105 |
| 101 Future _addCombinatorSuggestions(Combinator node) { | 106 Future _addCombinatorSuggestions(Combinator node) { |
| 102 var directive = node.getAncestor((parent) => parent is NamespaceDirective); | 107 var directive = node.getAncestor((parent) => parent is NamespaceDirective); |
| 103 if (directive is NamespaceDirective) { | 108 if (directive is NamespaceDirective) { |
| 104 LibraryElement library = directive.uriElement; | 109 LibraryElement library = directive.uriElement; |
| 105 LibraryElementSuggestionBuilder.suggestionsFor(request, library); | 110 LibraryElementSuggestionBuilder.suggestionsFor(request, library); |
| 106 return new Future.value(true); | 111 return new Future.value(true); |
| 107 } | 112 } |
| 108 | 113 |
| 109 return new Future.value(false); | 114 return new Future.value(false); |
| 110 } | 115 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 136 if (type != null) { | 141 if (type != null) { |
| 137 String name = type.displayName; | 142 String name = type.displayName; |
| 138 if (name != null && name.length > 0 && name != 'dynamic') { | 143 if (name != null && name.length > 0 && name != 'dynamic') { |
| 139 suggestion.returnType = name; | 144 suggestion.returnType = name; |
| 140 } | 145 } |
| 141 } | 146 } |
| 142 | 147 |
| 143 request.suggestions.add(suggestion); | 148 request.suggestions.add(suggestion); |
| 144 } | 149 } |
| 145 | 150 |
| 146 Future<bool> _addImportedElementSuggestions() { | 151 Future<bool> _addImportedElementSuggestions({bool typesOnly: false}) { |
| 147 | 152 |
| 148 // Exclude elements from local library | 153 // Exclude elements from local library |
| 149 // because they are provided by LocalComputer | 154 // because they are provided by LocalComputer |
| 150 Set<LibraryElement> excludedLibs = new Set<LibraryElement>(); | 155 Set<LibraryElement> excludedLibs = new Set<LibraryElement>(); |
| 151 excludedLibs.add(request.unit.element.enclosingElement); | 156 excludedLibs.add(request.unit.element.enclosingElement); |
| 152 | 157 |
| 153 // Include explicitly imported elements | 158 // Include explicitly imported elements |
| 154 request.unit.directives.forEach((Directive directive) { | 159 request.unit.directives.forEach((Directive directive) { |
| 155 if (directive is ImportDirective) { | 160 if (directive is ImportDirective) { |
| 156 ImportElement importElem = directive.element; | 161 ImportElement importElem = directive.element; |
| 157 if (importElem != null && importElem.importedLibrary != null) { | 162 if (importElem != null && importElem.importedLibrary != null) { |
| 158 if (directive.prefix == null) { | 163 if (directive.prefix == null) { |
| 159 Namespace importNamespace = | 164 Namespace importNamespace = |
| 160 new NamespaceBuilder().createImportNamespaceForDirective(importE
lem); | 165 new NamespaceBuilder().createImportNamespaceForDirective(importE
lem); |
| 161 importNamespace.definedNames.forEach((_, Element element) { | 166 importNamespace.definedNames.forEach((_, Element element) { |
| 162 _addElementSuggestion(element, CompletionRelevance.DEFAULT); | 167 if (!typesOnly || element is ClassElement) { |
| 168 _addElementSuggestion(element, CompletionRelevance.DEFAULT); |
| 169 } |
| 163 }); | 170 }); |
| 164 } else { | 171 } else { |
| 165 // Exclude elements from prefixed imports | 172 // Exclude elements from prefixed imports |
| 166 // because they are provided by InvocationComputer | 173 // because they are provided by InvocationComputer |
| 167 excludedLibs.add(importElem.importedLibrary); | 174 excludedLibs.add(importElem.importedLibrary); |
| 168 _addLibraryPrefixSuggestion(importElem); | 175 _addLibraryPrefixSuggestion(importElem); |
| 169 } | 176 } |
| 170 } | 177 } |
| 171 } | 178 } |
| 172 }); | 179 }); |
| 173 | 180 |
| 174 // Include implicitly imported dart:core elements | 181 // Include implicitly imported dart:core elements |
| 175 Source coreUri = request.context.sourceFactory.forUri('dart:core'); | 182 Source coreUri = request.context.sourceFactory.forUri('dart:core'); |
| 176 LibraryElement coreLib = request.context.getLibraryElement(coreUri); | 183 LibraryElement coreLib = request.context.getLibraryElement(coreUri); |
| 177 Namespace coreNamespace = | 184 Namespace coreNamespace = |
| 178 new NamespaceBuilder().createPublicNamespaceForLibrary(coreLib); | 185 new NamespaceBuilder().createPublicNamespaceForLibrary(coreLib); |
| 179 coreNamespace.definedNames.forEach((_, Element element) { | 186 coreNamespace.definedNames.forEach((_, Element element) { |
| 180 _addElementSuggestion(element, CompletionRelevance.DEFAULT); | 187 if (!typesOnly || element is ClassElement) { |
| 188 _addElementSuggestion(element, CompletionRelevance.DEFAULT); |
| 189 } |
| 181 }); | 190 }); |
| 182 | 191 |
| 183 // Add non-imported elements as low relevance | 192 // Add non-imported elements as low relevance |
| 184 var future = request.searchEngine.searchTopLevelDeclarations(''); | 193 var future = request.searchEngine.searchTopLevelDeclarations(''); |
| 185 return future.then((List<SearchMatch> matches) { | 194 return future.then((List<SearchMatch> matches) { |
| 186 Set<String> completionSet = new Set<String>(); | 195 Set<String> completionSet = new Set<String>(); |
| 187 request.suggestions.forEach((CompletionSuggestion suggestion) { | 196 request.suggestions.forEach((CompletionSuggestion suggestion) { |
| 188 completionSet.add(suggestion.completion); | 197 completionSet.add(suggestion.completion); |
| 189 }); | 198 }); |
| 190 matches.forEach((SearchMatch match) { | 199 matches.forEach((SearchMatch match) { |
| 191 if (match.kind == MatchKind.DECLARATION) { | 200 if (match.kind == MatchKind.DECLARATION) { |
| 192 Element element = match.element; | 201 Element element = match.element; |
| 193 if (element.isPublic && | 202 if (element.isPublic && |
| 194 !excludedLibs.contains(element.library) && | 203 !excludedLibs.contains(element.library) && |
| 195 !completionSet.contains(element.displayName)) { | 204 !completionSet.contains(element.displayName)) { |
| 196 _addElementSuggestion(element, CompletionRelevance.LOW); | 205 if (!typesOnly || element is ClassElement) { |
| 206 _addElementSuggestion(element, CompletionRelevance.LOW); |
| 207 } |
| 197 } | 208 } |
| 198 } | 209 } |
| 199 }); | 210 }); |
| 200 return true; | 211 return true; |
| 201 }); | 212 }); |
| 202 } | 213 } |
| 203 | 214 |
| 204 void _addLibraryPrefixSuggestion(ImportElement importElem) { | 215 void _addLibraryPrefixSuggestion(ImportElement importElem) { |
| 205 String completion = importElem.prefix.displayName; | 216 String completion = importElem.prefix.displayName; |
| 206 if (completion != null && completion.length > 0) { | 217 if (completion != null && completion.length > 0) { |
| 207 CompletionSuggestion suggestion = new CompletionSuggestion( | 218 CompletionSuggestion suggestion = new CompletionSuggestion( |
| 208 CompletionSuggestionKind.LIBRARY_PREFIX, | 219 CompletionSuggestionKind.LIBRARY_PREFIX, |
| 209 CompletionRelevance.DEFAULT, | 220 CompletionRelevance.DEFAULT, |
| 210 completion, | 221 completion, |
| 211 completion.length, | 222 completion.length, |
| 212 0, | 223 0, |
| 213 importElem.isDeprecated, | 224 importElem.isDeprecated, |
| 214 false); | 225 false); |
| 215 LibraryElement lib = importElem.importedLibrary; | 226 LibraryElement lib = importElem.importedLibrary; |
| 216 if (lib != null) { | 227 if (lib != null) { |
| 217 suggestion.element = newElement_fromEngine(lib); | 228 suggestion.element = newElement_fromEngine(lib); |
| 218 } | 229 } |
| 219 request.suggestions.add(suggestion); | 230 request.suggestions.add(suggestion); |
| 220 } | 231 } |
| 221 } | 232 } |
| 222 } | 233 } |
| OLD | NEW |