OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 analyzer_cli.src.build_mode; | 5 library analyzer_cli.src.build_mode; |
6 | 6 |
7 import 'dart:core' hide Resource; | 7 import 'dart:core' hide Resource; |
8 import 'dart:io' as io; | 8 import 'dart:io' as io; |
9 | 9 |
10 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit; | 10 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit; |
(...skipping 10 matching lines...) Expand all Loading... |
21 import 'package:analyzer/src/summary/idl.dart'; | 21 import 'package:analyzer/src/summary/idl.dart'; |
22 import 'package:analyzer/src/summary/link.dart'; | 22 import 'package:analyzer/src/summary/link.dart'; |
23 import 'package:analyzer/src/summary/package_bundle_reader.dart'; | 23 import 'package:analyzer/src/summary/package_bundle_reader.dart'; |
24 import 'package:analyzer/src/summary/summarize_ast.dart'; | 24 import 'package:analyzer/src/summary/summarize_ast.dart'; |
25 import 'package:analyzer/src/summary/summarize_elements.dart'; | 25 import 'package:analyzer/src/summary/summarize_elements.dart'; |
26 import 'package:analyzer/task/dart.dart'; | 26 import 'package:analyzer/task/dart.dart'; |
27 import 'package:analyzer_cli/src/analyzer_impl.dart'; | 27 import 'package:analyzer_cli/src/analyzer_impl.dart'; |
28 import 'package:analyzer_cli/src/driver.dart'; | 28 import 'package:analyzer_cli/src/driver.dart'; |
29 import 'package:analyzer_cli/src/error_formatter.dart'; | 29 import 'package:analyzer_cli/src/error_formatter.dart'; |
30 import 'package:analyzer_cli/src/options.dart'; | 30 import 'package:analyzer_cli/src/options.dart'; |
31 import 'package:protobuf/protobuf.dart'; | 31 import 'package:bazel_worker/bazel_worker.dart'; |
32 | |
33 import 'message_grouper.dart'; | |
34 import 'worker_protocol.pb.dart'; | |
35 | 32 |
36 /** | 33 /** |
37 * Analyzer used when the "--build-mode" option is supplied. | 34 * Analyzer used when the "--build-mode" option is supplied. |
38 */ | 35 */ |
39 class BuildMode { | 36 class BuildMode { |
40 final CommandLineOptions options; | 37 final CommandLineOptions options; |
41 final AnalysisStats stats; | 38 final AnalysisStats stats; |
42 | 39 |
43 final ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE; | 40 final ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE; |
44 SummaryDataStore summaryDataStore; | 41 SummaryDataStore summaryDataStore; |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 } | 265 } |
269 Uri uri = Uri.parse(sourceFile.substring(0, pipeIndex)); | 266 Uri uri = Uri.parse(sourceFile.substring(0, pipeIndex)); |
270 String path = sourceFile.substring(pipeIndex + 1); | 267 String path = sourceFile.substring(pipeIndex + 1); |
271 uriToFileMap[uri] = new JavaFile(path); | 268 uriToFileMap[uri] = new JavaFile(path); |
272 } | 269 } |
273 return uriToFileMap; | 270 return uriToFileMap; |
274 } | 271 } |
275 } | 272 } |
276 | 273 |
277 /** | 274 /** |
278 * Default implementation of [WorkerConnection] that works with stdio. | |
279 */ | |
280 class StdWorkerConnection implements WorkerConnection { | |
281 final MessageGrouper _messageGrouper; | |
282 final io.Stdout _stdoutStream; | |
283 | |
284 StdWorkerConnection(io.Stdin stdinStream, this._stdoutStream) | |
285 : _messageGrouper = new MessageGrouper(stdinStream); | |
286 | |
287 @override | |
288 WorkRequest readRequest() { | |
289 var buffer = _messageGrouper.next; | |
290 if (buffer == null) return null; | |
291 | |
292 return new WorkRequest.fromBuffer(buffer); | |
293 } | |
294 | |
295 @override | |
296 void writeResponse(WorkResponse response) { | |
297 var responseBuffer = response.writeToBuffer(); | |
298 | |
299 var writer = new CodedBufferWriter(); | |
300 writer.writeInt32NoTag(responseBuffer.length); | |
301 writer.writeRawBytes(responseBuffer); | |
302 | |
303 _stdoutStream.add(writer.toBuffer()); | |
304 } | |
305 } | |
306 | |
307 /** | |
308 * Connection between a worker and input / output. | |
309 */ | |
310 abstract class WorkerConnection { | |
311 /** | |
312 * Read a new [WorkRequest]. Returns [null] when there are no more requests. | |
313 */ | |
314 WorkRequest readRequest(); | |
315 | |
316 /** | |
317 * Write the given [response] as bytes to the output. | |
318 */ | |
319 void writeResponse(WorkResponse response); | |
320 } | |
321 | |
322 /** | |
323 * Persistent Bazel worker. | 275 * Persistent Bazel worker. |
324 */ | 276 */ |
325 class WorkerLoop { | 277 class AnalyzerWorkerLoop extends SyncWorkerLoop { |
326 static const int EXIT_CODE_OK = 0; | |
327 static const int EXIT_CODE_ERROR = 15; | |
328 | |
329 final WorkerConnection connection; | |
330 | |
331 final StringBuffer errorBuffer = new StringBuffer(); | 278 final StringBuffer errorBuffer = new StringBuffer(); |
332 final StringBuffer outBuffer = new StringBuffer(); | 279 final StringBuffer outBuffer = new StringBuffer(); |
333 | 280 |
334 final String dartSdkPath; | 281 final String dartSdkPath; |
335 | 282 |
336 WorkerLoop(this.connection, {this.dartSdkPath}); | 283 AnalyzerWorkerLoop(SyncWorkerConnection connection, {this.dartSdkPath}) |
| 284 : super(connection: connection); |
337 | 285 |
338 factory WorkerLoop.std( | 286 factory AnalyzerWorkerLoop.std( |
339 {io.Stdin stdinStream, io.Stdout stdoutStream, String dartSdkPath}) { | 287 {io.Stdin stdinStream, io.Stdout stdoutStream, String dartSdkPath}) { |
340 stdinStream ??= io.stdin; | 288 SyncWorkerConnection connection = new StdSyncWorkerConnection( |
341 stdoutStream ??= io.stdout; | 289 stdinStream: stdinStream, stdoutStream: stdoutStream); |
342 WorkerConnection connection = | 290 return new AnalyzerWorkerLoop(connection, dartSdkPath: dartSdkPath); |
343 new StdWorkerConnection(stdinStream, stdoutStream); | |
344 return new WorkerLoop(connection, dartSdkPath: dartSdkPath); | |
345 } | 291 } |
346 | 292 |
347 /** | 293 /** |
348 * Performs analysis with given [options]. | 294 * Performs analysis with given [options]. |
349 */ | 295 */ |
350 void analyze(CommandLineOptions options) { | 296 void analyze(CommandLineOptions options) { |
351 options.dartSdkPath ??= dartSdkPath; | 297 options.dartSdkPath ??= dartSdkPath; |
352 new BuildMode(options, new AnalysisStats()).analyze(); | 298 new BuildMode(options, new AnalysisStats()).analyze(); |
353 } | 299 } |
354 | 300 |
355 /** | 301 /** |
356 * Perform a single loop step. Return `true` if should exit the loop. | 302 * Perform a single loop step. |
357 */ | 303 */ |
358 bool performSingle() { | 304 WorkResponse performRequest(WorkRequest request) { |
| 305 errorBuffer.clear(); |
| 306 outBuffer.clear(); |
359 try { | 307 try { |
360 WorkRequest request = connection.readRequest(); | |
361 if (request == null) { | |
362 return true; | |
363 } | |
364 // Prepare options. | 308 // Prepare options. |
365 CommandLineOptions options = | 309 CommandLineOptions options = |
366 CommandLineOptions.parse(request.arguments, (String msg) { | 310 CommandLineOptions.parse(request.arguments, (String msg) { |
367 throw new ArgumentError(msg); | 311 throw new ArgumentError(msg); |
368 }); | 312 }); |
369 // Analyze and respond. | 313 // Analyze and respond. |
370 analyze(options); | 314 analyze(options); |
371 String msg = _getErrorOutputBuffersText(); | 315 String msg = _getErrorOutputBuffersText(); |
372 connection.writeResponse(new WorkResponse() | 316 return new WorkResponse() |
373 ..exitCode = EXIT_CODE_OK | 317 ..exitCode = EXIT_CODE_OK |
374 ..output = msg); | 318 ..output = msg; |
375 } catch (e, st) { | 319 } catch (e, st) { |
376 String msg = _getErrorOutputBuffersText(); | 320 String msg = _getErrorOutputBuffersText(); |
377 msg += '$e \n $st'; | 321 msg += '$e\n$st'; |
378 connection.writeResponse(new WorkResponse() | 322 return new WorkResponse() |
379 ..exitCode = EXIT_CODE_ERROR | 323 ..exitCode = EXIT_CODE_ERROR |
380 ..output = msg); | 324 ..output = msg; |
381 } | 325 } |
382 return false; | |
383 } | 326 } |
384 | 327 |
385 /** | 328 /** |
386 * Run the worker loop. | 329 * Run the worker loop. |
387 */ | 330 */ |
| 331 @override |
388 void run() { | 332 void run() { |
389 errorSink = errorBuffer; | 333 errorSink = errorBuffer; |
390 outSink = outBuffer; | 334 outSink = outBuffer; |
391 exitHandler = (int exitCode) { | 335 exitHandler = (int exitCode) { |
392 return throw new StateError('Exit called: $exitCode'); | 336 return throw new StateError('Exit called: $exitCode'); |
393 }; | 337 }; |
394 while (true) { | 338 super.run(); |
395 errorBuffer.clear(); | |
396 outBuffer.clear(); | |
397 bool shouldExit = performSingle(); | |
398 if (shouldExit) { | |
399 break; | |
400 } | |
401 } | |
402 } | 339 } |
403 | 340 |
404 String _getErrorOutputBuffersText() { | 341 String _getErrorOutputBuffersText() { |
405 String msg = ''; | 342 String msg = ''; |
406 if (errorBuffer.isNotEmpty) { | 343 if (errorBuffer.isNotEmpty) { |
407 msg += errorBuffer.toString() + '\n'; | 344 msg += errorBuffer.toString() + '\n'; |
408 } | 345 } |
409 if (outBuffer.isNotEmpty) { | 346 if (outBuffer.isNotEmpty) { |
410 msg += outBuffer.toString() + '\n'; | 347 msg += outBuffer.toString() + '\n'; |
411 } | 348 } |
412 return msg; | 349 return msg; |
413 } | 350 } |
414 } | 351 } |
OLD | NEW |