OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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:typed_data'; | 7 import 'dart:typed_data'; |
8 | 8 |
9 import 'package:analyzer/context/context_root.dart'; | 9 import 'package:analyzer/context/context_root.dart'; |
10 import 'package:analyzer/context/declared_variables.dart'; | 10 import 'package:analyzer/context/declared_variables.dart'; |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 /** | 313 /** |
314 * Return the stream that produces [ExceptionResult]s. | 314 * Return the stream that produces [ExceptionResult]s. |
315 */ | 315 */ |
316 Stream<ExceptionResult> get exceptions => _exceptionController.stream; | 316 Stream<ExceptionResult> get exceptions => _exceptionController.stream; |
317 | 317 |
318 /** | 318 /** |
319 * The current file system state. | 319 * The current file system state. |
320 */ | 320 */ |
321 FileSystemState get fsState => _fsState; | 321 FileSystemState get fsState => _fsState; |
322 | 322 |
323 /** | 323 @override |
324 * Return `true` if the driver has a file to analyze. | |
325 */ | |
326 bool get hasFilesToAnalyze { | 324 bool get hasFilesToAnalyze { |
327 return _fileTracker.hasChangedFiles || | 325 return _fileTracker.hasChangedFiles || |
328 _requestedFiles.isNotEmpty || | 326 _requestedFiles.isNotEmpty || |
329 _requestedParts.isNotEmpty || | 327 _requestedParts.isNotEmpty || |
330 _fileTracker.hasPendingFiles || | 328 _fileTracker.hasPendingFiles || |
331 _partsToAnalyze.isNotEmpty; | 329 _partsToAnalyze.isNotEmpty; |
332 } | 330 } |
333 | 331 |
334 /** | 332 /** |
335 * Return the set of files that are known at this moment. This set does not | 333 * Return the set of files that are known at this moment. This set does not |
(...skipping 10 matching lines...) Expand all Loading... |
346 /** | 344 /** |
347 * Return the number of files scheduled for analysis. | 345 * Return the number of files scheduled for analysis. |
348 */ | 346 */ |
349 int get numberOfFilesToAnalyze => _fileTracker.numberOfPendingFiles; | 347 int get numberOfFilesToAnalyze => _fileTracker.numberOfPendingFiles; |
350 | 348 |
351 /** | 349 /** |
352 * Return the list of files that the driver should try to analyze sooner. | 350 * Return the list of files that the driver should try to analyze sooner. |
353 */ | 351 */ |
354 List<String> get priorityFiles => _priorityFiles.toList(growable: false); | 352 List<String> get priorityFiles => _priorityFiles.toList(growable: false); |
355 | 353 |
356 /** | 354 @override |
357 * Set the list of files that the driver should try to analyze sooner. | |
358 * | |
359 * Every path in the list must be absolute and normalized. | |
360 * | |
361 * The driver will produce the results through the [results] stream. The | |
362 * exact order in which results are produced is not defined, neither | |
363 * between priority files, nor between priority and non-priority files. | |
364 */ | |
365 void set priorityFiles(List<String> priorityPaths) { | 355 void set priorityFiles(List<String> priorityPaths) { |
366 _priorityResults.keys | 356 _priorityResults.keys |
367 .toSet() | 357 .toSet() |
368 .difference(priorityPaths.toSet()) | 358 .difference(priorityPaths.toSet()) |
369 .forEach(_priorityResults.remove); | 359 .forEach(_priorityResults.remove); |
370 _priorityFiles.clear(); | 360 _priorityFiles.clear(); |
371 _priorityFiles.addAll(priorityPaths); | 361 _priorityFiles.addAll(priorityPaths); |
372 _scheduler.notify(this); | 362 _scheduler.notify(this); |
373 } | 363 } |
374 | 364 |
(...skipping 28 matching lines...) Expand all Loading... |
403 | 393 |
404 /** | 394 /** |
405 * Return the source factory used to resolve URIs to paths and restore URIs | 395 * Return the source factory used to resolve URIs to paths and restore URIs |
406 * from file paths. | 396 * from file paths. |
407 */ | 397 */ |
408 SourceFactory get sourceFactory => _sourceFactory; | 398 SourceFactory get sourceFactory => _sourceFactory; |
409 | 399 |
410 @visibleForTesting | 400 @visibleForTesting |
411 AnalysisDriverTestView get test => _testView; | 401 AnalysisDriverTestView get test => _testView; |
412 | 402 |
413 /** | 403 @override |
414 * Return the priority of work that the driver needs to perform. | |
415 */ | |
416 AnalysisDriverPriority get workPriority { | 404 AnalysisDriverPriority get workPriority { |
417 if (_requestedFiles.isNotEmpty) { | 405 if (_requestedFiles.isNotEmpty) { |
418 return AnalysisDriverPriority.interactive; | 406 return AnalysisDriverPriority.interactive; |
419 } | 407 } |
420 if (_definingClassMemberNameTasks.isNotEmpty || | 408 if (_definingClassMemberNameTasks.isNotEmpty || |
421 _referencingNameTasks.isNotEmpty) { | 409 _referencingNameTasks.isNotEmpty) { |
422 return AnalysisDriverPriority.interactive; | 410 return AnalysisDriverPriority.interactive; |
423 } | 411 } |
424 if (_indexRequestedFiles.isNotEmpty) { | 412 if (_indexRequestedFiles.isNotEmpty) { |
425 return AnalysisDriverPriority.interactive; | 413 return AnalysisDriverPriority.interactive; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
514 _analysisOptions = analysisOptions; | 502 _analysisOptions = analysisOptions; |
515 } | 503 } |
516 if (sourceFactory != null) { | 504 if (sourceFactory != null) { |
517 _sourceFactory = sourceFactory; | 505 _sourceFactory = sourceFactory; |
518 } | 506 } |
519 Iterable<String> addedFiles = _fileTracker.addedFiles; | 507 Iterable<String> addedFiles = _fileTracker.addedFiles; |
520 _createFileTracker(); | 508 _createFileTracker(); |
521 _fileTracker.addFiles(addedFiles); | 509 _fileTracker.addFiles(addedFiles); |
522 } | 510 } |
523 | 511 |
524 /** | 512 @override |
525 * Notify the driver that the client is going to stop using it. | |
526 */ | |
527 void dispose() { | 513 void dispose() { |
528 _scheduler._remove(this); | 514 _scheduler.remove(this); |
529 } | 515 } |
530 | 516 |
531 /** | 517 /** |
532 * Return a [Future] that completes with the [ErrorsResult] for the Dart | 518 * Return a [Future] that completes with the [ErrorsResult] for the Dart |
533 * file with the given [path]. If the file is not a Dart file or cannot | 519 * file with the given [path]. If the file is not a Dart file or cannot |
534 * be analyzed, the [Future] completes with `null`. | 520 * be analyzed, the [Future] completes with `null`. |
535 * | 521 * |
536 * The [path] must be absolute and normalized. | 522 * The [path] must be absolute and normalized. |
537 * | 523 * |
538 * This method does not use analysis priorities, and must not be used in | 524 * This method does not use analysis priorities, and must not be used in |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 * resolved unit). | 732 * resolved unit). |
747 */ | 733 */ |
748 Future<ParseResult> parseFile(String path) async { | 734 Future<ParseResult> parseFile(String path) async { |
749 FileState file = _fileTracker.verifyApiSignature(path); | 735 FileState file = _fileTracker.verifyApiSignature(path); |
750 RecordingErrorListener listener = new RecordingErrorListener(); | 736 RecordingErrorListener listener = new RecordingErrorListener(); |
751 CompilationUnit unit = file.parse(listener); | 737 CompilationUnit unit = file.parse(listener); |
752 return new ParseResult(file.path, file.uri, file.content, file.contentHash, | 738 return new ParseResult(file.path, file.uri, file.content, file.contentHash, |
753 unit.lineInfo, unit, listener.errors); | 739 unit.lineInfo, unit, listener.errors); |
754 } | 740 } |
755 | 741 |
756 /** | 742 @override |
757 * Perform a single chunk of work and produce [results]. | |
758 */ | |
759 Future<Null> performWork() async { | 743 Future<Null> performWork() async { |
760 if (_fileTracker.verifyChangedFilesIfNeeded()) { | 744 if (_fileTracker.verifyChangedFilesIfNeeded()) { |
761 return; | 745 return; |
762 } | 746 } |
763 | 747 |
764 // Analyze a requested file. | 748 // Analyze a requested file. |
765 if (_requestedFiles.isNotEmpty) { | 749 if (_requestedFiles.isNotEmpty) { |
766 String path = _requestedFiles.keys.first; | 750 String path = _requestedFiles.keys.first; |
767 try { | 751 try { |
768 AnalysisResult result = _computeAnalysisResult(path, withUnit: true); | 752 AnalysisResult result = _computeAnalysisResult(path, withUnit: true); |
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1341 * a temporary measure until the official plugin API is ready (and a different | 1325 * a temporary measure until the official plugin API is ready (and a different |
1342 * scheduler is used) | 1326 * scheduler is used) |
1343 */ | 1327 */ |
1344 abstract class AnalysisDriverGeneric { | 1328 abstract class AnalysisDriverGeneric { |
1345 /** | 1329 /** |
1346 * Return `true` if the driver has a file to analyze. | 1330 * Return `true` if the driver has a file to analyze. |
1347 */ | 1331 */ |
1348 bool get hasFilesToAnalyze; | 1332 bool get hasFilesToAnalyze; |
1349 | 1333 |
1350 /** | 1334 /** |
| 1335 * Set the list of files that the driver should try to analyze sooner. |
| 1336 * |
| 1337 * Every path in the list must be absolute and normalized. |
| 1338 * |
| 1339 * The driver will produce the results through the [results] stream. The |
| 1340 * exact order in which results are produced is not defined, neither |
| 1341 * between priority files, nor between priority and non-priority files. |
| 1342 */ |
| 1343 void set priorityFiles(List<String> priorityPaths); |
| 1344 |
| 1345 /** |
1351 * Return the priority of work that the driver needs to perform. | 1346 * Return the priority of work that the driver needs to perform. |
1352 */ | 1347 */ |
1353 AnalysisDriverPriority get workPriority; | 1348 AnalysisDriverPriority get workPriority; |
1354 | 1349 |
1355 /** | 1350 /** |
| 1351 * Notify the driver that the client is going to stop using it. |
| 1352 */ |
| 1353 void dispose(); |
| 1354 |
| 1355 /** |
1356 * Perform a single chunk of work and produce [results]. | 1356 * Perform a single chunk of work and produce [results]. |
1357 */ | 1357 */ |
1358 Future<Null> performWork(); | 1358 Future<Null> performWork(); |
1359 } | 1359 } |
1360 | 1360 |
1361 /** | 1361 /** |
1362 * Priorities of [AnalysisDriver] work. The farther a priority to the beginning | 1362 * Priorities of [AnalysisDriver] work. The farther a priority to the beginning |
1363 * of the list, the earlier the corresponding [AnalysisDriver] should be asked | 1363 * of the list, the earlier the corresponding [AnalysisDriver] should be asked |
1364 * to perform work. | 1364 * to perform work. |
1365 */ | 1365 */ |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1451 /** | 1451 /** |
1452 * Notify that there is a change to the [driver], it it might need to | 1452 * Notify that there is a change to the [driver], it it might need to |
1453 * perform some work. | 1453 * perform some work. |
1454 */ | 1454 */ |
1455 void notify(AnalysisDriverGeneric driver) { | 1455 void notify(AnalysisDriverGeneric driver) { |
1456 _hasWork.notify(); | 1456 _hasWork.notify(); |
1457 _statusSupport.preTransitionToAnalyzing(); | 1457 _statusSupport.preTransitionToAnalyzing(); |
1458 } | 1458 } |
1459 | 1459 |
1460 /** | 1460 /** |
| 1461 * Remove the given [driver] from the scheduler, so that it will not be |
| 1462 * asked to perform any new work. |
| 1463 */ |
| 1464 void remove(AnalysisDriverGeneric driver) { |
| 1465 if (driver is AnalysisDriver) { |
| 1466 driverWatcher?.removedDriver(driver); |
| 1467 } |
| 1468 _drivers.remove(driver); |
| 1469 _hasWork.notify(); |
| 1470 } |
| 1471 |
| 1472 /** |
1461 * Start the scheduler, so that any [AnalysisDriver] created before or | 1473 * Start the scheduler, so that any [AnalysisDriver] created before or |
1462 * after will be asked to perform work. | 1474 * after will be asked to perform work. |
1463 */ | 1475 */ |
1464 void start() { | 1476 void start() { |
1465 if (_started) { | 1477 if (_started) { |
1466 throw new StateError('The scheduler has already been started.'); | 1478 throw new StateError('The scheduler has already been started.'); |
1467 } | 1479 } |
1468 _started = true; | 1480 _started = true; |
1469 _run(); | 1481 _run(); |
1470 } | 1482 } |
1471 | 1483 |
1472 /** | 1484 /** |
1473 * Return a future that will be completed the next time the status is idle. | 1485 * Return a future that will be completed the next time the status is idle. |
1474 * | 1486 * |
1475 * If the status is currently idle, the returned future will be signaled | 1487 * If the status is currently idle, the returned future will be signaled |
1476 * immediately. | 1488 * immediately. |
1477 */ | 1489 */ |
1478 Future<Null> waitForIdle() => _statusSupport.waitForIdle(); | 1490 Future<Null> waitForIdle() => _statusSupport.waitForIdle(); |
1479 | 1491 |
1480 /** | 1492 /** |
1481 * Remove the given [driver] from the scheduler, so that it will not be | |
1482 * asked to perform any new work. | |
1483 */ | |
1484 void _remove(AnalysisDriverGeneric driver) { | |
1485 if (driver is AnalysisDriver) { | |
1486 driverWatcher?.removedDriver(driver); | |
1487 } | |
1488 | |
1489 _drivers.remove(driver); | |
1490 _hasWork.notify(); | |
1491 } | |
1492 | |
1493 /** | |
1494 * Run infinitely analysis cycle, selecting the drivers with the highest | 1493 * Run infinitely analysis cycle, selecting the drivers with the highest |
1495 * priority first. | 1494 * priority first. |
1496 */ | 1495 */ |
1497 Future<Null> _run() async { | 1496 Future<Null> _run() async { |
1498 Stopwatch timer = new Stopwatch()..start(); | 1497 Stopwatch timer = new Stopwatch()..start(); |
1499 PerformanceLogSection analysisSection; | 1498 PerformanceLogSection analysisSection; |
1500 while (true) { | 1499 while (true) { |
1501 // Pump the event queue. | 1500 // Pump the event queue. |
1502 if (timer.elapsedMilliseconds > _MS_BEFORE_PUMPING_EVENT_QUEUE) { | 1501 if (timer.elapsedMilliseconds > _MS_BEFORE_PUMPING_EVENT_QUEUE) { |
1503 await _pumpEventQueue(_NUMBER_OF_EVENT_QUEUE_PUMPINGS); | 1502 await _pumpEventQueue(_NUMBER_OF_EVENT_QUEUE_PUMPINGS); |
(...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2101 libraryDeclarations.add(new TopLevelDeclarationInSource( | 2100 libraryDeclarations.add(new TopLevelDeclarationInSource( |
2102 file.source, declaration, isExported)); | 2101 file.source, declaration, isExported)); |
2103 } | 2102 } |
2104 } | 2103 } |
2105 } | 2104 } |
2106 | 2105 |
2107 // We're not done yet. | 2106 // We're not done yet. |
2108 return false; | 2107 return false; |
2109 } | 2108 } |
2110 } | 2109 } |
OLD | NEW |