| 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/combinator_contributor.d
art'; | 13 import 'package:analysis_server/src/services/completion/combinator_contributor.d
art'; |
| 14 import 'package:analysis_server/src/services/completion/completion_core.dart'; | 14 import 'package:analysis_server/src/services/completion/completion_core.dart'; |
| 15 import 'package:analysis_server/src/services/completion/completion_manager.dart'
; | 15 import 'package:analysis_server/src/services/completion/completion_manager.dart'
; |
| 16 import 'package:analysis_server/src/services/completion/dart/common_usage_sorter
.dart'; | 16 import 'package:analysis_server/src/services/completion/dart/common_usage_sorter
.dart'; |
| 17 import 'package:analysis_server/src/services/completion/dart/contribution_sorter
.dart'; | 17 import 'package:analysis_server/src/services/completion/dart/contribution_sorter
.dart'; |
| 18 import 'package:analysis_server/src/services/completion/dart_completion_cache.da
rt'; | 18 import 'package:analysis_server/src/services/completion/dart_completion_cache.da
rt'; |
| 19 import 'package:analysis_server/src/services/completion/imported_reference_contr
ibutor.dart'; | 19 import 'package:analysis_server/src/services/completion/imported_reference_contr
ibutor.dart'; |
| 20 import 'package:analysis_server/src/services/completion/local_reference_contribu
tor.dart'; | 20 import 'package:analysis_server/src/services/completion/local_reference_contribu
tor.dart'; |
| 21 import 'package:analysis_server/src/services/completion/optype.dart'; | 21 import 'package:analysis_server/src/services/completion/optype.dart'; |
| 22 import 'package:analysis_server/src/services/completion/prefixed_element_contrib
utor.dart'; | 22 import 'package:analysis_server/src/services/completion/prefixed_element_contrib
utor.dart'; |
| 23 import 'package:analysis_server/src/services/completion/uri_contributor.dart'; | |
| 24 import 'package:analysis_server/src/services/search/search_engine.dart'; | 23 import 'package:analysis_server/src/services/search/search_engine.dart'; |
| 25 import 'package:analyzer/file_system/file_system.dart'; | 24 import 'package:analyzer/file_system/file_system.dart'; |
| 26 import 'package:analyzer/src/generated/ast.dart'; | 25 import 'package:analyzer/src/generated/ast.dart'; |
| 27 import 'package:analyzer/src/generated/engine.dart' hide AnalysisContextImpl; | 26 import 'package:analyzer/src/generated/engine.dart' hide AnalysisContextImpl; |
| 28 import 'package:analyzer/src/generated/scanner.dart'; | 27 import 'package:analyzer/src/generated/scanner.dart'; |
| 29 import 'package:analyzer/src/generated/source.dart'; | 28 import 'package:analyzer/src/generated/source.dart'; |
| 30 | 29 |
| 31 export 'package:analysis_server/src/provisional/completion/dart/completion_dart.
dart' | 30 export 'package:analysis_server/src/provisional/completion/dart/completion_dart.
dart' |
| 32 show | 31 show |
| 33 DART_RELEVANCE_COMMON_USAGE, | 32 DART_RELEVANCE_COMMON_USAGE, |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 contributors = [ | 94 contributors = [ |
| 96 // LocalReferenceContributor before ImportedReferenceContributor | 95 // LocalReferenceContributor before ImportedReferenceContributor |
| 97 // because local suggestions take precedence | 96 // because local suggestions take precedence |
| 98 // and can hide other suggestions with the same name | 97 // and can hide other suggestions with the same name |
| 99 new LocalReferenceContributor(), | 98 new LocalReferenceContributor(), |
| 100 new ImportedReferenceContributor(), | 99 new ImportedReferenceContributor(), |
| 101 //new KeywordContributor(), | 100 //new KeywordContributor(), |
| 102 //new ArgListContributor(), | 101 //new ArgListContributor(), |
| 103 new CombinatorContributor(), | 102 new CombinatorContributor(), |
| 104 new PrefixedElementContributor(), | 103 new PrefixedElementContributor(), |
| 105 new UriContributor(), | 104 //new UriContributor(), |
| 106 // TODO(brianwilkerson) Use the completion contributor extension point | 105 // TODO(brianwilkerson) Use the completion contributor extension point |
| 107 // to add the contributor below (and eventually, all the contributors). | 106 // to add the contributor below (and eventually, all the contributors). |
| 108 // new NewCompletionWrapper(new InheritedContributor()) | 107 // new NewCompletionWrapper(new InheritedContributor()) |
| 109 ]; | 108 ]; |
| 110 } | 109 } |
| 111 if (newContributors == null) { | 110 if (newContributors == null) { |
| 112 newContributors = <CompletionContributor>[]; | 111 newContributors = <CompletionContributor>[]; |
| 113 } | 112 } |
| 114 if (contributionSorter == null) { | 113 if (contributionSorter == null) { |
| 115 contributionSorter = defaultContributionSorter; | 114 contributionSorter = defaultContributionSorter; |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 class ReplacementRange { | 439 class ReplacementRange { |
| 441 int offset; | 440 int offset; |
| 442 int length; | 441 int length; |
| 443 | 442 |
| 444 ReplacementRange(this.offset, this.length); | 443 ReplacementRange(this.offset, this.length); |
| 445 | 444 |
| 446 factory ReplacementRange.compute(int requestOffset, CompletionTarget target) { | 445 factory ReplacementRange.compute(int requestOffset, CompletionTarget target) { |
| 447 bool isKeywordOrIdentifier(Token token) => | 446 bool isKeywordOrIdentifier(Token token) => |
| 448 token.type == TokenType.KEYWORD || token.type == TokenType.IDENTIFIER; | 447 token.type == TokenType.KEYWORD || token.type == TokenType.IDENTIFIER; |
| 449 | 448 |
| 449 //TODO(danrubel) Ideally this needs to be pushed down into the contributors |
| 450 // but that implies that each suggestion can have a different |
| 451 // replacement offsent/length which would mean an API change |
| 452 |
| 450 var entity = target.entity; | 453 var entity = target.entity; |
| 451 Token token = entity is AstNode ? entity.beginToken : entity; | 454 Token token = entity is AstNode ? entity.beginToken : entity; |
| 452 if (token != null && requestOffset < token.offset) { | 455 if (token != null && requestOffset < token.offset) { |
| 453 token = token.previous; | 456 token = token.previous; |
| 454 } | 457 } |
| 455 if (token != null) { | 458 if (token != null) { |
| 456 if (requestOffset == token.offset && !isKeywordOrIdentifier(token)) { | 459 if (requestOffset == token.offset && !isKeywordOrIdentifier(token)) { |
| 457 // If the insertion point is at the beginning of the current token | 460 // If the insertion point is at the beginning of the current token |
| 458 // and the current token is not an identifier | 461 // and the current token is not an identifier |
| 459 // then check the previous token to see if it should be replaced | 462 // then check the previous token to see if it should be replaced |
| 460 token = token.previous; | 463 token = token.previous; |
| 461 } | 464 } |
| 462 if (token != null && isKeywordOrIdentifier(token)) { | 465 if (token != null && isKeywordOrIdentifier(token)) { |
| 463 if (token.offset <= requestOffset && requestOffset <= token.end) { | 466 if (token.offset <= requestOffset && requestOffset <= token.end) { |
| 467 // Replacement range for typical identifier completion |
| 464 return new ReplacementRange(token.offset, token.length); | 468 return new ReplacementRange(token.offset, token.length); |
| 465 } | 469 } |
| 466 } | 470 } |
| 471 if (token is StringToken) { |
| 472 SimpleStringLiteral uri = new SimpleStringLiteral(token, token.lexeme); |
| 473 Token previous = token.previous; |
| 474 if (previous is KeywordToken) { |
| 475 Keyword keyword = previous.keyword; |
| 476 if (keyword == Keyword.IMPORT || |
| 477 keyword == Keyword.EXPORT || |
| 478 keyword == Keyword.PART) { |
| 479 int start = uri.contentsOffset; |
| 480 var end = uri.contentsEnd; |
| 481 if (start <= requestOffset && requestOffset <= end) { |
| 482 // Replacement range for import URI |
| 483 return new ReplacementRange(start, end - start); |
| 484 } |
| 485 } |
| 486 } |
| 487 } |
| 467 } | 488 } |
| 468 return new ReplacementRange(requestOffset, 0); | 489 return new ReplacementRange(requestOffset, 0); |
| 469 } | 490 } |
| 470 } | 491 } |
| OLD | NEW |