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 test.services.completion.dart; | |
6 | |
7 import 'dart:async'; | |
8 | |
9 import 'package:analysis_services/completion/completion_manager.dart'; | |
10 import 'package:analysis_services/completion/completion_suggestion.dart'; | |
11 import 'package:analysis_services/search/search_engine.dart'; | |
12 import 'package:analysis_services/src/completion/imported_type_computer.dart'; | |
13 import 'package:analysis_services/src/completion/invocation_computer.dart'; | |
14 import 'package:analysis_services/src/completion/keyword_computer.dart'; | |
15 import 'package:analysis_services/src/completion/local_computer.dart'; | |
16 import 'package:analyzer/src/generated/ast.dart'; | |
17 import 'package:analyzer/src/generated/element.dart'; | |
18 import 'package:analyzer/src/generated/engine.dart'; | |
19 import 'package:analyzer/src/generated/source.dart'; | |
20 | |
21 /** | |
22 * The base class for computing code completion suggestions. | |
23 */ | |
24 abstract class DartCompletionComputer { | |
25 /** | |
26 * Computes the initial set of [CompletionSuggestion]s based on | |
27 * the given completion context. The compilation unit and completion node | |
28 * in the given completion context may not be resolved. | |
29 * This method should execute quickly and not block waiting for any analysis. | |
30 * Returns `true` if the computer's work is complete | |
31 * or `false` if [computeFull] should be called to complete the work. | |
32 */ | |
33 bool computeFast(DartCompletionRequest request); | |
34 | |
35 /** | |
36 * Computes the complete set of [CompletionSuggestion]s based on | |
37 * the given completion context. The compilation unit and completion node | |
38 * in the given completion context are resolved. | |
39 * Returns `true` if the receiver modified the list of suggestions. | |
40 */ | |
41 Future<bool> computeFull(DartCompletionRequest request); | |
42 } | |
43 | |
44 /** | |
45 * Manages code completion for a given Dart file completion request. | |
46 */ | |
47 class DartCompletionManager extends CompletionManager { | |
48 final AnalysisContext context; | |
49 final Source source; | |
50 final int offset; | |
51 DartCompletionRequest request; | |
52 List<DartCompletionComputer> computers; | |
53 | |
54 DartCompletionManager(this.context, SearchEngine searchEngine, this.source, | |
55 this.offset) { | |
56 request = new DartCompletionRequest(context, searchEngine, source, offset); | |
57 } | |
58 | |
59 @override | |
60 void compute() { | |
61 initComputers(); | |
62 computeFast(); | |
63 if (!computers.isEmpty) { | |
64 computeFull(); | |
65 } | |
66 } | |
67 | |
68 /** | |
69 * Compute suggestions based upon cached information only | |
70 * then send an initial response to the client. | |
71 */ | |
72 void computeFast() { | |
73 CompilationUnit unit = context.parseCompilationUnit(source); | |
74 request.unit = unit; | |
75 request.node = new NodeLocator.con1(offset).searchWithin(unit); | |
76 computers.removeWhere((DartCompletionComputer c) => c.computeFast(request)); | |
77 sendResults(computers.isEmpty); | |
78 } | |
79 | |
80 /** | |
81 * If there is remaining work to be done, then wait for the unit to be | |
82 * resolved and request that each remaining computer finish their work. | |
83 */ | |
84 void computeFull() { | |
85 waitForAnalysis().then((CompilationUnit unit) { | |
86 if (unit == null) { | |
87 sendResults(true); | |
88 return; | |
89 } | |
90 request.unit = unit; | |
91 request.node = new NodeLocator.con1(offset).searchWithin(unit); | |
92 int count = computers.length; | |
93 computers.forEach((c) { | |
94 c.computeFull(request).then((bool changed) { | |
95 var last = --count == 0; | |
96 if (changed || last) { | |
97 sendResults(last); | |
98 } | |
99 }); | |
100 }); | |
101 }); | |
102 } | |
103 | |
104 /** | |
105 * Build and initialize the list of completion computers | |
106 */ | |
107 void initComputers() { | |
108 if (computers == null) { | |
109 computers = [ | |
110 new KeywordComputer(), | |
111 new LocalComputer(), | |
112 new ImportedTypeComputer(), | |
113 new InvocationComputer()]; | |
114 } | |
115 } | |
116 | |
117 /** | |
118 * Send the current list of suggestions to the client. | |
119 */ | |
120 void sendResults(bool last) { | |
121 controller.add( | |
122 new CompletionResult(request.offset, 0, request.suggestions, last)); | |
123 if (last) { | |
124 controller.close(); | |
125 } | |
126 } | |
127 | |
128 /** | |
129 * Return a future that completes when analysis is complete. | |
130 * Return `true` if the compilation unit is be resolved. | |
131 */ | |
132 Future<CompilationUnit> waitForAnalysis() { | |
133 LibraryElement library = context.getLibraryElement(source); | |
134 if (library != null) { | |
135 CompilationUnit unit = | |
136 context.getResolvedCompilationUnit(source, library); | |
137 if (unit != null) { | |
138 return new Future.value(unit); | |
139 } | |
140 } | |
141 //TODO (danrubel) Determine if analysis is complete but unit not resolved | |
142 return new Future(waitForAnalysis); | |
143 } | |
144 } | |
145 | |
146 /** | |
147 * The context in which the completion is requested. | |
148 */ | |
149 class DartCompletionRequest { | |
150 /** | |
151 * The analysis context in which the completion is requested. | |
152 */ | |
153 final AnalysisContext context; | |
154 | |
155 /** | |
156 * The search engine for use when building suggestions. | |
157 */ | |
158 final SearchEngine searchEngine; | |
159 | |
160 /** | |
161 * The source in which the completion is requested. | |
162 */ | |
163 final Source source; | |
164 | |
165 /** | |
166 * The offset within the source at which the completion is requested. | |
167 */ | |
168 final int offset; | |
169 | |
170 /** | |
171 * The compilation unit in which the completion was requested. This unit | |
172 * may or may not be resolved when [DartCompletionComputer.computeFast] | |
173 * is called but is resolved when [DartCompletionComputer.computeFull]. | |
174 */ | |
175 CompilationUnit unit; | |
176 | |
177 /** | |
178 * The node in which the completion occurred. This node | |
179 * may or may not be resolved when [DartCompletionComputer.computeFast] | |
180 * is called but is resolved when [DartCompletionComputer.computeFull]. | |
181 */ | |
182 AstNode node; | |
183 | |
184 /** | |
185 * The list of suggestions to be sent to the client. | |
186 */ | |
187 final List<CompletionSuggestion> suggestions = []; | |
188 | |
189 DartCompletionRequest(this.context, this.searchEngine, this.source, | |
190 this.offset); | |
191 } | |
OLD | NEW |