| 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/provisional/completion/completion_core.dart' | 10 import 'package:analysis_server/src/provisional/completion/completion_core.dart' |
| 11 show AnalysisRequest, CompletionContributor, CompletionRequest; | 11 show AnalysisRequest, CompletionContributor, CompletionRequest; |
| 12 import 'package:analysis_server/src/provisional/completion/dart/completion_targe
t.dart'; | 12 import 'package:analysis_server/src/provisional/completion/dart/completion_targe
t.dart'; |
| 13 import 'package:analysis_server/src/services/completion/completion_core.dart'; | 13 import 'package:analysis_server/src/services/completion/completion_core.dart'; |
| 14 import 'package:analysis_server/src/services/completion/completion_manager.dart'
; | 14 import 'package:analysis_server/src/services/completion/completion_manager.dart'
; |
| 15 import 'package:analysis_server/src/services/completion/dart/common_usage_sorter
.dart'; | 15 import 'package:analysis_server/src/services/completion/dart/common_usage_sorter
.dart'; |
| 16 import 'package:analysis_server/src/services/completion/dart/contribution_sorter
.dart'; | 16 import 'package:analysis_server/src/services/completion/dart/contribution_sorter
.dart'; |
| 17 import 'package:analysis_server/src/services/completion/optype.dart'; | 17 import 'package:analysis_server/src/services/completion/optype.dart'; |
| 18 import 'package:analysis_server/src/services/search/search_engine.dart'; | 18 import 'package:analysis_server/src/services/search/search_engine.dart'; |
| 19 import 'package:analyzer/file_system/file_system.dart'; | 19 import 'package:analyzer/file_system/file_system.dart'; |
| 20 import 'package:analyzer/src/generated/ast.dart'; | 20 import 'package:analyzer/src/generated/ast.dart'; |
| 21 import 'package:analyzer/src/generated/engine.dart'; | 21 import 'package:analyzer/src/generated/engine.dart'; |
| 22 import 'package:analyzer/src/generated/scanner.dart'; | 22 import 'package:analyzer/src/generated/scanner.dart'; |
| 23 import 'package:analyzer/src/generated/source.dart'; | 23 import 'package:analyzer/src/generated/source.dart'; |
| 24 | 24 |
| 25 export 'package:analysis_server/src/provisional/completion/dart/completion_dart.
dart' | |
| 26 show | |
| 27 DART_RELEVANCE_COMMON_USAGE, | |
| 28 DART_RELEVANCE_DEFAULT, | |
| 29 DART_RELEVANCE_HIGH, | |
| 30 DART_RELEVANCE_INHERITED_ACCESSOR, | |
| 31 DART_RELEVANCE_INHERITED_FIELD, | |
| 32 DART_RELEVANCE_INHERITED_METHOD, | |
| 33 DART_RELEVANCE_KEYWORD, | |
| 34 DART_RELEVANCE_LOCAL_ACCESSOR, | |
| 35 DART_RELEVANCE_LOCAL_FIELD, | |
| 36 DART_RELEVANCE_LOCAL_FUNCTION, | |
| 37 DART_RELEVANCE_LOCAL_METHOD, | |
| 38 DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE, | |
| 39 DART_RELEVANCE_LOCAL_VARIABLE, | |
| 40 DART_RELEVANCE_LOW, | |
| 41 DART_RELEVANCE_NAMED_PARAMETER, | |
| 42 DART_RELEVANCE_PARAMETER; | |
| 43 | |
| 44 /** | 25 /** |
| 45 * The base class for contributing code completion suggestions. | 26 * The base class for contributing code completion suggestions. |
| 46 */ | 27 */ |
| 47 abstract class DartCompletionContributor { | 28 abstract class DartCompletionContributor { |
| 48 /** | 29 /** |
| 49 * Computes the initial set of [CompletionSuggestion]s based on | 30 * Computes the initial set of [CompletionSuggestion]s based on |
| 50 * the given completion context. The compilation unit and completion node | 31 * the given completion context. The compilation unit and completion node |
| 51 * in the given completion context may not be resolved. | 32 * in the given completion context may not be resolved. |
| 52 * This method should execute quickly and not block waiting for any analysis. | 33 * This method should execute quickly and not block waiting for any analysis. |
| 53 * Returns `true` if the contributor's work is complete | 34 * Returns `true` if the contributor's work is complete |
| (...skipping 15 matching lines...) Expand all Loading... |
| 69 */ | 50 */ |
| 70 class DartCompletionManager extends CompletionManager { | 51 class DartCompletionManager extends CompletionManager { |
| 71 /** | 52 /** |
| 72 * The [defaultContributionSorter] is a long-lived object that isn't allowed | 53 * The [defaultContributionSorter] is a long-lived object that isn't allowed |
| 73 * to maintain state between calls to [ContributionSorter#sort(...)]. | 54 * to maintain state between calls to [ContributionSorter#sort(...)]. |
| 74 */ | 55 */ |
| 75 static DartContributionSorter defaultContributionSorter = | 56 static DartContributionSorter defaultContributionSorter = |
| 76 new CommonUsageSorter(); | 57 new CommonUsageSorter(); |
| 77 | 58 |
| 78 final SearchEngine searchEngine; | 59 final SearchEngine searchEngine; |
| 79 List<DartCompletionContributor> contributors; | |
| 80 Iterable<CompletionContributor> newContributors; | 60 Iterable<CompletionContributor> newContributors; |
| 81 DartContributionSorter contributionSorter; | 61 DartContributionSorter contributionSorter; |
| 82 | 62 |
| 83 DartCompletionManager( | 63 DartCompletionManager( |
| 84 AnalysisContext context, this.searchEngine, Source source, | 64 AnalysisContext context, this.searchEngine, Source source, |
| 85 [this.contributors, this.newContributors, this.contributionSorter]) | 65 [this.newContributors, this.contributionSorter]) |
| 86 : super(context, source) { | 66 : super(context, source) { |
| 87 if (contributors == null) { | |
| 88 contributors = [ | |
| 89 // LocalReferenceContributor before ImportedReferenceContributor | |
| 90 // because local suggestions take precedence | |
| 91 // and can hide other suggestions with the same name | |
| 92 //new LocalReferenceContributor(), | |
| 93 //new ImportedReferenceContributor(), | |
| 94 //new KeywordContributor(), | |
| 95 //new ArgListContributor(), | |
| 96 // new CombinatorContributor(), | |
| 97 // new PrefixedElementContributor(), | |
| 98 //new UriContributor(), | |
| 99 // TODO(brianwilkerson) Use the completion contributor extension point | |
| 100 // to add the contributor below (and eventually, all the contributors). | |
| 101 // new NewCompletionWrapper(new InheritedContributor()) | |
| 102 ]; | |
| 103 } | |
| 104 if (newContributors == null) { | 67 if (newContributors == null) { |
| 105 newContributors = <CompletionContributor>[]; | 68 newContributors = <CompletionContributor>[]; |
| 106 } | 69 } |
| 107 if (contributionSorter == null) { | 70 if (contributionSorter == null) { |
| 108 contributionSorter = defaultContributionSorter; | 71 contributionSorter = defaultContributionSorter; |
| 109 } | 72 } |
| 110 } | 73 } |
| 111 | 74 |
| 112 /** | 75 /** |
| 113 * Create a new initialized Dart source completion manager | 76 * Create a new initialized Dart source completion manager |
| 114 */ | 77 */ |
| 115 factory DartCompletionManager.create( | 78 factory DartCompletionManager.create( |
| 116 AnalysisContext context, | 79 AnalysisContext context, |
| 117 SearchEngine searchEngine, | 80 SearchEngine searchEngine, |
| 118 Source source, | 81 Source source, |
| 119 Iterable<CompletionContributor> newContributors) { | 82 Iterable<CompletionContributor> newContributors) { |
| 120 return new DartCompletionManager( | 83 return new DartCompletionManager( |
| 121 context, searchEngine, source, null, newContributors); | 84 context, searchEngine, source, newContributors); |
| 122 } | 85 } |
| 123 | 86 |
| 124 /** | 87 /** |
| 125 * Compute suggestions based upon cached information only | 88 * Compute suggestions based upon cached information only |
| 126 * then send an initial response to the client. | 89 * then send an initial response to the client. |
| 127 * Return a list of contributors for which [computeFull] should be called | 90 * Return a list of contributors for which [computeFull] should be called |
| 128 */ | 91 */ |
| 129 List<DartCompletionContributor> computeFast( | 92 List<DartCompletionContributor> computeFast( |
| 130 DartCompletionRequest request, CompletionPerformance performance) { | 93 DartCompletionRequest request, CompletionPerformance performance) { |
| 131 return performance.logElapseTime('computeFast', () { | 94 return performance.logElapseTime('computeFast', () { |
| 132 CompilationUnit unit = context.parseCompilationUnit(source); | 95 CompilationUnit unit = context.parseCompilationUnit(source); |
| 133 request.unit = unit; | 96 request.unit = unit; |
| 134 request.target = new CompletionTarget.forOffset(unit, request.offset); | 97 request.target = new CompletionTarget.forOffset(unit, request.offset); |
| 135 | 98 |
| 136 ReplacementRange range = | 99 ReplacementRange range = |
| 137 new ReplacementRange.compute(request.offset, request.target); | 100 new ReplacementRange.compute(request.offset, request.target); |
| 138 request.replacementOffset = range.offset; | 101 request.replacementOffset = range.offset; |
| 139 request.replacementLength = range.length; | 102 request.replacementLength = range.length; |
| 140 | 103 |
| 141 List<DartCompletionContributor> todo = new List.from(contributors); | 104 List<DartCompletionContributor> todo = []; |
| 142 todo.removeWhere((DartCompletionContributor c) { | 105 todo.removeWhere((DartCompletionContributor c) { |
| 143 return performance.logElapseTime('computeFast ${c.runtimeType}', () { | 106 return performance.logElapseTime('computeFast ${c.runtimeType}', () { |
| 144 return c.computeFast(request); | 107 return c.computeFast(request); |
| 145 }); | 108 }); |
| 146 }); | 109 }); |
| 147 return todo; | 110 return todo; |
| 148 }); | 111 }); |
| 149 } | 112 } |
| 150 | 113 |
| 151 /** | 114 /** |
| (...skipping 13 matching lines...) Expand all Loading... |
| 165 List<CompletionSuggestion> newSuggestions = | 128 List<CompletionSuggestion> newSuggestions = |
| 166 await contributor.computeSuggestions(request); | 129 await contributor.computeSuggestions(request); |
| 167 for (CompletionSuggestion suggestion in newSuggestions) { | 130 for (CompletionSuggestion suggestion in newSuggestions) { |
| 168 request.addSuggestion(suggestion); | 131 request.addSuggestion(suggestion); |
| 169 } | 132 } |
| 170 performance.logElapseTime(contributorTag); | 133 performance.logElapseTime(contributorTag); |
| 171 } | 134 } |
| 172 performance.logElapseTime('computeSuggestions'); | 135 performance.logElapseTime('computeSuggestions'); |
| 173 performance.logStartTime('waitForAnalysis'); | 136 performance.logStartTime('waitForAnalysis'); |
| 174 | 137 |
| 175 if (todo.isEmpty) { | 138 // TODO(danrubel) current sorter requires no additional analysis, |
| 176 // TODO(danrubel) current sorter requires no additional analysis, | 139 // but need to handle the returned future the same way that futures |
| 177 // but need to handle the returned future the same way that futures | 140 // returned from contributors are handled once this method is refactored |
| 178 // returned from contributors are handled once this method is refactored | 141 // to be async. |
| 179 // to be async. | 142 /* await */ contributionSorter.sort(request, request.suggestions); |
| 180 /* await */ contributionSorter.sort(request, request.suggestions); | 143 // TODO (danrubel) if request is obsolete |
| 181 // TODO (danrubel) if request is obsolete | 144 // (processAnalysisRequest returns false) |
| 182 // (processAnalysisRequest returns false) | 145 // then send empty results |
| 183 // then send empty results | 146 sendResults(request, true); |
| 184 sendResults(request, true); | 147 return new Future.value(); |
| 185 } | |
| 186 | |
| 187 // Compute the other suggestions | |
| 188 return waitForAnalysis().then((CompilationUnit unit) { | |
| 189 if (controller.isClosed) { | |
| 190 return; | |
| 191 } | |
| 192 performance.logElapseTime('waitForAnalysis'); | |
| 193 if (unit == null) { | |
| 194 sendResults(request, true); | |
| 195 return; | |
| 196 } | |
| 197 performance.logElapseTime('computeFull', () { | |
| 198 request.unit = unit; | |
| 199 // TODO(paulberry): Do we need to invoke _ReplacementOffsetBuilder | |
| 200 // again? | |
| 201 request.target = new CompletionTarget.forOffset(unit, request.offset); | |
| 202 int count = todo.length; | |
| 203 todo.forEach((DartCompletionContributor c) { | |
| 204 String name = c.runtimeType.toString(); | |
| 205 String completeTag = 'computeFull $name complete'; | |
| 206 performance.logStartTime(completeTag); | |
| 207 performance.logElapseTime('computeFull $name', () { | |
| 208 c.computeFull(request).then((bool changed) { | |
| 209 performance.logElapseTime(completeTag); | |
| 210 bool last = --count == 0; | |
| 211 if (changed || last) { | |
| 212 // TODO(danrubel) current sorter requires no additional analysis
, | |
| 213 // but need to handle the returned future the same way that futu
res | |
| 214 // returned from contributors are handled once this method is re
factored | |
| 215 // to be async. | |
| 216 /* await */ contributionSorter.sort( | |
| 217 request, request.suggestions); | |
| 218 // TODO (danrubel) if request is obsolete | |
| 219 // (processAnalysisRequest returns false) | |
| 220 // then send empty results | |
| 221 sendResults(request, last); | |
| 222 } | |
| 223 }); | |
| 224 }); | |
| 225 }); | |
| 226 }); | |
| 227 }); | |
| 228 } | 148 } |
| 229 | 149 |
| 230 @override | 150 @override |
| 231 void computeSuggestions(CompletionRequest completionRequest) { | 151 void computeSuggestions(CompletionRequest completionRequest) { |
| 232 DartCompletionRequest request = | 152 DartCompletionRequest request = |
| 233 new DartCompletionRequest.from(completionRequest); | 153 new DartCompletionRequest.from(completionRequest); |
| 234 CompletionPerformance performance = new CompletionPerformance(); | 154 CompletionPerformance performance = new CompletionPerformance(); |
| 235 performance.logElapseTime('compute', () { | 155 performance.logElapseTime('compute', () { |
| 236 List<DartCompletionContributor> todo = computeFast(request, performance); | 156 List<DartCompletionContributor> todo = computeFast(request, performance); |
| 237 computeFull(request, performance, todo); | 157 computeFull(request, performance, todo); |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 // Replacement range for import URI | 372 // Replacement range for import URI |
| 453 return new ReplacementRange(start, end - start); | 373 return new ReplacementRange(start, end - start); |
| 454 } | 374 } |
| 455 } | 375 } |
| 456 } | 376 } |
| 457 } | 377 } |
| 458 } | 378 } |
| 459 return new ReplacementRange(requestOffset, 0); | 379 return new ReplacementRange(requestOffset, 0); |
| 460 } | 380 } |
| 461 } | 381 } |
| OLD | NEW |