| 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 driver; | |
| 6 | |
| 7 import 'dart:async'; | |
| 8 import 'dart:io'; | |
| 9 | |
| 10 import 'package:analysis_server/http_server.dart'; | |
| 11 import 'package:analysis_server/plugin/plugin.dart'; | |
| 12 import 'package:analysis_server/src/analysis_server.dart'; | |
| 13 import 'package:analysis_server/src/plugin/plugin_impl.dart'; | |
| 14 import 'package:analysis_server/src/plugin/server_plugin.dart'; | |
| 15 import 'package:analysis_server/src/socket_server.dart'; | |
| 16 import 'package:analysis_server/stdio_server.dart'; | |
| 17 import 'package:analyzer/instrumentation/instrumentation.dart'; | |
| 18 import 'package:analyzer/src/generated/engine.dart'; | |
| 19 import 'package:analyzer/src/generated/incremental_logger.dart'; | |
| 20 import 'package:analyzer/src/generated/java_io.dart'; | |
| 21 import 'package:analyzer/src/generated/sdk.dart'; | |
| 22 import 'package:analyzer/src/generated/sdk_io.dart'; | |
| 23 import 'package:args/args.dart'; | |
| 24 | |
| 25 | |
| 26 /** | |
| 27 * Initializes incremental logger. | |
| 28 * | |
| 29 * Supports following formats of [spec]: | |
| 30 * | |
| 31 * "console" - log to the console; | |
| 32 * "file:/some/file/name" - log to the file, overwritten on start. | |
| 33 */ | |
| 34 void _initIncrementalLogger(String spec) { | |
| 35 logger = NULL_LOGGER; | |
| 36 if (spec == null) { | |
| 37 return; | |
| 38 } | |
| 39 // create logger | |
| 40 if (spec == 'console') { | |
| 41 logger = new StringSinkLogger(console.log); | |
| 42 } | |
| 43 if (spec.startsWith('file:')) { | |
| 44 String fileName = spec.substring('file:'.length); | |
| 45 File file = new File(fileName); | |
| 46 IOSink sink = file.openWrite(); | |
| 47 logger = new StringSinkLogger(sink); | |
| 48 } | |
| 49 } | |
| 50 | |
| 51 | |
| 52 /** | |
| 53 * The [Driver] class represents a single running instance of the analysis | |
| 54 * server application. It is responsible for parsing command line options | |
| 55 * and starting the HTTP and/or stdio servers. | |
| 56 */ | |
| 57 class Driver { | |
| 58 /** | |
| 59 * The name of the application that is used to start a server. | |
| 60 */ | |
| 61 static const BINARY_NAME = "server"; | |
| 62 | |
| 63 /** | |
| 64 * The name of the option used to set the identifier for the client. | |
| 65 */ | |
| 66 static const String CLIENT_ID = "client-id"; | |
| 67 | |
| 68 /** | |
| 69 * The name of the option used to enable incremental resolution of API | |
| 70 * changes. | |
| 71 */ | |
| 72 static const String ENABLE_INCREMENTAL_RESOLUTION_API = | |
| 73 "enable-incremental-resolution-api"; | |
| 74 | |
| 75 /** | |
| 76 * The name of the option used to describe the incremental resolution logger. | |
| 77 */ | |
| 78 static const String INCREMENTAL_RESOLUTION_LOG = "incremental-resolution-log"; | |
| 79 | |
| 80 /** | |
| 81 * The name of the option used to enable validation of incremental resolution | |
| 82 * results. | |
| 83 */ | |
| 84 static const String INCREMENTAL_RESOLUTION_VALIDATION = | |
| 85 "incremental-resolution-validation"; | |
| 86 | |
| 87 /** | |
| 88 * The name of the option used to enable instrumentation. | |
| 89 */ | |
| 90 static const String ENABLE_INSTRUMENTATION_OPTION = "enable-instrumentation"; | |
| 91 | |
| 92 /** | |
| 93 * The name of the option used to print usage information. | |
| 94 */ | |
| 95 static const String HELP_OPTION = "help"; | |
| 96 | |
| 97 /** | |
| 98 * The name of the option used to specify if [print] should print to the | |
| 99 * console instead of being intercepted. | |
| 100 */ | |
| 101 static const String INTERNAL_PRINT_TO_CONSOLE = "internal-print-to-console"; | |
| 102 | |
| 103 /** | |
| 104 * The name of the option used to specify the port to which the server will | |
| 105 * connect. | |
| 106 */ | |
| 107 static const String PORT_OPTION = "port"; | |
| 108 | |
| 109 /** | |
| 110 * The path to the SDK. | |
| 111 * TODO(paulberry): get rid of this once the 'analysis.updateSdks' request is | |
| 112 * operational. | |
| 113 */ | |
| 114 static const String SDK_OPTION = "sdk"; | |
| 115 | |
| 116 /** | |
| 117 * The name of the option used to disable error notifications. | |
| 118 */ | |
| 119 static const String NO_ERROR_NOTIFICATION = "no-error-notification"; | |
| 120 | |
| 121 /** | |
| 122 * The instrumentation server that is to be used by the analysis server. | |
| 123 */ | |
| 124 InstrumentationServer instrumentationServer; | |
| 125 | |
| 126 /** | |
| 127 * The plugins that are defined outside the analysis_server package. | |
| 128 */ | |
| 129 List<Plugin> _userDefinedPlugins = <Plugin>[]; | |
| 130 | |
| 131 SocketServer socketServer; | |
| 132 | |
| 133 HttpAnalysisServer httpServer; | |
| 134 | |
| 135 StdioAnalysisServer stdioServer; | |
| 136 | |
| 137 Driver(); | |
| 138 | |
| 139 /** | |
| 140 * Set the [plugins] that are defined outside the analysis_server package. | |
| 141 */ | |
| 142 void set userDefinedPlugins(List<Plugin> plugins) { | |
| 143 _userDefinedPlugins = plugins == null ? <Plugin>[] : plugins; | |
| 144 } | |
| 145 | |
| 146 /** | |
| 147 * Use the given command-line arguments to start this server. | |
| 148 */ | |
| 149 void start(List<String> args) { | |
| 150 ArgParser parser = new ArgParser(); | |
| 151 parser.addOption( | |
| 152 CLIENT_ID, | |
| 153 help: "an identifier used to identify the client"); | |
| 154 parser.addFlag( | |
| 155 ENABLE_INCREMENTAL_RESOLUTION_API, | |
| 156 help: "enable using incremental resolution for API changes", | |
| 157 defaultsTo: false, | |
| 158 negatable: false); | |
| 159 parser.addFlag( | |
| 160 ENABLE_INSTRUMENTATION_OPTION, | |
| 161 help: "enable sending instrumentation information to a server", | |
| 162 defaultsTo: false, | |
| 163 negatable: false); | |
| 164 parser.addFlag( | |
| 165 HELP_OPTION, | |
| 166 help: "print this help message without starting a server", | |
| 167 defaultsTo: false, | |
| 168 negatable: false); | |
| 169 parser.addOption( | |
| 170 INCREMENTAL_RESOLUTION_LOG, | |
| 171 help: "the description of the incremental resolution log"); | |
| 172 parser.addFlag( | |
| 173 INCREMENTAL_RESOLUTION_VALIDATION, | |
| 174 help: "enable validation of incremental resolution results (slow)", | |
| 175 defaultsTo: false, | |
| 176 negatable: false); | |
| 177 parser.addFlag( | |
| 178 INTERNAL_PRINT_TO_CONSOLE, | |
| 179 help: "enable sending `print` output to the console", | |
| 180 defaultsTo: false, | |
| 181 negatable: false); | |
| 182 parser.addOption( | |
| 183 PORT_OPTION, | |
| 184 help: "[port] the port on which the server will listen"); | |
| 185 parser.addOption(SDK_OPTION, help: "[path] the path to the sdk"); | |
| 186 parser.addFlag( | |
| 187 NO_ERROR_NOTIFICATION, | |
| 188 help: | |
| 189 "disable sending all analysis error notifications to the server (not
yet implemented)", | |
| 190 defaultsTo: false, | |
| 191 negatable: false); | |
| 192 | |
| 193 ArgResults results = parser.parse(args); | |
| 194 if (results[HELP_OPTION]) { | |
| 195 _printUsage(parser); | |
| 196 return; | |
| 197 } | |
| 198 | |
| 199 // TODO(brianwilkerson) Enable this after it is possible for an | |
| 200 // instrumentation server to be provided. | |
| 201 // if (results[ENABLE_INSTRUMENTATION_OPTION]) { | |
| 202 // if (instrumentationServer == null) { | |
| 203 // print('Exiting server: enabled instrumentation without providing an in
strumentation server'); | |
| 204 // print(''); | |
| 205 // _printUsage(parser); | |
| 206 // return; | |
| 207 // } | |
| 208 // } else { | |
| 209 // if (instrumentationServer != null) { | |
| 210 // print('Exiting server: providing an instrumentation server without ena
bling instrumentation'); | |
| 211 // print(''); | |
| 212 // _printUsage(parser); | |
| 213 // return; | |
| 214 // } | |
| 215 // } | |
| 216 | |
| 217 int port; | |
| 218 bool serve_http = false; | |
| 219 if (results[PORT_OPTION] != null) { | |
| 220 serve_http = true; | |
| 221 try { | |
| 222 port = int.parse(results[PORT_OPTION]); | |
| 223 } on FormatException { | |
| 224 print('Invalid port number: ${results[PORT_OPTION]}'); | |
| 225 print(''); | |
| 226 _printUsage(parser); | |
| 227 exitCode = 1; | |
| 228 return; | |
| 229 } | |
| 230 } | |
| 231 | |
| 232 AnalysisServerOptions analysisServerOptions = new AnalysisServerOptions(); | |
| 233 analysisServerOptions.enableIncrementalResolutionApi = | |
| 234 results[ENABLE_INCREMENTAL_RESOLUTION_API]; | |
| 235 analysisServerOptions.enableIncrementalResolutionValidation = | |
| 236 results[INCREMENTAL_RESOLUTION_VALIDATION]; | |
| 237 | |
| 238 _initIncrementalLogger(results[INCREMENTAL_RESOLUTION_LOG]); | |
| 239 | |
| 240 DartSdk defaultSdk; | |
| 241 if (results[SDK_OPTION] != null) { | |
| 242 defaultSdk = new DirectoryBasedDartSdk(new JavaFile(results[SDK_OPTION])); | |
| 243 } else { | |
| 244 // No path to the SDK provided; use DirectoryBasedDartSdk.defaultSdk, | |
| 245 // which will make a guess. | |
| 246 defaultSdk = DirectoryBasedDartSdk.defaultSdk; | |
| 247 } | |
| 248 | |
| 249 InstrumentationService service = | |
| 250 new InstrumentationService(instrumentationServer); | |
| 251 // service.logVersion(results[CLIENT_ID], defaultSdk.sdkVersion); | |
| 252 AnalysisEngine.instance.instrumentationService = service; | |
| 253 // | |
| 254 // Process all of the plugins so that extensions are registered. | |
| 255 // | |
| 256 ServerPlugin serverPlugin = new ServerPlugin(); | |
| 257 List<Plugin> plugins = <Plugin>[]; | |
| 258 plugins.add(serverPlugin); | |
| 259 plugins.addAll(_userDefinedPlugins); | |
| 260 ExtensionManager manager = new ExtensionManager(); | |
| 261 manager.processPlugins(plugins); | |
| 262 | |
| 263 socketServer = | |
| 264 new SocketServer(analysisServerOptions, defaultSdk, service, serverPlugi
n); | |
| 265 httpServer = new HttpAnalysisServer(socketServer); | |
| 266 stdioServer = new StdioAnalysisServer(socketServer); | |
| 267 | |
| 268 if (serve_http) { | |
| 269 httpServer.serveHttp(port); | |
| 270 } | |
| 271 | |
| 272 _captureExceptions(service, () { | |
| 273 stdioServer.serveStdio().then((_) { | |
| 274 if (serve_http) { | |
| 275 httpServer.close(); | |
| 276 } | |
| 277 service.shutdown(); | |
| 278 exit(0); | |
| 279 }); | |
| 280 }, | |
| 281 print: results[INTERNAL_PRINT_TO_CONSOLE] ? null : httpServer.recordPrin
t); | |
| 282 } | |
| 283 | |
| 284 /** | |
| 285 * Execute the given [callback] within a zone that will capture any unhandled | |
| 286 * exceptions and both report them to the client and send them to the given | |
| 287 * instrumentation [service]. If a [print] function is provided, then also | |
| 288 * capture any data printed by the callback and redirect it to the function. | |
| 289 */ | |
| 290 dynamic _captureExceptions(InstrumentationService service, dynamic callback(), | |
| 291 {void print(String line)}) { | |
| 292 Function errorFunction = | |
| 293 (Zone self, ZoneDelegate parent, Zone zone, dynamic exception, | |
| 294 StackTrace stackTrace) { | |
| 295 service.logPriorityException(exception, stackTrace); | |
| 296 socketServer.analysisServer.reportException(exception, stackTrace); | |
| 297 throw exception; | |
| 298 }; | |
| 299 Function printFunction = print == null ? | |
| 300 null : | |
| 301 (Zone self, ZoneDelegate parent, Zone zone, String line) { | |
| 302 // Note: we don't pass the line on to stdout, because that is reserved | |
| 303 // for communication to the client. | |
| 304 print(line); | |
| 305 }; | |
| 306 ZoneSpecification zoneSpecification = new ZoneSpecification( | |
| 307 handleUncaughtError: errorFunction, | |
| 308 print: printFunction); | |
| 309 return runZoned(callback, zoneSpecification: zoneSpecification); | |
| 310 } | |
| 311 | |
| 312 /** | |
| 313 * Print information about how to use the server. | |
| 314 */ | |
| 315 void _printUsage(ArgParser parser) { | |
| 316 print('Usage: $BINARY_NAME [flags]'); | |
| 317 print(''); | |
| 318 print('Supported flags are:'); | |
| 319 print(parser.usage); | |
| 320 } | |
| 321 } | |
| OLD | NEW |