| 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 |