| 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/declared_variables.dart'; | 9 import 'package:analyzer/context/declared_variables.dart'; |
| 10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 */ | 153 */ |
| 154 final _priorityFiles = new LinkedHashSet<String>(); | 154 final _priorityFiles = new LinkedHashSet<String>(); |
| 155 | 155 |
| 156 /** | 156 /** |
| 157 * The mapping from the files for which analysis was requested using | 157 * The mapping from the files for which analysis was requested using |
| 158 * [getResult] to the [Completer]s to report the result. | 158 * [getResult] to the [Completer]s to report the result. |
| 159 */ | 159 */ |
| 160 final _requestedFiles = <String, List<Completer<AnalysisResult>>>{}; | 160 final _requestedFiles = <String, List<Completer<AnalysisResult>>>{}; |
| 161 | 161 |
| 162 /** | 162 /** |
| 163 * The list of tasks to compute files defining a class member name. |
| 164 */ |
| 165 final _definingClassMemberNameTasks = <_FilesDefiningClassMemberNameTask>[]; |
| 166 |
| 167 /** |
| 163 * The list of tasks to compute files referencing a name. | 168 * The list of tasks to compute files referencing a name. |
| 164 */ | 169 */ |
| 165 final _referencingNameTasks = <_FilesReferencingNameTask>[]; | 170 final _referencingNameTasks = <_FilesReferencingNameTask>[]; |
| 166 | 171 |
| 167 /** | 172 /** |
| 168 * The list of tasks to compute top-level declarations of a name. | 173 * The list of tasks to compute top-level declarations of a name. |
| 169 */ | 174 */ |
| 170 final _topLevelNameDeclarationsTasks = <_TopLevelNameDeclarationsTask>[]; | 175 final _topLevelNameDeclarationsTasks = <_TopLevelNameDeclarationsTask>[]; |
| 171 | 176 |
| 172 /** | 177 /** |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 @visibleForTesting | 365 @visibleForTesting |
| 361 AnalysisDriverTestView get test => _testView; | 366 AnalysisDriverTestView get test => _testView; |
| 362 | 367 |
| 363 /** | 368 /** |
| 364 * Return the priority of work that the driver needs to perform. | 369 * Return the priority of work that the driver needs to perform. |
| 365 */ | 370 */ |
| 366 AnalysisDriverPriority get _workPriority { | 371 AnalysisDriverPriority get _workPriority { |
| 367 if (_requestedFiles.isNotEmpty) { | 372 if (_requestedFiles.isNotEmpty) { |
| 368 return AnalysisDriverPriority.interactive; | 373 return AnalysisDriverPriority.interactive; |
| 369 } | 374 } |
| 370 if (_referencingNameTasks.isNotEmpty) { | 375 if (_definingClassMemberNameTasks.isNotEmpty || |
| 376 _referencingNameTasks.isNotEmpty) { |
| 371 return AnalysisDriverPriority.interactive; | 377 return AnalysisDriverPriority.interactive; |
| 372 } | 378 } |
| 373 if (_indexRequestedFiles.isNotEmpty) { | 379 if (_indexRequestedFiles.isNotEmpty) { |
| 374 return AnalysisDriverPriority.interactive; | 380 return AnalysisDriverPriority.interactive; |
| 375 } | 381 } |
| 376 if (_unitElementRequestedFiles.isNotEmpty) { | 382 if (_unitElementRequestedFiles.isNotEmpty) { |
| 377 return AnalysisDriverPriority.interactive; | 383 return AnalysisDriverPriority.interactive; |
| 378 } | 384 } |
| 379 if (_topLevelNameDeclarationsTasks.isNotEmpty) { | 385 if (_topLevelNameDeclarationsTasks.isNotEmpty) { |
| 380 return AnalysisDriverPriority.interactive; | 386 return AnalysisDriverPriority.interactive; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 return new ErrorsResult( | 504 return new ErrorsResult( |
| 499 path, | 505 path, |
| 500 analysisResult.uri, | 506 analysisResult.uri, |
| 501 analysisResult.contentHash, | 507 analysisResult.contentHash, |
| 502 analysisResult.lineInfo, | 508 analysisResult.lineInfo, |
| 503 analysisResult.errors); | 509 analysisResult.errors); |
| 504 } | 510 } |
| 505 | 511 |
| 506 /** | 512 /** |
| 507 * Return a [Future] that completes with the list of added files that | 513 * Return a [Future] that completes with the list of added files that |
| 514 * define a class member with the given [name]. |
| 515 */ |
| 516 Future<List<String>> getFilesDefiningClassMemberName(String name) { |
| 517 var task = new _FilesDefiningClassMemberNameTask(this, name); |
| 518 _definingClassMemberNameTasks.add(task); |
| 519 _scheduler._notify(this); |
| 520 return task.completer.future; |
| 521 } |
| 522 |
| 523 /** |
| 524 * Return a [Future] that completes with the list of added files that |
| 508 * reference the given external [name]. | 525 * reference the given external [name]. |
| 509 */ | 526 */ |
| 510 Future<List<String>> getFilesReferencingName(String name) { | 527 Future<List<String>> getFilesReferencingName(String name) { |
| 511 var task = new _FilesReferencingNameTask(this, name); | 528 var task = new _FilesReferencingNameTask(this, name); |
| 512 _referencingNameTasks.add(task); | 529 _referencingNameTasks.add(task); |
| 513 _scheduler._notify(this); | 530 _scheduler._notify(this); |
| 514 return task.completer.future; | 531 return task.completer.future; |
| 515 } | 532 } |
| 516 | 533 |
| 517 /** | 534 /** |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 931 // Process a unit request. | 948 // Process a unit request. |
| 932 if (_unitElementRequestedFiles.isNotEmpty) { | 949 if (_unitElementRequestedFiles.isNotEmpty) { |
| 933 String path = _unitElementRequestedFiles.keys.first; | 950 String path = _unitElementRequestedFiles.keys.first; |
| 934 CompilationUnitElement unitElement = _computeUnitElement(path); | 951 CompilationUnitElement unitElement = _computeUnitElement(path); |
| 935 _unitElementRequestedFiles.remove(path).forEach((completer) { | 952 _unitElementRequestedFiles.remove(path).forEach((completer) { |
| 936 completer.complete(unitElement); | 953 completer.complete(unitElement); |
| 937 }); | 954 }); |
| 938 return; | 955 return; |
| 939 } | 956 } |
| 940 | 957 |
| 958 // Compute files defining a name. |
| 959 if (_definingClassMemberNameTasks.isNotEmpty) { |
| 960 _FilesDefiningClassMemberNameTask task = |
| 961 _definingClassMemberNameTasks.first; |
| 962 bool isDone = await task.perform(); |
| 963 if (isDone) { |
| 964 _definingClassMemberNameTasks.remove(task); |
| 965 } |
| 966 return; |
| 967 } |
| 968 |
| 941 // Compute files referencing a name. | 969 // Compute files referencing a name. |
| 942 if (_referencingNameTasks.isNotEmpty) { | 970 if (_referencingNameTasks.isNotEmpty) { |
| 943 _FilesReferencingNameTask task = _referencingNameTasks.first; | 971 _FilesReferencingNameTask task = _referencingNameTasks.first; |
| 944 bool isDone = await task.perform(); | 972 bool isDone = await task.perform(); |
| 945 if (isDone) { | 973 if (isDone) { |
| 946 _referencingNameTasks.remove(task); | 974 _referencingNameTasks.remove(task); |
| 947 } | 975 } |
| 948 return; | 976 return; |
| 949 } | 977 } |
| 950 | 978 |
| (...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1595 final String contextKey; | 1623 final String contextKey; |
| 1596 | 1624 |
| 1597 _ExceptionState(this.exception, this.stackTrace, this.contextKey); | 1625 _ExceptionState(this.exception, this.stackTrace, this.contextKey); |
| 1598 | 1626 |
| 1599 @override | 1627 @override |
| 1600 String toString() => '$exception\n$stackTrace'; | 1628 String toString() => '$exception\n$stackTrace'; |
| 1601 } | 1629 } |
| 1602 | 1630 |
| 1603 /** | 1631 /** |
| 1604 * Task that computes the list of files that were added to the driver and | 1632 * Task that computes the list of files that were added to the driver and |
| 1633 * declare a class member with the given [name]. |
| 1634 */ |
| 1635 class _FilesDefiningClassMemberNameTask { |
| 1636 static const int _MS_WORK_INTERVAL = 5; |
| 1637 |
| 1638 final AnalysisDriver driver; |
| 1639 final String name; |
| 1640 final Completer<List<String>> completer = new Completer<List<String>>(); |
| 1641 |
| 1642 final List<String> definingFiles = <String>[]; |
| 1643 final Set<String> checkedFiles = new Set<String>(); |
| 1644 final List<String> filesToCheck = <String>[]; |
| 1645 |
| 1646 _FilesDefiningClassMemberNameTask(this.driver, this.name); |
| 1647 |
| 1648 /** |
| 1649 * Perform work for a fixed length of time, and complete the [completer] to |
| 1650 * either return `true` to indicate that the task is done, or return `false` |
| 1651 * to indicate that the task should continue to be run. |
| 1652 * |
| 1653 * Each invocation of an asynchronous method has overhead, which looks as |
| 1654 * `_SyncCompleter.complete` invocation, we see as much as 62% in some |
| 1655 * scenarios. Instead we use a fixed length of time, so we can spend less time |
| 1656 * overall and keep quick enough response time. |
| 1657 */ |
| 1658 Future<bool> perform() async { |
| 1659 Stopwatch timer = new Stopwatch()..start(); |
| 1660 while (timer.elapsedMilliseconds < _MS_WORK_INTERVAL) { |
| 1661 // Prepare files to check. |
| 1662 if (filesToCheck.isEmpty) { |
| 1663 Set<String> newFiles = driver.addedFiles.difference(checkedFiles); |
| 1664 filesToCheck.addAll(newFiles); |
| 1665 } |
| 1666 |
| 1667 // If no more files to check, complete and done. |
| 1668 if (filesToCheck.isEmpty) { |
| 1669 completer.complete(definingFiles); |
| 1670 return true; |
| 1671 } |
| 1672 |
| 1673 // Check the next file. |
| 1674 String path = filesToCheck.removeLast(); |
| 1675 FileState file = driver._fsState.getFileForPath(path); |
| 1676 if (file.definedClassMemberNames.contains(name)) { |
| 1677 definingFiles.add(path); |
| 1678 } |
| 1679 checkedFiles.add(path); |
| 1680 } |
| 1681 |
| 1682 // We're not done yet. |
| 1683 return false; |
| 1684 } |
| 1685 } |
| 1686 |
| 1687 /** |
| 1688 * Task that computes the list of files that were added to the driver and |
| 1605 * have at least one reference to an identifier [name] defined outside of the | 1689 * have at least one reference to an identifier [name] defined outside of the |
| 1606 * file. | 1690 * file. |
| 1607 */ | 1691 */ |
| 1608 class _FilesReferencingNameTask { | 1692 class _FilesReferencingNameTask { |
| 1609 static const int _MS_WORK_INTERVAL = 5; | 1693 static const int _MS_WORK_INTERVAL = 5; |
| 1610 | 1694 |
| 1611 final AnalysisDriver driver; | 1695 final AnalysisDriver driver; |
| 1612 final String name; | 1696 final String name; |
| 1613 final Completer<List<String>> completer = new Completer<List<String>>(); | 1697 final Completer<List<String>> completer = new Completer<List<String>>(); |
| 1614 | 1698 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1710 libraryDeclarations.add(new TopLevelDeclarationInSource( | 1794 libraryDeclarations.add(new TopLevelDeclarationInSource( |
| 1711 file.source, declaration, isExported)); | 1795 file.source, declaration, isExported)); |
| 1712 } | 1796 } |
| 1713 } | 1797 } |
| 1714 } | 1798 } |
| 1715 | 1799 |
| 1716 // We're not done yet. | 1800 // We're not done yet. |
| 1717 return false; | 1801 return false; |
| 1718 } | 1802 } |
| 1719 } | 1803 } |
| OLD | NEW |