Chromium Code Reviews| 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/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/element/element.dart' show CompilationUnitElement; | 10 import 'package:analyzer/dart/element/element.dart' show CompilationUnitElement; |
| 11 import 'package:analyzer/error/error.dart'; | 11 import 'package:analyzer/error/error.dart'; |
| 12 import 'package:analyzer/error/listener.dart'; | 12 import 'package:analyzer/error/listener.dart'; |
| 13 import 'package:analyzer/file_system/file_system.dart'; | 13 import 'package:analyzer/file_system/file_system.dart'; |
| 14 import 'package:analyzer/src/context/context.dart'; | 14 import 'package:analyzer/src/context/context.dart'; |
| 15 import 'package:analyzer/src/dart/analysis/byte_store.dart'; | 15 import 'package:analyzer/src/dart/analysis/byte_store.dart'; |
| 16 import 'package:analyzer/src/dart/analysis/file_state.dart'; | 16 import 'package:analyzer/src/dart/analysis/file_state.dart'; |
| 17 import 'package:analyzer/src/dart/analysis/index.dart'; | 17 import 'package:analyzer/src/dart/analysis/index.dart'; |
| 18 import 'package:analyzer/src/dart/analysis/search.dart'; | 18 import 'package:analyzer/src/dart/analysis/search.dart'; |
| 19 import 'package:analyzer/src/dart/analysis/status.dart'; | 19 import 'package:analyzer/src/dart/analysis/status.dart'; |
| 20 import 'package:analyzer/src/dart/analysis/top_level_declaration.dart'; | |
| 20 import 'package:analyzer/src/generated/engine.dart' | 21 import 'package:analyzer/src/generated/engine.dart' |
| 21 show AnalysisContext, AnalysisEngine, AnalysisOptions, ChangeSet; | 22 show AnalysisContext, AnalysisEngine, AnalysisOptions, ChangeSet; |
| 22 import 'package:analyzer/src/generated/source.dart'; | 23 import 'package:analyzer/src/generated/source.dart'; |
| 23 import 'package:analyzer/src/summary/api_signature.dart'; | 24 import 'package:analyzer/src/summary/api_signature.dart'; |
| 24 import 'package:analyzer/src/summary/format.dart'; | 25 import 'package:analyzer/src/summary/format.dart'; |
| 25 import 'package:analyzer/src/summary/idl.dart'; | 26 import 'package:analyzer/src/summary/idl.dart'; |
| 26 import 'package:analyzer/src/summary/link.dart'; | 27 import 'package:analyzer/src/summary/link.dart'; |
| 27 import 'package:analyzer/src/summary/package_bundle_reader.dart'; | 28 import 'package:analyzer/src/summary/package_bundle_reader.dart'; |
| 28 import 'package:analyzer/src/task/dart.dart' show COMPILATION_UNIT_ELEMENT; | 29 import 'package:analyzer/src/task/dart.dart' show COMPILATION_UNIT_ELEMENT; |
| 29 import 'package:analyzer/task/dart.dart' show LibrarySpecificUnit; | 30 import 'package:analyzer/task/dart.dart' show LibrarySpecificUnit; |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 * [getResult] to the [Completer]s to report the result. | 151 * [getResult] to the [Completer]s to report the result. |
| 151 */ | 152 */ |
| 152 final _requestedFiles = <String, List<Completer<AnalysisResult>>>{}; | 153 final _requestedFiles = <String, List<Completer<AnalysisResult>>>{}; |
| 153 | 154 |
| 154 /** | 155 /** |
| 155 * The list of tasks to compute files referencing a name. | 156 * The list of tasks to compute files referencing a name. |
| 156 */ | 157 */ |
| 157 final _referencingNameTasks = <_FilesReferencingNameTask>[]; | 158 final _referencingNameTasks = <_FilesReferencingNameTask>[]; |
| 158 | 159 |
| 159 /** | 160 /** |
| 161 * The list of tasks to compute top-level declarations. | |
| 162 */ | |
| 163 final _topLevelDeclarationsTasks = <_TopLevelLibraryDeclarationsTask>[]; | |
| 164 | |
| 165 /** | |
| 160 * The mapping from the files for which the index was requested using | 166 * The mapping from the files for which the index was requested using |
| 161 * [getIndex] to the [Completer]s to report the result. | 167 * [getIndex] to the [Completer]s to report the result. |
| 162 */ | 168 */ |
| 163 final _indexRequestedFiles = <String, List<Completer<IndexResult>>>{}; | 169 final _indexRequestedFiles = <String, List<Completer<IndexResult>>>{}; |
| 164 | 170 |
| 165 /** | 171 /** |
| 166 * The set of files were reported as changed through [changeFile] and not | 172 * The set of files were reported as changed through [changeFile] and not |
| 167 * checked for actual changes yet. | 173 * checked for actual changes yet. |
| 168 */ | 174 */ |
| 169 final _changedFiles = new LinkedHashSet<String>(); | 175 final _changedFiles = new LinkedHashSet<String>(); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 289 * Return the search support for the driver. | 295 * Return the search support for the driver. |
| 290 */ | 296 */ |
| 291 Search get search => _search; | 297 Search get search => _search; |
| 292 | 298 |
| 293 /** | 299 /** |
| 294 * Return the stream that produces [AnalysisStatus] events. | 300 * Return the stream that produces [AnalysisStatus] events. |
| 295 */ | 301 */ |
| 296 Stream<AnalysisStatus> get status => _statusSupport.stream; | 302 Stream<AnalysisStatus> get status => _statusSupport.stream; |
| 297 | 303 |
| 298 /** | 304 /** |
| 305 * Return a [Future] that completes with top-level declaration in all known | |
| 306 * libraries. | |
| 307 */ | |
| 308 Future<List<TopLevelLibraryDeclarations>> get topLevelLibraryDeclarations { | |
|
Paul Berry
2016/12/01 22:28:15
I'm concerned that this API forces the driver to c
scheglov
2016/12/02 17:19:12
That's a good idea.
Thank you.
We need to know ki
| |
| 309 var task = new _TopLevelLibraryDeclarationsTask(this); | |
| 310 _topLevelDeclarationsTasks.add(task); | |
| 311 _statusSupport.transitionToAnalyzing(); | |
| 312 _scheduler._notify(this); | |
| 313 return task.completer.future; | |
| 314 } | |
| 315 | |
| 316 /** | |
| 299 * Return the priority of work that the driver needs to perform. | 317 * Return the priority of work that the driver needs to perform. |
| 300 */ | 318 */ |
| 301 AnalysisDriverPriority get _workPriority { | 319 AnalysisDriverPriority get _workPriority { |
| 302 if (_requestedFiles.isNotEmpty) { | 320 if (_requestedFiles.isNotEmpty) { |
| 303 return AnalysisDriverPriority.interactive; | 321 return AnalysisDriverPriority.interactive; |
| 304 } | 322 } |
| 305 if (_referencingNameTasks.isNotEmpty) { | 323 if (_referencingNameTasks.isNotEmpty) { |
| 306 return AnalysisDriverPriority.referencingName; | 324 return AnalysisDriverPriority.interactive; |
| 307 } | 325 } |
| 308 if (_indexRequestedFiles.isNotEmpty) { | 326 if (_indexRequestedFiles.isNotEmpty) { |
| 309 return AnalysisDriverPriority.getIndex; | 327 return AnalysisDriverPriority.interactive; |
| 328 } | |
| 329 if (_topLevelDeclarationsTasks.isNotEmpty) { | |
| 330 return AnalysisDriverPriority.interactive; | |
| 310 } | 331 } |
| 311 if (_priorityFiles.isNotEmpty) { | 332 if (_priorityFiles.isNotEmpty) { |
| 312 for (String path in _priorityFiles) { | 333 for (String path in _priorityFiles) { |
| 313 if (_filesToAnalyze.contains(path)) { | 334 if (_filesToAnalyze.contains(path)) { |
| 314 return AnalysisDriverPriority.priority; | 335 return AnalysisDriverPriority.priority; |
| 315 } | 336 } |
| 316 } | 337 } |
| 317 } | 338 } |
| 318 if (_filesToAnalyze.isNotEmpty) { | 339 if (_filesToAnalyze.isNotEmpty) { |
| 319 return AnalysisDriverPriority.general; | 340 return AnalysisDriverPriority.general; |
| (...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 806 // Compute files referencing a name. | 827 // Compute files referencing a name. |
| 807 if (_referencingNameTasks.isNotEmpty) { | 828 if (_referencingNameTasks.isNotEmpty) { |
| 808 _FilesReferencingNameTask task = _referencingNameTasks.first; | 829 _FilesReferencingNameTask task = _referencingNameTasks.first; |
| 809 bool isDone = await task.perform(); | 830 bool isDone = await task.perform(); |
| 810 if (isDone) { | 831 if (isDone) { |
| 811 _referencingNameTasks.remove(task); | 832 _referencingNameTasks.remove(task); |
| 812 } | 833 } |
| 813 return; | 834 return; |
| 814 } | 835 } |
| 815 | 836 |
| 837 // Compute top-level declarations. | |
| 838 if (_topLevelDeclarationsTasks.isNotEmpty) { | |
| 839 _TopLevelLibraryDeclarationsTask task = _topLevelDeclarationsTasks.first; | |
| 840 bool isDone = await task.perform(); | |
| 841 if (isDone) { | |
| 842 _topLevelDeclarationsTasks.remove(task); | |
| 843 } | |
| 844 return; | |
| 845 } | |
| 846 | |
| 816 // Analyze a priority file. | 847 // Analyze a priority file. |
| 817 if (_priorityFiles.isNotEmpty) { | 848 if (_priorityFiles.isNotEmpty) { |
| 818 for (String path in _priorityFiles) { | 849 for (String path in _priorityFiles) { |
| 819 if (_filesToAnalyze.remove(path)) { | 850 if (_filesToAnalyze.remove(path)) { |
| 820 AnalysisResult result = _computeAnalysisResult(path, withUnit: true); | 851 AnalysisResult result = _computeAnalysisResult(path, withUnit: true); |
| 821 if (result == null) { | 852 if (result == null) { |
| 822 _partsToAnalyze.add(path); | 853 _partsToAnalyze.add(path); |
| 823 } else { | 854 } else { |
| 824 _resultController.add(result); | 855 _resultController.add(result); |
| 825 } | 856 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 897 set.remove(element); | 928 set.remove(element); |
| 898 return element; | 929 return element; |
| 899 } | 930 } |
| 900 } | 931 } |
| 901 | 932 |
| 902 /** | 933 /** |
| 903 * Priorities of [AnalysisDriver] work. The farther a priority to the beginning | 934 * Priorities of [AnalysisDriver] work. The farther a priority to the beginning |
| 904 * of the list, the earlier the corresponding [AnalysisDriver] should be asked | 935 * of the list, the earlier the corresponding [AnalysisDriver] should be asked |
| 905 * to perform work. | 936 * to perform work. |
| 906 */ | 937 */ |
| 907 enum AnalysisDriverPriority { | 938 enum AnalysisDriverPriority { nothing, general, priority, interactive } |
| 908 nothing, | |
| 909 general, | |
| 910 priority, | |
| 911 referencingName, | |
| 912 getIndex, | |
| 913 interactive | |
| 914 } | |
| 915 | 939 |
| 916 /** | 940 /** |
| 917 * Instances of this class schedule work in multiple [AnalysisDriver]s so that | 941 * Instances of this class schedule work in multiple [AnalysisDriver]s so that |
| 918 * work with the highest priority is performed first. | 942 * work with the highest priority is performed first. |
| 919 */ | 943 */ |
| 920 class AnalysisDriverScheduler { | 944 class AnalysisDriverScheduler { |
| 921 /** | 945 /** |
| 922 * Time interval in milliseconds before pumping the event queue. | 946 * Time interval in milliseconds before pumping the event queue. |
| 923 * | 947 * |
| 924 * Relinquishing execution flow and running the event loop after every task | 948 * Relinquishing execution flow and running the event loop after every task |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1314 } | 1338 } |
| 1315 | 1339 |
| 1316 /** | 1340 /** |
| 1317 * TODO(scheglov) document | 1341 * TODO(scheglov) document |
| 1318 */ | 1342 */ |
| 1319 class _LibraryContext { | 1343 class _LibraryContext { |
| 1320 final FileState file; | 1344 final FileState file; |
| 1321 final SummaryDataStore store; | 1345 final SummaryDataStore store; |
| 1322 _LibraryContext(this.file, this.store); | 1346 _LibraryContext(this.file, this.store); |
| 1323 } | 1347 } |
| 1348 | |
| 1349 /** | |
| 1350 * Task that computes top-level declarations in all known libraries. | |
| 1351 */ | |
| 1352 class _TopLevelLibraryDeclarationsTask { | |
| 1353 final AnalysisDriver driver; | |
| 1354 final Completer<List<TopLevelLibraryDeclarations>> completer = | |
| 1355 new Completer<List<TopLevelLibraryDeclarations>>(); | |
| 1356 | |
| 1357 final List<TopLevelLibraryDeclarations> libraryDeclarations = | |
| 1358 <TopLevelLibraryDeclarations>[]; | |
| 1359 final Set<String> checkedFiles = new Set<String>(); | |
| 1360 final List<String> filesToCheck = <String>[]; | |
| 1361 | |
| 1362 _TopLevelLibraryDeclarationsTask(this.driver); | |
| 1363 | |
| 1364 /** | |
| 1365 * Perform a single piece of work, and either complete the [completer] and | |
| 1366 * return `true` to indicate that the task is done, return `false` to indicate | |
| 1367 * that the task should continue to be run. | |
| 1368 */ | |
| 1369 Future<bool> perform() async { | |
| 1370 // Prepare files to check. | |
| 1371 if (filesToCheck.isEmpty) { | |
| 1372 filesToCheck.addAll(driver.addedFiles.difference(checkedFiles)); | |
| 1373 filesToCheck.addAll(driver.knownFiles.difference(checkedFiles)); | |
| 1374 } | |
| 1375 | |
| 1376 // If no more files to check, complete and done. | |
| 1377 if (filesToCheck.isEmpty) { | |
| 1378 completer.complete(libraryDeclarations); | |
| 1379 return true; | |
| 1380 } | |
| 1381 | |
| 1382 // Check the next file. | |
| 1383 String path = filesToCheck.removeLast(); | |
| 1384 FileState file = driver._fsState.getFileForPath(path); | |
| 1385 if (!file.isPart) { | |
| 1386 libraryDeclarations.add(new TopLevelLibraryDeclarations( | |
| 1387 file.source, file.exportedTopLevelDeclarations)); | |
| 1388 } | |
| 1389 checkedFiles.add(path); | |
| 1390 | |
| 1391 // We're not done yet. | |
| 1392 return false; | |
| 1393 } | |
| 1394 } | |
| OLD | NEW |