| 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.dart; | 5 library services.completion.dart; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/plugin/protocol/protocol.dart'; | 9 import 'package:analysis_server/plugin/protocol/protocol.dart'; |
| 10 import 'package:analysis_server/src/analysis_server.dart'; | 10 import 'package:analysis_server/src/analysis_server.dart'; |
| 11 import 'package:analysis_server/src/provisional/completion/completion_core.dart' | 11 import 'package:analysis_server/src/provisional/completion/completion_core.dart' |
| 12 show AnalysisRequest, CompletionRequest; | 12 show AnalysisRequest, CompletionContributor, CompletionRequest; |
| 13 import 'package:analysis_server/src/provisional/completion/dart/completion_targe
t.dart'; | 13 import 'package:analysis_server/src/provisional/completion/dart/completion_targe
t.dart'; |
| 14 import 'package:analysis_server/src/services/completion/arglist_contributor.dart
'; | 14 import 'package:analysis_server/src/services/completion/arglist_contributor.dart
'; |
| 15 import 'package:analysis_server/src/services/completion/combinator_contributor.d
art'; | 15 import 'package:analysis_server/src/services/completion/combinator_contributor.d
art'; |
| 16 import 'package:analysis_server/src/services/completion/completion_manager.dart'
; | 16 import 'package:analysis_server/src/services/completion/completion_manager.dart'
; |
| 17 import 'package:analysis_server/src/services/completion/dart/common_usage_sorter
.dart'; | 17 import 'package:analysis_server/src/services/completion/dart/common_usage_sorter
.dart'; |
| 18 import 'package:analysis_server/src/services/completion/dart/completion_manager.
dart' |
| 19 as newImpl; |
| 18 import 'package:analysis_server/src/services/completion/dart/contribution_sorter
.dart'; | 20 import 'package:analysis_server/src/services/completion/dart/contribution_sorter
.dart'; |
| 19 import 'package:analysis_server/src/services/completion/dart_completion_cache.da
rt'; | 21 import 'package:analysis_server/src/services/completion/dart_completion_cache.da
rt'; |
| 20 import 'package:analysis_server/src/services/completion/imported_reference_contr
ibutor.dart'; | 22 import 'package:analysis_server/src/services/completion/imported_reference_contr
ibutor.dart'; |
| 21 import 'package:analysis_server/src/services/completion/keyword_contributor.dart
'; | |
| 22 import 'package:analysis_server/src/services/completion/local_reference_contribu
tor.dart'; | 23 import 'package:analysis_server/src/services/completion/local_reference_contribu
tor.dart'; |
| 23 import 'package:analysis_server/src/services/completion/optype.dart'; | 24 import 'package:analysis_server/src/services/completion/optype.dart'; |
| 24 import 'package:analysis_server/src/services/completion/prefixed_element_contrib
utor.dart'; | 25 import 'package:analysis_server/src/services/completion/prefixed_element_contrib
utor.dart'; |
| 25 import 'package:analysis_server/src/services/completion/uri_contributor.dart'; | 26 import 'package:analysis_server/src/services/completion/uri_contributor.dart'; |
| 26 import 'package:analysis_server/src/services/search/search_engine.dart'; | 27 import 'package:analysis_server/src/services/search/search_engine.dart'; |
| 27 import 'package:analyzer/src/generated/ast.dart'; | 28 import 'package:analyzer/src/generated/ast.dart'; |
| 28 import 'package:analyzer/src/generated/engine.dart' hide AnalysisContextImpl; | 29 import 'package:analyzer/src/generated/engine.dart' hide AnalysisContextImpl; |
| 29 import 'package:analyzer/src/generated/scanner.dart'; | 30 import 'package:analyzer/src/generated/scanner.dart'; |
| 30 import 'package:analyzer/src/generated/source.dart'; | 31 import 'package:analyzer/src/generated/source.dart'; |
| 31 | 32 |
| 32 const int DART_RELEVANCE_COMMON_USAGE = 1200; | 33 export 'package:analysis_server/src/provisional/completion/completion_dart.dart' |
| 33 const int DART_RELEVANCE_DEFAULT = 1000; | 34 show |
| 34 const int DART_RELEVANCE_HIGH = 2000; | 35 DART_RELEVANCE_COMMON_USAGE, |
| 35 const int DART_RELEVANCE_INHERITED_ACCESSOR = 1057; | 36 DART_RELEVANCE_DEFAULT, |
| 36 const int DART_RELEVANCE_INHERITED_FIELD = 1058; | 37 DART_RELEVANCE_HIGH, |
| 37 const int DART_RELEVANCE_INHERITED_METHOD = 1057; | 38 DART_RELEVANCE_INHERITED_ACCESSOR, |
| 38 const int DART_RELEVANCE_KEYWORD = 1055; | 39 DART_RELEVANCE_INHERITED_FIELD, |
| 39 const int DART_RELEVANCE_LOCAL_ACCESSOR = 1057; | 40 DART_RELEVANCE_INHERITED_METHOD, |
| 40 const int DART_RELEVANCE_LOCAL_FIELD = 1058; | 41 DART_RELEVANCE_KEYWORD, |
| 41 const int DART_RELEVANCE_LOCAL_FUNCTION = 1056; | 42 DART_RELEVANCE_LOCAL_ACCESSOR, |
| 42 const int DART_RELEVANCE_LOCAL_METHOD = 1057; | 43 DART_RELEVANCE_LOCAL_FIELD, |
| 43 const int DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE = 1056; | 44 DART_RELEVANCE_LOCAL_FUNCTION, |
| 44 const int DART_RELEVANCE_LOCAL_VARIABLE = 1059; | 45 DART_RELEVANCE_LOCAL_METHOD, |
| 45 const int DART_RELEVANCE_LOW = 500; | 46 DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE, |
| 46 const int DART_RELEVANCE_NAMED_PARAMETER = 1060; | 47 DART_RELEVANCE_LOCAL_VARIABLE, |
| 47 const int DART_RELEVANCE_PARAMETER = 1059; | 48 DART_RELEVANCE_LOW, |
| 49 DART_RELEVANCE_NAMED_PARAMETER, |
| 50 DART_RELEVANCE_PARAMETER; |
| 48 | 51 |
| 49 /** | 52 /** |
| 50 * The base class for contributing code completion suggestions. | 53 * The base class for contributing code completion suggestions. |
| 51 */ | 54 */ |
| 52 abstract class DartCompletionContributor { | 55 abstract class DartCompletionContributor { |
| 53 /** | 56 /** |
| 54 * Computes the initial set of [CompletionSuggestion]s based on | 57 * Computes the initial set of [CompletionSuggestion]s based on |
| 55 * the given completion context. The compilation unit and completion node | 58 * the given completion context. The compilation unit and completion node |
| 56 * in the given completion context may not be resolved. | 59 * in the given completion context may not be resolved. |
| 57 * This method should execute quickly and not block waiting for any analysis. | 60 * This method should execute quickly and not block waiting for any analysis. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 76 /** | 79 /** |
| 77 * The [defaultContributionSorter] is a long-lived object that isn't allowed | 80 * The [defaultContributionSorter] is a long-lived object that isn't allowed |
| 78 * to maintain state between calls to [ContributionSorter#sort(...)]. | 81 * to maintain state between calls to [ContributionSorter#sort(...)]. |
| 79 */ | 82 */ |
| 80 static DartContributionSorter defaultContributionSorter = | 83 static DartContributionSorter defaultContributionSorter = |
| 81 new CommonUsageSorter(); | 84 new CommonUsageSorter(); |
| 82 | 85 |
| 83 final SearchEngine searchEngine; | 86 final SearchEngine searchEngine; |
| 84 final DartCompletionCache cache; | 87 final DartCompletionCache cache; |
| 85 List<DartCompletionContributor> contributors; | 88 List<DartCompletionContributor> contributors; |
| 89 List<CompletionContributor> newContributors; |
| 86 DartContributionSorter contributionSorter; | 90 DartContributionSorter contributionSorter; |
| 87 | 91 |
| 88 DartCompletionManager( | 92 DartCompletionManager( |
| 89 AnalysisContext context, this.searchEngine, Source source, this.cache, | 93 AnalysisContext context, this.searchEngine, Source source, this.cache, |
| 90 [this.contributors, this.contributionSorter]) | 94 [this.contributors, this.newContributors, this.contributionSorter]) |
| 91 : super(context, source) { | 95 : super(context, source) { |
| 92 if (contributors == null) { | 96 if (contributors == null) { |
| 93 contributors = [ | 97 contributors = [ |
| 94 // LocalReferenceContributor before ImportedReferenceContributor | 98 // LocalReferenceContributor before ImportedReferenceContributor |
| 95 // because local suggestions take precedence | 99 // because local suggestions take precedence |
| 96 // and can hide other suggestions with the same name | 100 // and can hide other suggestions with the same name |
| 97 new LocalReferenceContributor(), | 101 new LocalReferenceContributor(), |
| 98 new ImportedReferenceContributor(), | 102 new ImportedReferenceContributor(), |
| 99 new KeywordContributor(), | 103 //new KeywordContributor(), |
| 100 new ArgListContributor(), | 104 new ArgListContributor(), |
| 101 new CombinatorContributor(), | 105 new CombinatorContributor(), |
| 102 new PrefixedElementContributor(), | 106 new PrefixedElementContributor(), |
| 103 new UriContributor(), | 107 new UriContributor(), |
| 104 // TODO(brianwilkerson) Use the completion contributor extension point | 108 // TODO(brianwilkerson) Use the completion contributor extension point |
| 105 // to add the contributor below (and eventually, all the contributors). | 109 // to add the contributor below (and eventually, all the contributors). |
| 106 // new NewCompletionWrapper(new InheritedContributor()) | 110 // new NewCompletionWrapper(new InheritedContributor()) |
| 107 ]; | 111 ]; |
| 108 } | 112 } |
| 113 if (newContributors == null) { |
| 114 newContributors = <CompletionContributor>[ |
| 115 // TODO(danrubel) initialize using plugin API |
| 116 new newImpl.DartCompletionManager(), |
| 117 ]; |
| 118 } |
| 109 if (contributionSorter == null) { | 119 if (contributionSorter == null) { |
| 110 contributionSorter = defaultContributionSorter; | 120 contributionSorter = defaultContributionSorter; |
| 111 } | 121 } |
| 112 } | 122 } |
| 113 | 123 |
| 114 /** | 124 /** |
| 115 * Create a new initialized Dart source completion manager | 125 * Create a new initialized Dart source completion manager |
| 116 */ | 126 */ |
| 117 factory DartCompletionManager.create( | 127 factory DartCompletionManager.create( |
| 118 AnalysisContext context, SearchEngine searchEngine, Source source) { | 128 AnalysisContext context, SearchEngine searchEngine, Source source) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 } | 181 } |
| 172 } | 182 } |
| 173 } | 183 } |
| 174 | 184 |
| 175 List<DartCompletionContributor> todo = new List.from(contributors); | 185 List<DartCompletionContributor> todo = new List.from(contributors); |
| 176 todo.removeWhere((DartCompletionContributor c) { | 186 todo.removeWhere((DartCompletionContributor c) { |
| 177 return performance.logElapseTime('computeFast ${c.runtimeType}', () { | 187 return performance.logElapseTime('computeFast ${c.runtimeType}', () { |
| 178 return c.computeFast(request); | 188 return c.computeFast(request); |
| 179 }); | 189 }); |
| 180 }); | 190 }); |
| 181 // TODO(danrubel) current sorter requires no additional analysis, | |
| 182 // but need to handle the returned future the same way that futures | |
| 183 // returned from contributors are handled once this method is refactored | |
| 184 // to be async. | |
| 185 /* await */ contributionSorter.sort(request, request.suggestions); | |
| 186 // TODO (danrubel) if request is obsolete | |
| 187 // (processAnalysisRequest returns false) | |
| 188 // then send empty results | |
| 189 if (todo.isEmpty) { | |
| 190 sendResults(request, todo.isEmpty); | |
| 191 } | |
| 192 return todo; | 191 return todo; |
| 193 }); | 192 }); |
| 194 } | 193 } |
| 195 | 194 |
| 196 /** | 195 /** |
| 197 * If there is remaining work to be done, then wait for the unit to be | 196 * If there is remaining work to be done, then wait for the unit to be |
| 198 * resolved and request that each remaining contributor finish their work. | 197 * resolved and request that each remaining contributor finish their work. |
| 199 * Return a [Future] that completes when the last notification has been sent. | 198 * Return a [Future] that completes when the last notification has been sent. |
| 200 */ | 199 */ |
| 201 Future computeFull(DartCompletionRequest request, | 200 Future computeFull( |
| 202 CompletionPerformance performance, List<DartCompletionContributor> todo) { | 201 DartCompletionRequest request, |
| 202 CompletionPerformance performance, |
| 203 List<DartCompletionContributor> todo) async { |
| 204 |
| 205 // Compute suggestions using the new API |
| 206 performance.logStartTime('computeSuggestions'); |
| 207 for (CompletionContributor contributor in newContributors) { |
| 208 String contributorTag = 'computeSuggestions - ${contributor.runtimeType}'; |
| 209 performance.logStartTime(contributorTag); |
| 210 List<CompletionSuggestion> newSuggestions = |
| 211 await contributor.computeSuggestions(request); |
| 212 for (CompletionSuggestion suggestion in newSuggestions) { |
| 213 request.addSuggestion(suggestion); |
| 214 } |
| 215 performance.logElapseTime(contributorTag); |
| 216 } |
| 217 performance.logElapseTime('computeSuggestions'); |
| 203 performance.logStartTime('waitForAnalysis'); | 218 performance.logStartTime('waitForAnalysis'); |
| 219 |
| 220 if (todo.isEmpty) { |
| 221 // TODO(danrubel) current sorter requires no additional analysis, |
| 222 // but need to handle the returned future the same way that futures |
| 223 // returned from contributors are handled once this method is refactored |
| 224 // to be async. |
| 225 /* await */ contributionSorter.sort( |
| 226 request, request.suggestions); |
| 227 // TODO (danrubel) if request is obsolete |
| 228 // (processAnalysisRequest returns false) |
| 229 // then send empty results |
| 230 sendResults(request, true); |
| 231 } |
| 232 |
| 233 // Compute the other suggestions |
| 204 return waitForAnalysis().then((CompilationUnit unit) { | 234 return waitForAnalysis().then((CompilationUnit unit) { |
| 205 if (controller.isClosed) { | 235 if (controller.isClosed) { |
| 206 return; | 236 return; |
| 207 } | 237 } |
| 208 performance.logElapseTime('waitForAnalysis'); | 238 performance.logElapseTime('waitForAnalysis'); |
| 209 if (unit == null) { | 239 if (unit == null) { |
| 210 sendResults(request, true); | 240 sendResults(request, true); |
| 211 return; | 241 return; |
| 212 } | 242 } |
| 213 performance.logElapseTime('computeFull', () { | 243 performance.logElapseTime('computeFull', () { |
| 214 request.unit = unit; | 244 request.unit = unit; |
| 215 // TODO(paulberry): Do we need to invoke _ReplacementOffsetBuilder | 245 // TODO(paulberry): Do we need to invoke _ReplacementOffsetBuilder |
| 216 // again? | 246 // again? |
| 217 request.target = new CompletionTarget.forOffset(unit, request.offset); | 247 request.target = new CompletionTarget.forOffset(unit, request.offset); |
| 218 int count = todo.length; | 248 int count = todo.length; |
| 219 todo.forEach((DartCompletionContributor c) { | 249 todo.forEach((DartCompletionContributor c) { |
| 220 String name = c.runtimeType.toString(); | 250 String name = c.runtimeType.toString(); |
| 221 String completeTag = 'computeFull $name complete'; | 251 String completeTag = 'computeFull $name complete'; |
| 222 performance.logStartTime(completeTag); | 252 performance.logStartTime(completeTag); |
| 223 performance.logElapseTime('computeFull $name', () { | 253 performance.logElapseTime('computeFull $name', () { |
| 224 c.computeFull(request).then((bool changed) { | 254 c.computeFull(request).then((bool changed) { |
| 225 performance.logElapseTime(completeTag); | 255 performance.logElapseTime(completeTag); |
| 226 bool last = --count == 0; | 256 bool last = --count == 0; |
| 227 if (changed || last) { | 257 if (changed || last) { |
| 228 // TODO(danrubel) current sorter requires no additional analysis
, | 258 // TODO(danrubel) current sorter requires no additional analysis
, |
| 229 // but need to handle the returned future the same way that futu
res | 259 // but need to handle the returned future the same way that futu
res |
| 230 // returned from contributors are handled once this method is re
factored | 260 // returned from contributors are handled once this method is re
factored |
| 231 // to be async. | 261 // to be async. |
| 232 /* await */ contributionSorter.sort(request, request.suggestions
); | 262 /* await */ contributionSorter.sort( |
| 263 request, request.suggestions); |
| 233 // TODO (danrubel) if request is obsolete | 264 // TODO (danrubel) if request is obsolete |
| 234 // (processAnalysisRequest returns false) | 265 // (processAnalysisRequest returns false) |
| 235 // then send empty results | 266 // then send empty results |
| 236 sendResults(request, last); | 267 sendResults(request, last); |
| 237 } | 268 } |
| 238 }); | 269 }); |
| 239 }); | 270 }); |
| 240 }); | 271 }); |
| 241 }); | 272 }); |
| 242 }); | 273 }); |
| 243 } | 274 } |
| 244 | 275 |
| 245 @override | 276 @override |
| 246 void computeSuggestions(CompletionRequest completionRequest) { | 277 void computeSuggestions(CompletionRequest completionRequest) { |
| 247 DartCompletionRequest request = | 278 DartCompletionRequest request = |
| 248 new DartCompletionRequest.from(completionRequest, cache); | 279 new DartCompletionRequest.from(completionRequest, cache); |
| 249 CompletionPerformance performance = new CompletionPerformance(); | 280 CompletionPerformance performance = new CompletionPerformance(); |
| 250 performance.logElapseTime('compute', () { | 281 performance.logElapseTime('compute', () { |
| 251 List<DartCompletionContributor> todo = computeFast(request, performance); | 282 List<DartCompletionContributor> todo = computeFast(request, performance); |
| 252 if (!todo.isEmpty) { | 283 computeFull(request, performance, todo); |
| 253 computeFull(request, performance, todo); | |
| 254 } | |
| 255 }); | 284 }); |
| 256 } | 285 } |
| 257 | 286 |
| 258 /** | 287 /** |
| 259 * Send the current list of suggestions to the client. | 288 * Send the current list of suggestions to the client. |
| 260 */ | 289 */ |
| 261 void sendResults(DartCompletionRequest request, bool last) { | 290 void sendResults(DartCompletionRequest request, bool last) { |
| 262 if (controller == null || controller.isClosed) { | 291 if (controller == null || controller.isClosed) { |
| 263 return; | 292 return; |
| 264 } | 293 } |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 parameterNames: suggestion.parameterNames, | 448 parameterNames: suggestion.parameterNames, |
| 420 parameterTypes: suggestion.parameterTypes, | 449 parameterTypes: suggestion.parameterTypes, |
| 421 requiredParameterCount: suggestion.requiredParameterCount, | 450 requiredParameterCount: suggestion.requiredParameterCount, |
| 422 hasNamedParameters: suggestion.hasNamedParameters, | 451 hasNamedParameters: suggestion.hasNamedParameters, |
| 423 returnType: suggestion.returnType, | 452 returnType: suggestion.returnType, |
| 424 element: suggestion.element); | 453 element: suggestion.element); |
| 425 } | 454 } |
| 426 } | 455 } |
| 427 } | 456 } |
| 428 } | 457 } |
| OLD | NEW |