| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library services.completion.computer; | |
| 6 | |
| 7 import 'dart:async'; | |
| 8 | |
| 9 import 'package:analysis_services/completion/completion_suggestion.dart'; | |
| 10 import 'package:analysis_services/search/search_engine.dart'; | |
| 11 import 'package:analysis_services/src/completion/dart_completion_manager.dart'; | |
| 12 import 'package:analyzer/src/generated/ast.dart'; | |
| 13 import 'package:analyzer/src/generated/engine.dart'; | |
| 14 import 'package:analyzer/src/generated/source.dart'; | |
| 15 | |
| 16 /** | |
| 17 * The base class for computing code completion suggestions. | |
| 18 */ | |
| 19 abstract class CompletionComputer { | |
| 20 AnalysisContext context; | |
| 21 Source source; | |
| 22 int offset; | |
| 23 SearchEngine searchEngine; | |
| 24 | |
| 25 /** | |
| 26 * Computes the initial set of [CompletionSuggestion]s based on | |
| 27 * the compilation [unit], the AST [node] in which the completion occurred, | |
| 28 * and information already cached in the analysis context. | |
| 29 * The supplied [unit] and [node] may not be resolved. | |
| 30 * This method should execute quickly and not block waiting for any analysis. | |
| 31 * Returns `true` if the computer's work is complete | |
| 32 * or `false` if [computeFull] should be called to complete the work. | |
| 33 */ | |
| 34 bool computeFast(CompilationUnit unit, AstNode node, | |
| 35 List<CompletionSuggestion> suggestions); | |
| 36 | |
| 37 /** | |
| 38 * Computes the complete set of [CompletionSuggestion]s based on | |
| 39 * the resolved compilation [unit] and the resolved AST [node] in which the | |
| 40 * completion occurred. | |
| 41 * Returns `true` if the receiver modified the list of suggestions. | |
| 42 */ | |
| 43 Future<bool> computeFull(CompilationUnit unit, AstNode node, | |
| 44 List<CompletionSuggestion> suggestions); | |
| 45 } | |
| 46 | |
| 47 /** | |
| 48 * Manages `CompletionComputer`s for a given completion request. | |
| 49 */ | |
| 50 abstract class CompletionManager { | |
| 51 | |
| 52 StreamController<CompletionResult> controller; | |
| 53 | |
| 54 /** | |
| 55 * Compute completion results and append them to the stream. | |
| 56 * Subclasses should override this method, append at least one result | |
| 57 * to the [controller], and close the controller stream once complete. | |
| 58 * Clients should not call this method directly as it is automatically called | |
| 59 * when a client listens to the stream returned by [results]. | |
| 60 */ | |
| 61 void compute(); | |
| 62 | |
| 63 /** | |
| 64 * Generate a stream of code completion results. | |
| 65 */ | |
| 66 Stream<CompletionResult> results() { | |
| 67 controller = new StreamController<CompletionResult>(onListen: () { | |
| 68 scheduleMicrotask(compute); | |
| 69 }); | |
| 70 return controller.stream; | |
| 71 } | |
| 72 | |
| 73 /** | |
| 74 * Create a manager for the given request. | |
| 75 */ | |
| 76 static CompletionManager create(AnalysisContext context, Source source, | |
| 77 int offset, SearchEngine searchEngine) { | |
| 78 if (context != null) { | |
| 79 if (AnalysisEngine.isDartFileName(source.shortName)) { | |
| 80 return new DartCompletionManager(context, source, offset, searchEngine); | |
| 81 } | |
| 82 } | |
| 83 return new NoOpCompletionManager(source, offset); | |
| 84 } | |
| 85 } | |
| 86 | |
| 87 /** | |
| 88 * Code completion result generated by an [CompletionManager]. | |
| 89 */ | |
| 90 class CompletionResult { | |
| 91 | |
| 92 /** | |
| 93 * The length of the text to be replaced if the remainder of the identifier | |
| 94 * containing the cursor is to be replaced when the suggestion is applied | |
| 95 * (that is, the number of characters in the existing identifier). | |
| 96 */ | |
| 97 final int replacementLength; | |
| 98 | |
| 99 /** | |
| 100 * The offset of the start of the text to be replaced. This will be different | |
| 101 * than the offset used to request the completion suggestions if there was a | |
| 102 * portion of an identifier before the original offset. In particular, the | |
| 103 * replacementOffset will be the offset of the beginning of said identifier. | |
| 104 */ | |
| 105 final int replacementOffset; | |
| 106 | |
| 107 /** | |
| 108 * The suggested completions. | |
| 109 */ | |
| 110 final List<CompletionSuggestion> suggestions; | |
| 111 | |
| 112 /** | |
| 113 * `true` if this is that last set of results that will be returned | |
| 114 * for the indicated completion. | |
| 115 */ | |
| 116 final bool last; | |
| 117 | |
| 118 CompletionResult(this.replacementOffset, this.replacementLength, | |
| 119 this.suggestions, this.last); | |
| 120 } | |
| 121 | |
| 122 | |
| 123 class NoOpCompletionManager extends CompletionManager { | |
| 124 final Source source; | |
| 125 final int offset; | |
| 126 | |
| 127 NoOpCompletionManager(this.source, this.offset); | |
| 128 | |
| 129 @override | |
| 130 void compute() { | |
| 131 controller.add(new CompletionResult(offset, 0, [], true)); | |
| 132 } | |
| 133 } | |
| OLD | NEW |