| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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.manager; | 5 library services.completion.dart.manager; |
| 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 CompletionContributor, CompletionRequest; | 11 show CompletionContributor, CompletionRequest; |
| 12 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.
dart'; | 12 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.
dart'; |
| 13 import 'package:analysis_server/src/provisional/completion/dart/completion_plugi
n.dart'; | 13 import 'package:analysis_server/src/provisional/completion/dart/completion_plugi
n.dart'; |
| 14 import 'package:analysis_server/src/provisional/completion/dart/completion_targe
t.dart'; | 14 import 'package:analysis_server/src/provisional/completion/dart/completion_targe
t.dart'; |
| 15 import 'package:analysis_server/src/services/completion/completion_core.dart'; | 15 import 'package:analysis_server/src/services/completion/completion_core.dart'; |
| 16 import 'package:analysis_server/src/services/completion/completion_performance.d
art'; |
| 16 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'; |
| 17 import 'package:analysis_server/src/services/completion/dart/contribution_sorter
.dart'; | 18 import 'package:analysis_server/src/services/completion/dart/contribution_sorter
.dart'; |
| 18 import 'package:analysis_server/src/services/completion/dart/optype.dart'; | 19 import 'package:analysis_server/src/services/completion/dart/optype.dart'; |
| 19 import 'package:analysis_server/src/services/search/search_engine.dart'; | 20 import 'package:analysis_server/src/services/search/search_engine.dart'; |
| 20 import 'package:analyzer/dart/element/element.dart'; | 21 import 'package:analyzer/dart/element/element.dart'; |
| 21 import 'package:analyzer/dart/element/type.dart'; | 22 import 'package:analyzer/dart/element/type.dart'; |
| 22 import 'package:analyzer/file_system/file_system.dart'; | 23 import 'package:analyzer/file_system/file_system.dart'; |
| 23 import 'package:analyzer/src/context/context.dart' | 24 import 'package:analyzer/src/context/context.dart' |
| 24 show AnalysisFutureHelper, AnalysisContextImpl; | 25 show AnalysisFutureHelper, AnalysisContextImpl; |
| 25 import 'package:analyzer/src/generated/ast.dart'; | 26 import 'package:analyzer/src/generated/ast.dart'; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 40 */ | 41 */ |
| 41 static DartContributionSorter contributionSorter = new CommonUsageSorter(); | 42 static DartContributionSorter contributionSorter = new CommonUsageSorter(); |
| 42 | 43 |
| 43 @override | 44 @override |
| 44 Future<List<CompletionSuggestion>> computeSuggestions( | 45 Future<List<CompletionSuggestion>> computeSuggestions( |
| 45 CompletionRequest request) async { | 46 CompletionRequest request) async { |
| 46 if (!AnalysisEngine.isDartFileName(request.source.shortName)) { | 47 if (!AnalysisEngine.isDartFileName(request.source.shortName)) { |
| 47 return EMPTY_LIST; | 48 return EMPTY_LIST; |
| 48 } | 49 } |
| 49 | 50 |
| 51 CompletionPerformance performance = |
| 52 (request as CompletionRequestImpl).performance; |
| 53 const BUILD_REQUEST_TAG = 'build DartCompletionRequestImpl'; |
| 54 performance.logStartTime(BUILD_REQUEST_TAG); |
| 50 DartCompletionRequestImpl dartRequest = | 55 DartCompletionRequestImpl dartRequest = |
| 51 await DartCompletionRequestImpl.from(request); | 56 await DartCompletionRequestImpl.from(request); |
| 57 performance.logElapseTime(BUILD_REQUEST_TAG); |
| 58 |
| 59 // Don't suggest in comments. |
| 60 if (dartRequest.target.isCommentText) { |
| 61 return EMPTY_LIST; |
| 62 } |
| 63 |
| 52 ReplacementRange range = | 64 ReplacementRange range = |
| 53 new ReplacementRange.compute(dartRequest.offset, dartRequest.target); | 65 new ReplacementRange.compute(dartRequest.offset, dartRequest.target); |
| 54 (request as CompletionRequestImpl) | 66 (request as CompletionRequestImpl) |
| 55 ..replacementOffset = range.offset | 67 ..replacementOffset = range.offset |
| 56 ..replacementLength = range.length; | 68 ..replacementLength = range.length; |
| 57 | 69 |
| 58 // Don't suggest in comments. | |
| 59 if (dartRequest.target.isCommentText) { | |
| 60 return EMPTY_LIST; | |
| 61 } | |
| 62 | |
| 63 // Request Dart specific completions from each contributor | 70 // Request Dart specific completions from each contributor |
| 64 Map<String, CompletionSuggestion> suggestionMap = | 71 Map<String, CompletionSuggestion> suggestionMap = |
| 65 <String, CompletionSuggestion>{}; | 72 <String, CompletionSuggestion>{}; |
| 66 for (DartCompletionContributor contributor | 73 for (DartCompletionContributor contributor |
| 67 in dartCompletionPlugin.contributors) { | 74 in dartCompletionPlugin.contributors) { |
| 75 String contributorTag = |
| 76 'DartCompletionManager - ${contributor.runtimeType}'; |
| 77 performance.logStartTime(contributorTag); |
| 68 List<CompletionSuggestion> contributorSuggestions = | 78 List<CompletionSuggestion> contributorSuggestions = |
| 69 await contributor.computeSuggestions(dartRequest); | 79 await contributor.computeSuggestions(dartRequest); |
| 80 performance.logElapseTime(contributorTag); |
| 70 | 81 |
| 71 for (CompletionSuggestion newSuggestion in contributorSuggestions) { | 82 for (CompletionSuggestion newSuggestion in contributorSuggestions) { |
| 72 var oldSuggestion = suggestionMap.putIfAbsent( | 83 var oldSuggestion = suggestionMap.putIfAbsent( |
| 73 newSuggestion.completion, () => newSuggestion); | 84 newSuggestion.completion, () => newSuggestion); |
| 74 if (newSuggestion != oldSuggestion && | 85 if (newSuggestion != oldSuggestion && |
| 75 newSuggestion.relevance > oldSuggestion.relevance) { | 86 newSuggestion.relevance > oldSuggestion.relevance) { |
| 76 suggestionMap[newSuggestion.completion] = newSuggestion; | 87 suggestionMap[newSuggestion.completion] = newSuggestion; |
| 77 } | 88 } |
| 78 } | 89 } |
| 79 } | 90 } |
| 80 | 91 |
| 81 // Adjust suggestion relevance before returning | 92 // Adjust suggestion relevance before returning |
| 82 List<CompletionSuggestion> suggestions = suggestionMap.values.toList(); | 93 List<CompletionSuggestion> suggestions = suggestionMap.values.toList(); |
| 94 const SORT_TAG = 'DartCompletionManager - sort'; |
| 95 performance.logStartTime(SORT_TAG); |
| 83 await contributionSorter.sort(dartRequest, suggestions); | 96 await contributionSorter.sort(dartRequest, suggestions); |
| 97 performance.logElapseTime(SORT_TAG); |
| 84 return suggestions; | 98 return suggestions; |
| 85 } | 99 } |
| 86 } | 100 } |
| 87 | 101 |
| 88 /** | 102 /** |
| 89 * The information about a requested list of completions within a Dart file. | 103 * The information about a requested list of completions within a Dart file. |
| 90 */ | 104 */ |
| 91 class DartCompletionRequestImpl implements DartCompletionRequest { | 105 class DartCompletionRequestImpl implements DartCompletionRequest { |
| 92 @override | 106 @override |
| 93 final AnalysisContext context; | 107 final AnalysisContext context; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 118 */ | 132 */ |
| 119 LibraryElement _coreLib; | 133 LibraryElement _coreLib; |
| 120 | 134 |
| 121 /** | 135 /** |
| 122 * The [DartType] for Object in dart:core | 136 * The [DartType] for Object in dart:core |
| 123 */ | 137 */ |
| 124 InterfaceType _objectType; | 138 InterfaceType _objectType; |
| 125 | 139 |
| 126 OpType _opType; | 140 OpType _opType; |
| 127 | 141 |
| 142 final CompletionPerformance performance; |
| 143 |
| 128 DartCompletionRequestImpl._( | 144 DartCompletionRequestImpl._( |
| 129 this.context, | 145 this.context, |
| 130 this.resourceProvider, | 146 this.resourceProvider, |
| 131 this.searchEngine, | 147 this.searchEngine, |
| 132 this.librarySource, | 148 this.librarySource, |
| 133 this.source, | 149 this.source, |
| 134 this.offset, | 150 this.offset, |
| 135 CompilationUnit unit) { | 151 CompilationUnit unit, |
| 152 this.performance) { |
| 136 _updateTargets(unit); | 153 _updateTargets(unit); |
| 137 } | 154 } |
| 138 | 155 |
| 139 @override | 156 @override |
| 140 LibraryElement get coreLib { | 157 LibraryElement get coreLib { |
| 141 if (_coreLib == null) { | 158 if (_coreLib == null) { |
| 142 Source coreUri = context.sourceFactory.forUri('dart:core'); | 159 Source coreUri = context.sourceFactory.forUri('dart:core'); |
| 143 _coreLib = context.computeLibraryElement(coreUri); | 160 _coreLib = context.computeLibraryElement(coreUri); |
| 144 } | 161 } |
| 145 return _coreLib; | 162 return _coreLib; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 } | 201 } |
| 185 | 202 |
| 186 // For internal use only | 203 // For internal use only |
| 187 @override | 204 @override |
| 188 Future<List<Directive>> resolveDirectives() async { | 205 Future<List<Directive>> resolveDirectives() async { |
| 189 CompilationUnit libUnit; | 206 CompilationUnit libUnit; |
| 190 if (librarySource == source) { | 207 if (librarySource == source) { |
| 191 libUnit = target.unit; | 208 libUnit = target.unit; |
| 192 } else if (librarySource != null) { | 209 } else if (librarySource != null) { |
| 193 // TODO(danrubel) only resolve the directives | 210 // TODO(danrubel) only resolve the directives |
| 211 const RESOLVE_DIRECTIVES_TAG = 'resolve directives'; |
| 212 performance.logStartTime(RESOLVE_DIRECTIVES_TAG); |
| 194 libUnit = await new AnalysisFutureHelper<CompilationUnit>( | 213 libUnit = await new AnalysisFutureHelper<CompilationUnit>( |
| 195 context, | 214 context, |
| 196 new LibrarySpecificUnit(librarySource, librarySource), | 215 new LibrarySpecificUnit(librarySource, librarySource), |
| 197 RESOLVED_UNIT3) | 216 RESOLVED_UNIT3) |
| 198 .computeAsync(); | 217 .computeAsync(); |
| 218 performance.logElapseTime(RESOLVE_DIRECTIVES_TAG); |
| 199 } | 219 } |
| 200 return libUnit?.directives; | 220 return libUnit?.directives; |
| 201 } | 221 } |
| 202 | 222 |
| 203 @override | 223 @override |
| 204 Future resolveExpression(Expression expression) async { | 224 Future resolveExpression(Expression expression) async { |
| 205 // Return immediately if the expression has already been resolved | 225 // Return immediately if the expression has already been resolved |
| 206 if (expression.propagatedType != null) { | 226 if (expression.propagatedType != null) { |
| 207 return; | 227 return; |
| 208 } | 228 } |
| 209 | 229 |
| 210 // Gracefully degrade if librarySource cannot be determined | 230 // Gracefully degrade if librarySource cannot be determined |
| 211 if (librarySource == null) { | 231 if (librarySource == null) { |
| 212 return; | 232 return; |
| 213 } | 233 } |
| 214 | 234 |
| 215 // Resolve declarations in the target unit | 235 // Resolve declarations in the target unit |
| 216 // TODO(danrubel) resolve the expression or containing method | 236 // TODO(danrubel) resolve the expression or containing method |
| 217 // rather than the entire complilation unit | 237 // rather than the entire complilation unit |
| 238 const RESOLVE_EXPRESSION_TAG = 'resolve expression'; |
| 239 performance.logStartTime(RESOLVE_EXPRESSION_TAG); |
| 218 CompilationUnit resolvedUnit = | 240 CompilationUnit resolvedUnit = |
| 219 await new AnalysisFutureHelper<CompilationUnit>(context, | 241 await new AnalysisFutureHelper<CompilationUnit>(context, |
| 220 new LibrarySpecificUnit(librarySource, source), RESOLVED_UNIT) | 242 new LibrarySpecificUnit(librarySource, source), RESOLVED_UNIT) |
| 221 .computeAsync(); | 243 .computeAsync(); |
| 244 performance.logElapseTime(RESOLVE_EXPRESSION_TAG); |
| 222 | 245 |
| 223 // TODO(danrubel) determine if the underlying source has been modified | 246 // TODO(danrubel) determine if the underlying source has been modified |
| 224 // in a way that invalidates the completion request | 247 // in a way that invalidates the completion request |
| 225 // and return null | 248 // and return null |
| 226 | 249 |
| 227 // Gracefully degrade if unit cannot be resolved | 250 // Gracefully degrade if unit cannot be resolved |
| 228 if (resolvedUnit == null) { | 251 if (resolvedUnit == null) { |
| 229 return; | 252 return; |
| 230 } | 253 } |
| 231 | 254 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 260 dotTarget = node.prefix; | 283 dotTarget = node.prefix; |
| 261 } | 284 } |
| 262 } | 285 } |
| 263 } | 286 } |
| 264 | 287 |
| 265 /** | 288 /** |
| 266 * Return a [Future] that completes with a newly created completion request | 289 * Return a [Future] that completes with a newly created completion request |
| 267 * based on the given [request]. | 290 * based on the given [request]. |
| 268 */ | 291 */ |
| 269 static Future<DartCompletionRequest> from(CompletionRequest request) async { | 292 static Future<DartCompletionRequest> from(CompletionRequest request) async { |
| 293 CompletionPerformance performance = |
| 294 (request as CompletionRequestImpl).performance; |
| 295 const BUILD_REQUEST_TAG = 'build DartCompletionRequest'; |
| 296 performance.logStartTime(BUILD_REQUEST_TAG); |
| 297 |
| 270 Source source = request.source; | 298 Source source = request.source; |
| 271 AnalysisContext context = request.context; | 299 AnalysisContext context = request.context; |
| 300 |
| 301 const PARSE_TAG = 'parse unit'; |
| 302 performance.logStartTime(PARSE_TAG); |
| 272 CompilationUnit unit = request.context.computeResult(source, PARSED_UNIT); | 303 CompilationUnit unit = request.context.computeResult(source, PARSED_UNIT); |
| 304 performance.logElapseTime(PARSE_TAG); |
| 273 | 305 |
| 274 Source libSource; | 306 Source libSource; |
| 275 if (unit.directives.any((d) => d is PartOfDirective)) { | 307 if (unit.directives.any((d) => d is PartOfDirective)) { |
| 276 List<Source> libraries = context.getLibrariesContaining(source); | 308 List<Source> libraries = context.getLibrariesContaining(source); |
| 277 if (libraries.isNotEmpty) { | 309 if (libraries.isNotEmpty) { |
| 278 libSource = libraries[0]; | 310 libSource = libraries[0]; |
| 279 } | 311 } |
| 280 } else { | 312 } else { |
| 281 libSource = source; | 313 libSource = source; |
| 282 } | 314 } |
| 283 | 315 |
| 284 // Most (all?) contributors need declarations in scope to be resolved | 316 // Most (all?) contributors need declarations in scope to be resolved |
| 285 if (libSource != null) { | 317 if (libSource != null) { |
| 318 const RESOLVE_DECLARATIONS_TAG = 'resolve declarations'; |
| 319 performance.logStartTime(RESOLVE_DECLARATIONS_TAG); |
| 286 unit = await new AnalysisFutureHelper<CompilationUnit>(context, | 320 unit = await new AnalysisFutureHelper<CompilationUnit>(context, |
| 287 new LibrarySpecificUnit(libSource, source), RESOLVED_UNIT3) | 321 new LibrarySpecificUnit(libSource, source), RESOLVED_UNIT3) |
| 288 .computeAsync(); | 322 .computeAsync(); |
| 323 performance.logElapseTime(RESOLVE_DECLARATIONS_TAG); |
| 289 } | 324 } |
| 290 | 325 |
| 291 DartCompletionRequestImpl dartRequest = new DartCompletionRequestImpl._( | 326 DartCompletionRequestImpl dartRequest = new DartCompletionRequestImpl._( |
| 292 request.context, | 327 request.context, |
| 293 request.resourceProvider, | 328 request.resourceProvider, |
| 294 request.searchEngine, | 329 request.searchEngine, |
| 295 libSource, | 330 libSource, |
| 296 request.source, | 331 request.source, |
| 297 request.offset, | 332 request.offset, |
| 298 unit); | 333 unit, |
| 334 performance); |
| 299 | 335 |
| 300 // Resolve the expression in which the completion occurs | 336 // Resolve the expression in which the completion occurs |
| 301 // to properly determine if identifiers should be suggested | 337 // to properly determine if identifiers should be suggested |
| 302 // rather than invocations. | 338 // rather than invocations. |
| 303 if (dartRequest.target.maybeFunctionalArgument()) { | 339 if (dartRequest.target.maybeFunctionalArgument()) { |
| 304 AstNode node = dartRequest.target.containingNode.parent; | 340 AstNode node = dartRequest.target.containingNode.parent; |
| 305 if (node is Expression) { | 341 if (node is Expression) { |
| 342 const FUNCTIONAL_ARG_TAG = 'resolve expression for isFunctionalArg'; |
| 343 performance.logStartTime(FUNCTIONAL_ARG_TAG); |
| 306 await dartRequest.resolveExpression(node); | 344 await dartRequest.resolveExpression(node); |
| 345 performance.logElapseTime(FUNCTIONAL_ARG_TAG); |
| 307 } | 346 } |
| 308 } | 347 } |
| 309 | 348 |
| 349 performance.logElapseTime(BUILD_REQUEST_TAG); |
| 310 return dartRequest; | 350 return dartRequest; |
| 311 } | 351 } |
| 312 } | 352 } |
| 313 | 353 |
| 314 /** | 354 /** |
| 315 * Utility class for computing the code completion replacement range | 355 * Utility class for computing the code completion replacement range |
| 316 */ | 356 */ |
| 317 class ReplacementRange { | 357 class ReplacementRange { |
| 318 int offset; | 358 int offset; |
| 319 int length; | 359 int length; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 // Replacement range for import URI | 400 // Replacement range for import URI |
| 361 return new ReplacementRange(start, end - start); | 401 return new ReplacementRange(start, end - start); |
| 362 } | 402 } |
| 363 } | 403 } |
| 364 } | 404 } |
| 365 } | 405 } |
| 366 } | 406 } |
| 367 return new ReplacementRange(requestOffset, 0); | 407 return new ReplacementRange(requestOffset, 0); |
| 368 } | 408 } |
| 369 } | 409 } |
| OLD | NEW |