| 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 domain.execution; | 5 library domain.execution; |
| 6 | 6 |
| 7 import 'dart:async'; |
| 8 import 'dart:collection'; |
| 9 |
| 7 import 'package:analysis_server/src/analysis_server.dart'; | 10 import 'package:analysis_server/src/analysis_server.dart'; |
| 8 import 'package:analysis_server/src/constants.dart'; | 11 import 'package:analysis_server/src/constants.dart'; |
| 9 import 'package:analysis_server/src/protocol.dart'; | 12 import 'package:analysis_server/src/protocol.dart'; |
| 10 import 'dart:collection'; | |
| 11 import 'package:analyzer/src/generated/engine.dart'; | 13 import 'package:analyzer/src/generated/engine.dart'; |
| 12 import 'package:analyzer/src/generated/source.dart'; | 14 import 'package:analyzer/src/generated/source.dart'; |
| 13 | 15 |
| 14 /** | 16 /** |
| 15 * Instances of the class [ExecutionDomainHandler] implement a [RequestHandler] | 17 * Instances of the class [ExecutionDomainHandler] implement a [RequestHandler] |
| 16 * that handles requests in the `execution` domain. | 18 * that handles requests in the `execution` domain. |
| 17 */ | 19 */ |
| 18 class ExecutionDomainHandler implements RequestHandler { | 20 class ExecutionDomainHandler implements RequestHandler { |
| 19 /** | 21 /** |
| 20 * The analysis server that is using this handler to process requests. | 22 * The analysis server that is using this handler to process requests. |
| 21 */ | 23 */ |
| 22 final AnalysisServer server; | 24 final AnalysisServer server; |
| 23 | 25 |
| 24 /** | 26 /** |
| 25 * The next execution context identifier to be returned. | 27 * The next execution context identifier to be returned. |
| 26 */ | 28 */ |
| 27 int nextContextId = 0; | 29 int nextContextId = 0; |
| 28 | 30 |
| 29 /** | 31 /** |
| 30 * A table mapping execution context id's to the root of the context. | 32 * A table mapping execution context id's to the root of the context. |
| 31 */ | 33 */ |
| 32 Map<String, String> contextMap = new HashMap<String, String>(); | 34 Map<String, String> contextMap = new HashMap<String, String>(); |
| 33 | 35 |
| 34 /** | 36 /** |
| 35 * The listener used to send notifications when | 37 * The subscription to the 'onAnalysisComplete' events, |
| 38 * used to send notifications when |
| 36 */ | 39 */ |
| 37 LaunchDataNotificationListener launchDataListener; | 40 StreamSubscription onAnalysisSubscription; |
| 38 | 41 |
| 39 /** | 42 /** |
| 40 * Initialize a newly created handler to handle requests for the given [server
]. | 43 * Initialize a newly created handler to handle requests for the given [server
]. |
| 41 */ | 44 */ |
| 42 ExecutionDomainHandler(this.server); | 45 ExecutionDomainHandler(this.server); |
| 43 | 46 |
| 44 /** | 47 /** |
| 45 * Implement the `execution.createContext` request. | 48 * Implement the `execution.createContext` request. |
| 46 */ | 49 */ |
| 47 Response createContext(Request request) { | 50 Response createContext(Request request) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 'Either file or uri must be provided'); | 119 'Either file or uri must be provided'); |
| 117 } | 120 } |
| 118 | 121 |
| 119 /** | 122 /** |
| 120 * Implement the 'execution.setSubscriptions' request. | 123 * Implement the 'execution.setSubscriptions' request. |
| 121 */ | 124 */ |
| 122 Response setSubscriptions(Request request) { | 125 Response setSubscriptions(Request request) { |
| 123 List<ExecutionService> subscriptions = | 126 List<ExecutionService> subscriptions = |
| 124 new ExecutionSetSubscriptionsParams.fromRequest(request).subscriptions; | 127 new ExecutionSetSubscriptionsParams.fromRequest(request).subscriptions; |
| 125 if (subscriptions.contains(ExecutionService.LAUNCH_DATA)) { | 128 if (subscriptions.contains(ExecutionService.LAUNCH_DATA)) { |
| 126 if (launchDataListener == null) { | 129 if (onAnalysisSubscription == null) { |
| 127 launchDataListener = new LaunchDataNotificationListener(server); | 130 onAnalysisSubscription = |
| 128 server.addAnalysisServerListener(launchDataListener); | 131 server.onAnalysisComplete.listen(_analysisComplete); |
| 129 if (server.isAnalysisComplete()) { | |
| 130 launchDataListener.analysisComplete(); | |
| 131 } | |
| 132 } | 132 } |
| 133 } else { | 133 } else { |
| 134 if (launchDataListener != null) { | 134 if (onAnalysisSubscription != null) { |
| 135 server.removeAnalysisServerListener(launchDataListener); | 135 onAnalysisSubscription.cancel(); |
| 136 launchDataListener = null; | 136 onAnalysisSubscription = null; |
| 137 } | 137 } |
| 138 } | 138 } |
| 139 return new ExecutionSetSubscriptionsResult().toResponse(request.id); | 139 return new ExecutionSetSubscriptionsResult().toResponse(request.id); |
| 140 } | 140 } |
| 141 } | |
| 142 | 141 |
| 143 /** | 142 void _analysisComplete(_) { |
| 144 * Instances of the class [LaunchDataNotificationListener] listen for analysis | |
| 145 * to be complete and then notify the client of the launch data that has been | |
| 146 * computed. | |
| 147 */ | |
| 148 class LaunchDataNotificationListener implements AnalysisServerListener { | |
| 149 /** | |
| 150 * The analysis server used to send notifications. | |
| 151 */ | |
| 152 final AnalysisServer server; | |
| 153 | |
| 154 /** | |
| 155 * Initialize a newly created listener to send notifications through the given | |
| 156 * [server] when analysis is complete. | |
| 157 */ | |
| 158 LaunchDataNotificationListener(this.server); | |
| 159 | |
| 160 @override | |
| 161 void analysisComplete() { | |
| 162 List<ExecutableFile> executables = []; | 143 List<ExecutableFile> executables = []; |
| 163 Map<String, List<String>> dartToHtml = new HashMap<String, List<String>>(); | 144 Map<String, List<String>> dartToHtml = new HashMap<String, List<String>>(); |
| 164 Map<String, List<String>> htmlToDart = new HashMap<String, List<String>>(); | 145 Map<String, List<String>> htmlToDart = new HashMap<String, List<String>>(); |
| 165 for (AnalysisContext context in server.getAnalysisContexts()) { | 146 for (AnalysisContext context in server.getAnalysisContexts()) { |
| 166 List<Source> clientSources = context.launchableClientLibrarySources; | 147 List<Source> clientSources = context.launchableClientLibrarySources; |
| 167 List<Source> serverSources = context.launchableServerLibrarySources; | 148 List<Source> serverSources = context.launchableServerLibrarySources; |
| 168 for (Source source in clientSources) { | 149 for (Source source in clientSources) { |
| 169 ExecutableKind kind = ExecutableKind.CLIENT; | 150 ExecutableKind kind = ExecutableKind.CLIENT; |
| 170 if (serverSources.remove(source)) { | 151 if (serverSources.remove(source)) { |
| 171 kind = ExecutableKind.EITHER; | 152 kind = ExecutableKind.EITHER; |
| 172 } | 153 } |
| 173 executables.add(new ExecutableFile(source.fullName, kind)); | 154 executables.add(new ExecutableFile(source.fullName, kind)); |
| 174 } | 155 } |
| 175 for (Source source in serverSources) { | 156 for (Source source in serverSources) { |
| 176 executables.add( | 157 executables.add( |
| 177 new ExecutableFile(source.fullName, ExecutableKind.SERVER)); | 158 new ExecutableFile(source.fullName, ExecutableKind.SERVER)); |
| 178 } | 159 } |
| 179 | 160 |
| 180 for (Source librarySource in context.librarySources) { | 161 for (Source librarySource in context.librarySources) { |
| 181 List<Source> files = context.getHtmlFilesReferencing(librarySource); | 162 List<Source> files = context.getHtmlFilesReferencing(librarySource); |
| 182 if (files.isNotEmpty) { | 163 if (files.isNotEmpty) { |
| 183 // TODO(brianwilkerson) Handle the case where the same library is | 164 // TODO(brianwilkerson) Handle the case where the same library is |
| 184 // being analyzed in multiple contexts. | 165 // being analyzed in multiple contexts. |
| 185 dartToHtml[librarySource.fullName] = getFullNames(files); | 166 dartToHtml[librarySource.fullName] = _getFullNames(files); |
| 186 } | 167 } |
| 187 } | 168 } |
| 188 | 169 |
| 189 for (Source htmlSource in context.htmlSources) { | 170 for (Source htmlSource in context.htmlSources) { |
| 190 List<Source> libraries = | 171 List<Source> libraries = |
| 191 context.getLibrariesReferencedFromHtml(htmlSource); | 172 context.getLibrariesReferencedFromHtml(htmlSource); |
| 192 if (libraries.isNotEmpty) { | 173 if (libraries.isNotEmpty) { |
| 193 // TODO(brianwilkerson) Handle the case where the same HTML file is | 174 // TODO(brianwilkerson) Handle the case where the same HTML file is |
| 194 // being analyzed in multiple contexts. | 175 // being analyzed in multiple contexts. |
| 195 htmlToDart[htmlSource.fullName] = getFullNames(libraries); | 176 htmlToDart[htmlSource.fullName] = _getFullNames(libraries); |
| 196 } | 177 } |
| 197 } | 178 } |
| 198 } | 179 } |
| 199 server.sendNotification( | 180 server.sendNotification( |
| 200 new ExecutionLaunchDataParams( | 181 new ExecutionLaunchDataParams( |
| 201 executables, | 182 executables, |
| 202 dartToHtml, | 183 dartToHtml, |
| 203 htmlToDart).toNotification()); | 184 htmlToDart).toNotification()); |
| 204 } | 185 } |
| 205 | 186 |
| 206 List<String> getFullNames(List<Source> sources) { | 187 static List<String> _getFullNames(List<Source> sources) { |
| 207 return sources.map((Source source) => source.fullName).toList(); | 188 return sources.map((Source source) => source.fullName).toList(); |
| 208 } | 189 } |
| 209 } | 190 } |
| OLD | NEW |