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 import 'dart:async'; | 5 import 'dart:async'; |
6 import 'dart:collection'; | 6 import 'dart:collection'; |
7 import 'dart:core'; | 7 import 'dart:core'; |
8 | 8 |
9 import 'package:analysis_server/protocol/protocol.dart'; | 9 import 'package:analysis_server/protocol/protocol.dart'; |
10 import 'package:analysis_server/protocol/protocol_generated.dart'; | 10 import 'package:analysis_server/protocol/protocol_generated.dart'; |
11 import 'package:analysis_server/src/analysis_server.dart'; | 11 import 'package:analysis_server/src/analysis_server.dart'; |
12 import 'package:analysis_server/src/constants.dart'; | 12 import 'package:analysis_server/src/constants.dart'; |
13 import 'package:analyzer/file_system/file_system.dart'; | 13 import 'package:analyzer/file_system/file_system.dart'; |
14 import 'package:analyzer/src/dart/analysis/driver.dart'; | 14 import 'package:analyzer/src/dart/analysis/driver.dart'; |
15 import 'package:analyzer/src/generated/engine.dart'; | |
16 import 'package:analyzer/src/generated/source.dart'; | 15 import 'package:analyzer/src/generated/source.dart'; |
17 | 16 |
18 /** | 17 /** |
19 * Instances of the class [ExecutionDomainHandler] implement a [RequestHandler] | 18 * Instances of the class [ExecutionDomainHandler] implement a [RequestHandler] |
20 * that handles requests in the `execution` domain. | 19 * that handles requests in the `execution` domain. |
21 */ | 20 */ |
22 class ExecutionDomainHandler implements RequestHandler { | 21 class ExecutionDomainHandler implements RequestHandler { |
23 /** | 22 /** |
24 * The analysis server that is using this handler to process requests. | 23 * The analysis server that is using this handler to process requests. |
25 */ | 24 */ |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 Response mapUri(Request request) { | 90 Response mapUri(Request request) { |
92 ExecutionMapUriParams params = | 91 ExecutionMapUriParams params = |
93 new ExecutionMapUriParams.fromRequest(request); | 92 new ExecutionMapUriParams.fromRequest(request); |
94 String contextId = params.id; | 93 String contextId = params.id; |
95 String path = contextMap[contextId]; | 94 String path = contextMap[contextId]; |
96 if (path == null) { | 95 if (path == null) { |
97 return new Response.invalidParameter(request, 'id', | 96 return new Response.invalidParameter(request, 'id', |
98 'There is no execution context with an id of $contextId'); | 97 'There is no execution context with an id of $contextId'); |
99 } | 98 } |
100 | 99 |
101 SourceFactory sourceFactory; | 100 AnalysisDriver driver = server.getAnalysisDriver(path); |
102 AnalysisDriver driver; | 101 if (driver == null) { |
103 if (server.options.enableNewAnalysisDriver) { | 102 return new Response.invalidExecutionContext(request, contextId); |
104 driver = server.getAnalysisDriver(path); | |
105 if (driver == null) { | |
106 return new Response.invalidExecutionContext(request, contextId); | |
107 } | |
108 sourceFactory = driver.sourceFactory; | |
109 } else { | |
110 AnalysisContext context = server.getContainingContext(path); | |
111 if (context == null) { | |
112 return new Response.invalidExecutionContext(request, contextId); | |
113 } | |
114 sourceFactory = context.sourceFactory; | |
115 } | 103 } |
| 104 SourceFactory sourceFactory = driver.sourceFactory; |
116 | 105 |
117 String file = params.file; | 106 String file = params.file; |
118 String uri = params.uri; | 107 String uri = params.uri; |
119 if (file != null) { | 108 if (file != null) { |
120 if (uri != null) { | 109 if (uri != null) { |
121 return new Response.invalidParameter(request, 'file', | 110 return new Response.invalidParameter(request, 'file', |
122 'Either file or uri must be provided, but not both'); | 111 'Either file or uri must be provided, but not both'); |
123 } | 112 } |
124 Resource resource = server.resourceProvider.getResource(file); | 113 Resource resource = server.resourceProvider.getResource(file); |
125 if (!resource.exists) { | 114 if (!resource.exists) { |
126 return new Response.invalidParameter(request, 'file', 'Must exist'); | 115 return new Response.invalidParameter(request, 'file', 'Must exist'); |
127 } else if (resource is! File) { | 116 } else if (resource is! File) { |
128 return new Response.invalidParameter( | 117 return new Response.invalidParameter( |
129 request, 'file', 'Must not refer to a directory'); | 118 request, 'file', 'Must not refer to a directory'); |
130 } | 119 } |
131 | 120 |
132 Source source; | 121 Source source = driver.fsState.getFileForPath(file).source; |
133 if (server.options.enableNewAnalysisDriver) { | |
134 source = driver.fsState.getFileForPath(file).source; | |
135 } else { | |
136 ContextSourcePair contextSource = server.getContextSourcePair(file); | |
137 source = contextSource.source; | |
138 } | |
139 if (source.uriKind != UriKind.FILE_URI) { | 122 if (source.uriKind != UriKind.FILE_URI) { |
140 uri = source.uri.toString(); | 123 uri = source.uri.toString(); |
141 } else { | 124 } else { |
142 uri = sourceFactory.restoreUri(source).toString(); | 125 uri = sourceFactory.restoreUri(source).toString(); |
143 } | 126 } |
144 return new ExecutionMapUriResult(uri: uri).toResponse(request.id); | 127 return new ExecutionMapUriResult(uri: uri).toResponse(request.id); |
145 } else if (uri != null) { | 128 } else if (uri != null) { |
146 Source source = sourceFactory.forUri(uri); | 129 Source source = sourceFactory.forUri(uri); |
147 if (source == null) { | 130 if (source == null) { |
148 return new Response.invalidParameter(request, 'uri', 'Invalid URI'); | 131 return new Response.invalidParameter(request, 'uri', 'Invalid URI'); |
149 } | 132 } |
150 file = source.fullName; | 133 file = source.fullName; |
151 return new ExecutionMapUriResult(file: file).toResponse(request.id); | 134 return new ExecutionMapUriResult(file: file).toResponse(request.id); |
152 } | 135 } |
153 return new Response.invalidParameter( | 136 return new Response.invalidParameter( |
154 request, 'file', 'Either file or uri must be provided'); | 137 request, 'file', 'Either file or uri must be provided'); |
155 } | 138 } |
156 | 139 |
157 /** | 140 /** |
158 * Implement the 'execution.setSubscriptions' request. | 141 * Implement the 'execution.setSubscriptions' request. |
159 */ | 142 */ |
160 Response setSubscriptions(Request request) { | 143 Response setSubscriptions(Request request) { |
161 if (server.options.enableNewAnalysisDriver) { | 144 // Under the analysis driver, setSubscriptions() becomes a no-op. |
162 // Under the analysis driver, setSubscriptions() becomes a no-op. | 145 return new ExecutionSetSubscriptionsResult().toResponse(request.id); |
163 return new ExecutionSetSubscriptionsResult().toResponse(request.id); | |
164 } else { | |
165 List<ExecutionService> subscriptions = | |
166 new ExecutionSetSubscriptionsParams.fromRequest(request) | |
167 .subscriptions; | |
168 if (subscriptions.contains(ExecutionService.LAUNCH_DATA)) { | |
169 if (onFileAnalyzed == null) { | |
170 onFileAnalyzed = server.onFileAnalyzed.listen(_fileAnalyzed); | |
171 _reportCurrentFileStatus(); | |
172 } | |
173 } else { | |
174 if (onFileAnalyzed != null) { | |
175 onFileAnalyzed.cancel(); | |
176 onFileAnalyzed = null; | |
177 } | |
178 } | |
179 return new ExecutionSetSubscriptionsResult().toResponse(request.id); | |
180 } | |
181 } | |
182 | |
183 void _fileAnalyzed(ChangeNotice notice) { | |
184 ServerPerformanceStatistics.executionNotifications.makeCurrentWhile(() { | |
185 Source source = notice.source; | |
186 String filePath = source.fullName; | |
187 // check files | |
188 bool isDartFile = notice.resolvedDartUnit != null; | |
189 if (!isDartFile) { | |
190 return; | |
191 } | |
192 // prepare context | |
193 AnalysisContext context = server.getContainingContext(filePath); | |
194 if (context == null) { | |
195 return; | |
196 } | |
197 // analyze the file | |
198 if (isDartFile) { | |
199 ExecutableKind kind = ExecutableKind.NOT_EXECUTABLE; | |
200 if (context.isClientLibrary(source)) { | |
201 kind = ExecutableKind.CLIENT; | |
202 if (context.isServerLibrary(source)) { | |
203 kind = ExecutableKind.EITHER; | |
204 } | |
205 } else if (context.isServerLibrary(source)) { | |
206 kind = ExecutableKind.SERVER; | |
207 } | |
208 server.sendNotification( | |
209 new ExecutionLaunchDataParams(filePath, kind: kind) | |
210 .toNotification()); | |
211 } | |
212 }); | |
213 } | |
214 | |
215 /** | |
216 * Return `true` if the given [filePath] represents a file that is in an | |
217 * analysis root. | |
218 */ | |
219 bool _isInAnalysisRoot(String filePath) => | |
220 server.contextManager.isInAnalysisRoot(filePath); | |
221 | |
222 void _reportCurrentFileStatus() { | |
223 for (AnalysisContext context in server.analysisContexts) { | |
224 List<Source> librarySources = context.librarySources; | |
225 List<Source> clientSources = context.launchableClientLibrarySources; | |
226 List<Source> serverSources = context.launchableServerLibrarySources; | |
227 for (Source source in clientSources) { | |
228 if (serverSources.remove(source)) { | |
229 _sendKindNotification(source.fullName, ExecutableKind.EITHER); | |
230 } else { | |
231 _sendKindNotification(source.fullName, ExecutableKind.CLIENT); | |
232 } | |
233 librarySources.remove(source); | |
234 } | |
235 for (Source source in serverSources) { | |
236 _sendKindNotification(source.fullName, ExecutableKind.SERVER); | |
237 librarySources.remove(source); | |
238 } | |
239 for (Source source in librarySources) { | |
240 _sendKindNotification(source.fullName, ExecutableKind.NOT_EXECUTABLE); | |
241 } | |
242 for (Source source in context.htmlSources) { | |
243 String filePath = source.fullName; | |
244 if (_isInAnalysisRoot(filePath)) { | |
245 List<Source> libraries = | |
246 context.getLibrariesReferencedFromHtml(source); | |
247 server.sendNotification(new ExecutionLaunchDataParams(filePath, | |
248 referencedFiles: _getFullNames(libraries)) | |
249 .toNotification()); | |
250 } | |
251 } | |
252 } | |
253 } | |
254 | |
255 /** | |
256 * Send a notification indicating the [kind] of the file with the given | |
257 * [filePath], but only if the file is in an analysis root. | |
258 */ | |
259 void _sendKindNotification(String filePath, ExecutableKind kind) { | |
260 if (_isInAnalysisRoot(filePath)) { | |
261 server.sendNotification( | |
262 new ExecutionLaunchDataParams(filePath, kind: kind).toNotification()); | |
263 } | |
264 } | |
265 | |
266 static List<String> _getFullNames(List<Source> sources) { | |
267 return sources.map((Source source) => source.fullName).toList(); | |
268 } | 146 } |
269 } | 147 } |
OLD | NEW |