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:io'; | 6 import 'dart:io'; |
7 import 'dart:math'; | 7 import 'dart:math'; |
8 | 8 |
9 import 'package:analysis_server/src/analysis_server.dart'; | 9 import 'package:analysis_server/src/analysis_server.dart'; |
10 import 'package:analysis_server/src/plugin/server_plugin.dart'; | 10 import 'package:analysis_server/src/plugin/server_plugin.dart'; |
11 import 'package:analysis_server/src/provisional/completion/dart/completion_plugi
n.dart'; | 11 import 'package:analysis_server/src/provisional/completion/dart/completion_plugi
n.dart'; |
12 import 'package:analysis_server/src/server/diagnostic_server.dart'; | 12 import 'package:analysis_server/src/server/diagnostic_server.dart'; |
13 import 'package:analysis_server/src/server/http_server.dart'; | 13 import 'package:analysis_server/src/server/http_server.dart'; |
14 import 'package:analysis_server/src/server/stdio_server.dart'; | 14 import 'package:analysis_server/src/server/stdio_server.dart'; |
15 import 'package:analysis_server/src/socket_server.dart'; | 15 import 'package:analysis_server/src/socket_server.dart'; |
16 import 'package:analysis_server/starter.dart'; | 16 import 'package:analysis_server/starter.dart'; |
17 import 'package:analyzer/file_system/physical_file_system.dart'; | 17 import 'package:analyzer/file_system/physical_file_system.dart'; |
18 import 'package:analyzer/instrumentation/file_instrumentation.dart'; | 18 import 'package:analyzer/instrumentation/file_instrumentation.dart'; |
19 import 'package:analyzer/instrumentation/instrumentation.dart'; | 19 import 'package:analyzer/instrumentation/instrumentation.dart'; |
20 import 'package:analyzer/plugin/resolver_provider.dart'; | 20 import 'package:analyzer/plugin/resolver_provider.dart'; |
21 import 'package:analyzer/src/dart/sdk/sdk.dart'; | 21 import 'package:analyzer/src/dart/sdk/sdk.dart'; |
22 import 'package:analyzer/src/generated/engine.dart'; | 22 import 'package:analyzer/src/generated/engine.dart'; |
23 import 'package:analyzer/src/generated/sdk.dart'; | 23 import 'package:analyzer/src/generated/sdk.dart'; |
24 import 'package:args/args.dart'; | 24 import 'package:args/args.dart'; |
25 import 'package:linter/src/rules.dart' as linter; | 25 import 'package:linter/src/rules.dart' as linter; |
26 import 'package:plugin/manager.dart'; | 26 import 'package:plugin/manager.dart'; |
27 import 'package:plugin/plugin.dart'; | 27 import 'package:plugin/plugin.dart'; |
| 28 import 'package:telemetry/crash_reporting.dart'; |
| 29 import 'package:telemetry/telemetry.dart' as telemetry; |
28 | 30 |
29 /// Commandline argument parser. (Copied from analyzer/lib/options.dart) | 31 /// Commandline argument parser. (Copied from analyzer/lib/options.dart) |
30 /// TODO(pquitslund): replaces with a simple [ArgParser] instance | 32 /// TODO(pquitslund): replaces with a simple [ArgParser] instance |
31 /// when the args package supports ignoring unrecognized | 33 /// when the args package supports ignoring unrecognized |
32 /// options/flags (https://github.com/dart-lang/args/issues/9). | 34 /// options/flags (https://github.com/dart-lang/args/issues/9). |
33 class CommandLineParser { | 35 class CommandLineParser { |
34 final List<String> _knownFlags; | 36 final List<String> _knownFlags; |
35 final bool _alwaysIgnoreUnrecognized; | 37 final bool _alwaysIgnoreUnrecognized; |
36 final ArgParser _parser; | 38 final ArgParser _parser; |
37 | 39 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 // Only filter args if the ignore flag is specified, or if | 120 // Only filter args if the ignore flag is specified, or if |
119 // _alwaysIgnoreUnrecognized was set to true | 121 // _alwaysIgnoreUnrecognized was set to true |
120 if (_alwaysIgnoreUnrecognized || | 122 if (_alwaysIgnoreUnrecognized || |
121 args.contains('--ignore-unrecognized-flags')) { | 123 args.contains('--ignore-unrecognized-flags')) { |
122 // Filter all unrecognized flags and options. | 124 // Filter all unrecognized flags and options. |
123 List<String> filtered = <String>[]; | 125 List<String> filtered = <String>[]; |
124 for (int i = 0; i < args.length; ++i) { | 126 for (int i = 0; i < args.length; ++i) { |
125 String arg = args[i]; | 127 String arg = args[i]; |
126 if (arg.startsWith('--') && arg.length > 2) { | 128 if (arg.startsWith('--') && arg.length > 2) { |
127 String option = arg.substring(2); | 129 String option = arg.substring(2); |
| 130 // remove any leading 'no-' |
| 131 if (option.startsWith('no-')) { |
| 132 option = option.substring(3); |
| 133 } |
128 // strip the last '=value' | 134 // strip the last '=value' |
129 int equalsOffset = option.lastIndexOf('='); | 135 int equalsOffset = option.lastIndexOf('='); |
130 if (equalsOffset != -1) { | 136 if (equalsOffset != -1) { |
131 option = option.substring(0, equalsOffset); | 137 option = option.substring(0, equalsOffset); |
132 } | 138 } |
133 // check the option | 139 // check the option |
134 if (!_knownFlags.contains(option)) { | 140 if (!_knownFlags.contains(option)) { |
135 //"eat" params by advancing to the next flag/option | 141 //"eat" params by advancing to the next flag/option |
136 i = _getNextFlagIndex(args, i); | 142 i = _getNextFlagIndex(args, i); |
137 } else { | 143 } else { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 * The name of the option used to set the file read mode. | 194 * The name of the option used to set the file read mode. |
189 */ | 195 */ |
190 static const String FILE_READ_MODE = "file-read-mode"; | 196 static const String FILE_READ_MODE = "file-read-mode"; |
191 | 197 |
192 /** | 198 /** |
193 * The name of the option used to print usage information. | 199 * The name of the option used to print usage information. |
194 */ | 200 */ |
195 static const String HELP_OPTION = "help"; | 201 static const String HELP_OPTION = "help"; |
196 | 202 |
197 /** | 203 /** |
| 204 * The name of the flag used to configure reporting analytics. |
| 205 */ |
| 206 static const String ANALYTICS_FLAG = "analytics"; |
| 207 |
| 208 /** |
| 209 * Suppress analytics for this session. |
| 210 */ |
| 211 static const String SUPPRESS_ANALYTICS_FLAG = "suppress-analytics"; |
| 212 |
| 213 /** |
198 * The name of the option used to cause instrumentation to also be written to | 214 * The name of the option used to cause instrumentation to also be written to |
199 * a local file. | 215 * a local file. |
200 */ | 216 */ |
201 static const String INSTRUMENTATION_LOG_FILE = "instrumentation-log-file"; | 217 static const String INSTRUMENTATION_LOG_FILE = "instrumentation-log-file"; |
202 | 218 |
203 /** | 219 /** |
204 * The name of the option used to specify if [print] should print to the | 220 * The name of the option used to specify if [print] should print to the |
205 * console instead of being intercepted. | 221 * console instead of being intercepted. |
206 */ | 222 */ |
207 static const String INTERNAL_PRINT_TO_CONSOLE = "internal-print-to-console"; | 223 static const String INTERNAL_PRINT_TO_CONSOLE = "internal-print-to-console"; |
(...skipping 17 matching lines...) Expand all Loading... |
225 | 241 |
226 /** | 242 /** |
227 * The option for specifying the http diagnostic port. | 243 * The option for specifying the http diagnostic port. |
228 * If specified, users can review server status and performance information | 244 * If specified, users can review server status and performance information |
229 * by opening a web browser on http://localhost:<port> | 245 * by opening a web browser on http://localhost:<port> |
230 */ | 246 */ |
231 static const String PORT_OPTION = "port"; | 247 static const String PORT_OPTION = "port"; |
232 | 248 |
233 /** | 249 /** |
234 * The path to the SDK. | 250 * The path to the SDK. |
235 * TODO(paulberry): get rid of this once the 'analysis.updateSdks' request is | |
236 * operational. | |
237 */ | 251 */ |
238 static const String SDK_OPTION = "sdk"; | 252 static const String SDK_OPTION = "sdk"; |
239 | 253 |
240 /** | 254 /** |
241 * The instrumentation server that is to be used by the analysis server. | 255 * The instrumentation server that is to be used by the analysis server. |
242 */ | 256 */ |
243 InstrumentationServer instrumentationServer; | 257 InstrumentationServer instrumentationServer; |
244 | 258 |
245 /** | 259 /** |
246 * The file resolver provider used to override the way file URI's are | 260 * The file resolver provider used to override the way file URI's are |
(...skipping 30 matching lines...) Expand all Loading... |
277 /** | 291 /** |
278 * Use the given command-line [arguments] to start this server. | 292 * Use the given command-line [arguments] to start this server. |
279 * | 293 * |
280 * At least temporarily returns AnalysisServer so that consumers of the | 294 * At least temporarily returns AnalysisServer so that consumers of the |
281 * starter API can then use the server, this is done as a stopgap for the | 295 * starter API can then use the server, this is done as a stopgap for the |
282 * angular plugin until the official plugin API is finished. | 296 * angular plugin until the official plugin API is finished. |
283 */ | 297 */ |
284 AnalysisServer start(List<String> arguments) { | 298 AnalysisServer start(List<String> arguments) { |
285 CommandLineParser parser = _createArgParser(); | 299 CommandLineParser parser = _createArgParser(); |
286 ArgResults results = parser.parse(arguments, <String, String>{}); | 300 ArgResults results = parser.parse(arguments, <String, String>{}); |
287 if (results[HELP_OPTION]) { | 301 |
288 _printUsage(parser.parser); | 302 AnalysisServerOptions analysisServerOptions = new AnalysisServerOptions(); |
| 303 analysisServerOptions.useAnalysisHighlight2 = |
| 304 results[USE_ANALYSIS_HIGHLIGHT2]; |
| 305 analysisServerOptions.fileReadMode = results[FILE_READ_MODE]; |
| 306 analysisServerOptions.newAnalysisDriverLog = |
| 307 results[NEW_ANALYSIS_DRIVER_LOG]; |
| 308 analysisServerOptions.clientId = results[CLIENT_ID]; |
| 309 analysisServerOptions.clientVersion = results[CLIENT_VERSION]; |
| 310 analysisServerOptions.enableVerboseFlutterCompletions = |
| 311 results[VERBOSE_FLUTTER_COMPLETIONS]; |
| 312 |
| 313 telemetry.Analytics analytics = telemetry.createAnalyticsInstance( |
| 314 'UA-26406144-29', 'analysis-server', |
| 315 disableForSession: results[SUPPRESS_ANALYTICS_FLAG]); |
| 316 analysisServerOptions.analytics = analytics; |
| 317 |
| 318 if (analysisServerOptions.clientId != null) { |
| 319 // Record the client name as the application installer ID. |
| 320 analytics.setSessionValue('aiid', analysisServerOptions.clientId); |
| 321 } |
| 322 if (analysisServerOptions.clientVersion != null) { |
| 323 analytics.setSessionValue('cd1', analysisServerOptions.clientVersion); |
| 324 } |
| 325 |
| 326 // TODO(devoncarew): Replace with the real crash product ID. |
| 327 analysisServerOptions.crashReportSender = |
| 328 new CrashReportSender('Dart_analysis_server', analytics); |
| 329 |
| 330 if (results.wasParsed(ANALYTICS_FLAG)) { |
| 331 analytics.enabled = results[ANALYTICS_FLAG]; |
| 332 print(telemetry.createAnalyticsStatusMessage(analytics.enabled)); |
289 return null; | 333 return null; |
290 } | 334 } |
291 | 335 |
| 336 if (results[HELP_OPTION]) { |
| 337 _printUsage(parser.parser, analytics, fromHelp: true); |
| 338 return null; |
| 339 } |
| 340 |
292 int port; | 341 int port; |
293 bool serve_http = false; | 342 bool serve_http = false; |
294 if (results[PORT_OPTION] != null) { | 343 if (results[PORT_OPTION] != null) { |
295 try { | 344 try { |
296 port = int.parse(results[PORT_OPTION]); | 345 port = int.parse(results[PORT_OPTION]); |
297 serve_http = true; | 346 serve_http = true; |
298 } on FormatException { | 347 } on FormatException { |
299 print('Invalid port number: ${results[PORT_OPTION]}'); | 348 print('Invalid port number: ${results[PORT_OPTION]}'); |
300 print(''); | 349 print(''); |
301 _printUsage(parser.parser); | 350 _printUsage(parser.parser, analytics); |
302 exitCode = 1; | 351 exitCode = 1; |
303 return null; | 352 return null; |
304 } | 353 } |
305 } | 354 } |
306 | 355 |
307 AnalysisServerOptions analysisServerOptions = new AnalysisServerOptions(); | |
308 analysisServerOptions.useAnalysisHighlight2 = | |
309 results[USE_ANALYSIS_HIGHLIGHT2]; | |
310 analysisServerOptions.fileReadMode = results[FILE_READ_MODE]; | |
311 analysisServerOptions.newAnalysisDriverLog = | |
312 results[NEW_ANALYSIS_DRIVER_LOG]; | |
313 | |
314 analysisServerOptions.clientId = results[CLIENT_ID]; | |
315 analysisServerOptions.clientVersion = results[CLIENT_VERSION]; | |
316 | |
317 analysisServerOptions.enableVerboseFlutterCompletions = | |
318 results[VERBOSE_FLUTTER_COMPLETIONS]; | |
319 | |
320 // | 356 // |
321 // Process all of the plugins so that extensions are registered. | 357 // Process all of the plugins so that extensions are registered. |
322 // | 358 // |
323 ServerPlugin serverPlugin = new ServerPlugin(); | 359 ServerPlugin serverPlugin = new ServerPlugin(); |
324 List<Plugin> plugins = <Plugin>[]; | 360 List<Plugin> plugins = <Plugin>[]; |
325 plugins.addAll(AnalysisEngine.instance.requiredPlugins); | 361 plugins.addAll(AnalysisEngine.instance.requiredPlugins); |
326 plugins.add(serverPlugin); | 362 plugins.add(serverPlugin); |
327 plugins.add(dartCompletionPlugin); | 363 plugins.add(dartCompletionPlugin); |
328 plugins.addAll(_userDefinedPlugins); | 364 plugins.addAll(_userDefinedPlugins); |
329 ExtensionManager manager = new ExtensionManager(); | 365 ExtensionManager manager = new ExtensionManager(); |
(...skipping 24 matching lines...) Expand all Loading... |
354 new FileInstrumentationServer(logFilePath); | 390 new FileInstrumentationServer(logFilePath); |
355 instrumentationServer = instrumentationServer != null | 391 instrumentationServer = instrumentationServer != null |
356 ? new MulticastInstrumentationServer( | 392 ? new MulticastInstrumentationServer( |
357 [instrumentationServer, fileBasedServer]) | 393 [instrumentationServer, fileBasedServer]) |
358 : fileBasedServer; | 394 : fileBasedServer; |
359 } | 395 } |
360 InstrumentationService instrumentationService = | 396 InstrumentationService instrumentationService = |
361 new InstrumentationService(instrumentationServer); | 397 new InstrumentationService(instrumentationServer); |
362 instrumentationService.logVersion( | 398 instrumentationService.logVersion( |
363 _readUuid(instrumentationService), | 399 _readUuid(instrumentationService), |
364 results[CLIENT_ID], | 400 analysisServerOptions.clientId, |
365 results[CLIENT_VERSION], | 401 analysisServerOptions.clientVersion, |
366 AnalysisServer.VERSION, | 402 AnalysisServer.VERSION, |
367 defaultSdk.sdkVersion); | 403 defaultSdk.sdkVersion); |
368 AnalysisEngine.instance.instrumentationService = instrumentationService; | 404 AnalysisEngine.instance.instrumentationService = instrumentationService; |
369 | 405 |
370 _DiagnosticServerImpl diagnosticServer = new _DiagnosticServerImpl(); | 406 _DiagnosticServerImpl diagnosticServer = new _DiagnosticServerImpl(); |
371 | 407 |
| 408 // Ping analytics with our initial call. |
| 409 analytics.sendScreenView('home'); |
| 410 |
372 // | 411 // |
373 // Create the sockets and start listening for requests. | 412 // Create the sockets and start listening for requests. |
374 // | 413 // |
375 socketServer = new SocketServer( | 414 socketServer = new SocketServer( |
376 analysisServerOptions, | 415 analysisServerOptions, |
377 new DartSdkManager(defaultSdkPath, true), | 416 new DartSdkManager(defaultSdkPath, true), |
378 defaultSdk, | 417 defaultSdk, |
379 instrumentationService, | 418 instrumentationService, |
380 diagnosticServer, | 419 diagnosticServer, |
381 serverPlugin, | 420 serverPlugin, |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 parser.addFlag(ENABLE_INSTRUMENTATION_OPTION, | 484 parser.addFlag(ENABLE_INSTRUMENTATION_OPTION, |
446 help: "enable sending instrumentation information to a server", | 485 help: "enable sending instrumentation information to a server", |
447 defaultsTo: false, | 486 defaultsTo: false, |
448 negatable: false); | 487 negatable: false); |
449 parser.addFlag(HELP_OPTION, | 488 parser.addFlag(HELP_OPTION, |
450 help: "print this help message without starting a server", | 489 help: "print this help message without starting a server", |
451 abbr: 'h', | 490 abbr: 'h', |
452 defaultsTo: false, | 491 defaultsTo: false, |
453 negatable: false); | 492 negatable: false); |
454 parser.addOption(INSTRUMENTATION_LOG_FILE, | 493 parser.addOption(INSTRUMENTATION_LOG_FILE, |
455 help: | 494 help: "write instrumentation data to the given file"); |
456 "the path of the file to which instrumentation data will be written"
); | |
457 parser.addFlag(INTERNAL_PRINT_TO_CONSOLE, | 495 parser.addFlag(INTERNAL_PRINT_TO_CONSOLE, |
458 help: "enable sending `print` output to the console", | 496 help: "enable sending `print` output to the console", |
459 defaultsTo: false, | 497 defaultsTo: false, |
460 negatable: false); | 498 negatable: false); |
461 parser.addOption(NEW_ANALYSIS_DRIVER_LOG, | 499 parser.addOption(NEW_ANALYSIS_DRIVER_LOG, |
462 help: "set a destination for the new analysis driver's log"); | 500 help: "set a destination for the new analysis driver's log"); |
463 parser.addFlag(VERBOSE_FLUTTER_COMPLETIONS, | 501 parser.addFlag(VERBOSE_FLUTTER_COMPLETIONS, |
464 help: "enable verbose code completion for Flutter (experimental)"); | 502 help: "enable verbose code completion for Flutter (experimental)"); |
| 503 parser.addFlag(ANALYTICS_FLAG, |
| 504 help: 'enable or disable sending analytics information to Google'); |
| 505 parser.addFlag(SUPPRESS_ANALYTICS_FLAG, |
| 506 negatable: false, help: 'suppress analytics for this session'); |
465 parser.addOption(PORT_OPTION, | 507 parser.addOption(PORT_OPTION, |
466 help: "the http diagnostic port on which the server provides" | 508 help: "the http diagnostic port on which the server provides" |
467 " status and performance information"); | 509 " status and performance information"); |
468 parser.addOption(SDK_OPTION, help: "[path] the path to the sdk"); | 510 parser.addOption(SDK_OPTION, help: "[path] the path to the sdk"); |
469 parser.addFlag(USE_ANALYSIS_HIGHLIGHT2, | 511 parser.addFlag(USE_ANALYSIS_HIGHLIGHT2, |
470 help: "enable version 2 of semantic highlight", | 512 help: "enable version 2 of semantic highlight", |
471 defaultsTo: false, | 513 defaultsTo: false, |
472 negatable: false); | 514 negatable: false); |
473 parser.addOption(FILE_READ_MODE, | 515 parser.addOption(FILE_READ_MODE, |
474 help: "an option for reading files (some clients normalize eol " | 516 help: "an option for reading files (some clients normalize eol " |
(...skipping 15 matching lines...) Expand all Loading... |
490 PhysicalResourceProvider.INSTANCE; | 532 PhysicalResourceProvider.INSTANCE; |
491 FolderBasedDartSdk sdk = new FolderBasedDartSdk( | 533 FolderBasedDartSdk sdk = new FolderBasedDartSdk( |
492 resourceProvider, resourceProvider.getFolder(defaultSdkPath)); | 534 resourceProvider, resourceProvider.getFolder(defaultSdkPath)); |
493 sdk.useSummary = useSummaries; | 535 sdk.useSummary = useSummaries; |
494 return sdk; | 536 return sdk; |
495 } | 537 } |
496 | 538 |
497 /** | 539 /** |
498 * Print information about how to use the server. | 540 * Print information about how to use the server. |
499 */ | 541 */ |
500 void _printUsage(ArgParser parser) { | 542 void _printUsage(ArgParser parser, telemetry.Analytics analytics, |
| 543 {bool fromHelp: false}) { |
501 print('Usage: $BINARY_NAME [flags]'); | 544 print('Usage: $BINARY_NAME [flags]'); |
502 print(''); | 545 print(''); |
503 print('Supported flags are:'); | 546 print('Supported flags are:'); |
504 print(parser.usage); | 547 print(parser.usage); |
| 548 |
| 549 // Print analytics status and information. |
| 550 if (fromHelp) { |
| 551 print(''); |
| 552 print(telemetry.analyticsNotice); |
| 553 } |
| 554 print(''); |
| 555 print(telemetry.createAnalyticsStatusMessage(analytics.enabled, |
| 556 command: ANALYTICS_FLAG)); |
505 } | 557 } |
506 | 558 |
507 /** | 559 /** |
508 * Read the UUID from disk, generating and storing a new one if necessary. | 560 * Read the UUID from disk, generating and storing a new one if necessary. |
509 */ | 561 */ |
510 String _readUuid(InstrumentationService service) { | 562 String _readUuid(InstrumentationService service) { |
511 File uuidFile = new File(PhysicalResourceProvider.INSTANCE | 563 File uuidFile = new File(PhysicalResourceProvider.INSTANCE |
512 .getStateLocation('.instrumentation') | 564 .getStateLocation('.instrumentation') |
513 .getChild('uuid.txt') | 565 .getChild('uuid.txt') |
514 .path); | 566 .path); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 | 613 |
562 _DiagnosticServerImpl(); | 614 _DiagnosticServerImpl(); |
563 | 615 |
564 @override | 616 @override |
565 Future<int> getServerPort() => httpServer.serveHttp(); | 617 Future<int> getServerPort() => httpServer.serveHttp(); |
566 | 618 |
567 Future startOnPort(int port) { | 619 Future startOnPort(int port) { |
568 return httpServer.serveHttp(port); | 620 return httpServer.serveHttp(port); |
569 } | 621 } |
570 } | 622 } |
OLD | NEW |