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 of a name. | |
| 162 */ | |
| 163 final _topLevelNameDeclarationsTasks = <_TopLevelNameDeclarationsTask>[]; | |
| 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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 Stream<AnalysisStatus> get status => _statusSupport.stream; | 302 Stream<AnalysisStatus> get status => _statusSupport.stream; |
| 297 | 303 |
| 298 /** | 304 /** |
| 299 * Return the priority of work that the driver needs to perform. | 305 * Return the priority of work that the driver needs to perform. |
| 300 */ | 306 */ |
| 301 AnalysisDriverPriority get _workPriority { | 307 AnalysisDriverPriority get _workPriority { |
| 302 if (_requestedFiles.isNotEmpty) { | 308 if (_requestedFiles.isNotEmpty) { |
| 303 return AnalysisDriverPriority.interactive; | 309 return AnalysisDriverPriority.interactive; |
| 304 } | 310 } |
| 305 if (_referencingNameTasks.isNotEmpty) { | 311 if (_referencingNameTasks.isNotEmpty) { |
| 306 return AnalysisDriverPriority.referencingName; | 312 return AnalysisDriverPriority.interactive; |
| 307 } | 313 } |
| 308 if (_indexRequestedFiles.isNotEmpty) { | 314 if (_indexRequestedFiles.isNotEmpty) { |
| 309 return AnalysisDriverPriority.getIndex; | 315 return AnalysisDriverPriority.interactive; |
| 316 } | |
| 317 if (_topLevelNameDeclarationsTasks.isNotEmpty) { | |
| 318 return AnalysisDriverPriority.interactive; | |
| 310 } | 319 } |
| 311 if (_priorityFiles.isNotEmpty) { | 320 if (_priorityFiles.isNotEmpty) { |
| 312 for (String path in _priorityFiles) { | 321 for (String path in _priorityFiles) { |
| 313 if (_filesToAnalyze.contains(path)) { | 322 if (_filesToAnalyze.contains(path)) { |
| 314 return AnalysisDriverPriority.priority; | 323 return AnalysisDriverPriority.priority; |
| 315 } | 324 } |
| 316 } | 325 } |
| 317 } | 326 } |
| 318 if (_filesToAnalyze.isNotEmpty) { | 327 if (_filesToAnalyze.isNotEmpty) { |
| 319 return AnalysisDriverPriority.general; | 328 return AnalysisDriverPriority.general; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 431 .putIfAbsent(path, () => <Completer<AnalysisResult>>[]) | 440 .putIfAbsent(path, () => <Completer<AnalysisResult>>[]) |
| 432 .add(completer); | 441 .add(completer); |
| 433 _statusSupport.transitionToAnalyzing(); | 442 _statusSupport.transitionToAnalyzing(); |
| 434 _scheduler._notify(this); | 443 _scheduler._notify(this); |
| 435 return completer.future; | 444 return completer.future; |
| 436 } | 445 } |
| 437 return new Future.value(); | 446 return new Future.value(); |
| 438 } | 447 } |
| 439 | 448 |
| 440 /** | 449 /** |
| 450 * Return a [Future] that completes with top-level declarations with the | |
| 451 * given [name] in all known libraries. | |
| 452 */ | |
| 453 Future<List<TopLevelDeclarationInSource>> getTopLevelNameDeclarations( | |
| 454 String name) { | |
| 455 var task = new _TopLevelNameDeclarationsTask(this, name); | |
| 456 _topLevelNameDeclarationsTasks.add(task); | |
| 457 _statusSupport.transitionToAnalyzing(); | |
| 458 _scheduler._notify(this); | |
| 459 return task.completer.future; | |
| 460 } | |
| 461 | |
| 462 /** | |
| 441 * Return a [Future] that completes with a [ParseResult] for the file | 463 * Return a [Future] that completes with a [ParseResult] for the file |
| 442 * with the given [path]. | 464 * with the given [path]. |
| 443 * | 465 * |
| 444 * The [path] must be absolute and normalized. | 466 * The [path] must be absolute and normalized. |
| 445 * | 467 * |
| 446 * The [path] can be any file - explicitly or implicitly analyzed, or neither. | 468 * The [path] can be any file - explicitly or implicitly analyzed, or neither. |
| 447 * | 469 * |
| 448 * The parsing is performed in the method itself, and the result is not | 470 * The parsing is performed in the method itself, and the result is not |
| 449 * produced through the [results] stream (just because it is not a fully | 471 * produced through the [results] stream (just because it is not a fully |
| 450 * resolved unit). | 472 * resolved unit). |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 806 // Compute files referencing a name. | 828 // Compute files referencing a name. |
| 807 if (_referencingNameTasks.isNotEmpty) { | 829 if (_referencingNameTasks.isNotEmpty) { |
| 808 _FilesReferencingNameTask task = _referencingNameTasks.first; | 830 _FilesReferencingNameTask task = _referencingNameTasks.first; |
| 809 bool isDone = await task.perform(); | 831 bool isDone = await task.perform(); |
| 810 if (isDone) { | 832 if (isDone) { |
| 811 _referencingNameTasks.remove(task); | 833 _referencingNameTasks.remove(task); |
| 812 } | 834 } |
| 813 return; | 835 return; |
| 814 } | 836 } |
| 815 | 837 |
| 838 // Compute top-level declarations. | |
| 839 if (_topLevelNameDeclarationsTasks.isNotEmpty) { | |
| 840 _TopLevelNameDeclarationsTask task = _topLevelNameDeclarationsTasks.first; | |
| 841 bool isDone = await task.perform(); | |
| 842 if (isDone) { | |
| 843 _topLevelNameDeclarationsTasks.remove(task); | |
| 844 } | |
| 845 return; | |
| 846 } | |
| 847 | |
| 816 // Analyze a priority file. | 848 // Analyze a priority file. |
| 817 if (_priorityFiles.isNotEmpty) { | 849 if (_priorityFiles.isNotEmpty) { |
| 818 for (String path in _priorityFiles) { | 850 for (String path in _priorityFiles) { |
| 819 if (_filesToAnalyze.remove(path)) { | 851 if (_filesToAnalyze.remove(path)) { |
| 820 AnalysisResult result = _computeAnalysisResult(path, withUnit: true); | 852 AnalysisResult result = _computeAnalysisResult(path, withUnit: true); |
| 821 if (result == null) { | 853 if (result == null) { |
| 822 _partsToAnalyze.add(path); | 854 _partsToAnalyze.add(path); |
| 823 } else { | 855 } else { |
| 824 _resultController.add(result); | 856 _resultController.add(result); |
| 825 } | 857 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 897 set.remove(element); | 929 set.remove(element); |
| 898 return element; | 930 return element; |
| 899 } | 931 } |
| 900 } | 932 } |
| 901 | 933 |
| 902 /** | 934 /** |
| 903 * Priorities of [AnalysisDriver] work. The farther a priority to the beginning | 935 * Priorities of [AnalysisDriver] work. The farther a priority to the beginning |
| 904 * of the list, the earlier the corresponding [AnalysisDriver] should be asked | 936 * of the list, the earlier the corresponding [AnalysisDriver] should be asked |
| 905 * to perform work. | 937 * to perform work. |
| 906 */ | 938 */ |
| 907 enum AnalysisDriverPriority { | 939 enum AnalysisDriverPriority { nothing, general, priority, interactive } |
| 908 nothing, | |
| 909 general, | |
| 910 priority, | |
| 911 referencingName, | |
| 912 getIndex, | |
| 913 interactive | |
| 914 } | |
| 915 | 940 |
| 916 /** | 941 /** |
| 917 * Instances of this class schedule work in multiple [AnalysisDriver]s so that | 942 * Instances of this class schedule work in multiple [AnalysisDriver]s so that |
| 918 * work with the highest priority is performed first. | 943 * work with the highest priority is performed first. |
| 919 */ | 944 */ |
| 920 class AnalysisDriverScheduler { | 945 class AnalysisDriverScheduler { |
| 921 /** | 946 /** |
| 922 * Time interval in milliseconds before pumping the event queue. | 947 * Time interval in milliseconds before pumping the event queue. |
| 923 * | 948 * |
| 924 * Relinquishing execution flow and running the event loop after every task | 949 * 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 } | 1339 } |
| 1315 | 1340 |
| 1316 /** | 1341 /** |
| 1317 * TODO(scheglov) document | 1342 * TODO(scheglov) document |
| 1318 */ | 1343 */ |
| 1319 class _LibraryContext { | 1344 class _LibraryContext { |
| 1320 final FileState file; | 1345 final FileState file; |
| 1321 final SummaryDataStore store; | 1346 final SummaryDataStore store; |
| 1322 _LibraryContext(this.file, this.store); | 1347 _LibraryContext(this.file, this.store); |
| 1323 } | 1348 } |
| 1349 | |
| 1350 /** | |
| 1351 * Task that computes top-level declarations in all known libraries. | |
|
Paul Berry
2016/12/02 17:56:37
Nit: Change to "Task that computes top-level decla
| |
| 1352 */ | |
| 1353 class _TopLevelNameDeclarationsTask { | |
| 1354 final AnalysisDriver driver; | |
| 1355 final String name; | |
| 1356 final Completer<List<TopLevelDeclarationInSource>> completer = | |
| 1357 new Completer<List<TopLevelDeclarationInSource>>(); | |
| 1358 | |
| 1359 final List<TopLevelDeclarationInSource> libraryDeclarations = | |
| 1360 <TopLevelDeclarationInSource>[]; | |
| 1361 final Set<String> checkedFiles = new Set<String>(); | |
| 1362 final List<String> filesToCheck = <String>[]; | |
| 1363 | |
| 1364 _TopLevelNameDeclarationsTask(this.driver, this.name); | |
| 1365 | |
| 1366 /** | |
| 1367 * Perform a single piece of work, and either complete the [completer] and | |
| 1368 * return `true` to indicate that the task is done, return `false` to indicate | |
| 1369 * that the task should continue to be run. | |
| 1370 */ | |
| 1371 Future<bool> perform() async { | |
| 1372 // Prepare files to check. | |
| 1373 if (filesToCheck.isEmpty) { | |
| 1374 filesToCheck.addAll(driver.addedFiles.difference(checkedFiles)); | |
| 1375 filesToCheck.addAll(driver.knownFiles.difference(checkedFiles)); | |
| 1376 } | |
| 1377 | |
| 1378 // If no more files to check, complete and done. | |
| 1379 if (filesToCheck.isEmpty) { | |
| 1380 completer.complete(libraryDeclarations); | |
| 1381 return true; | |
| 1382 } | |
| 1383 | |
| 1384 // Check the next file. | |
| 1385 String path = filesToCheck.removeLast(); | |
| 1386 if (checkedFiles.add(path)) { | |
| 1387 FileState file = driver._fsState.getFileForPath(path); | |
| 1388 if (!file.isPart) { | |
| 1389 TopLevelDeclaration declaration = | |
| 1390 file.exportedTopLevelDeclarations[name]; | |
| 1391 if (declaration != null) { | |
| 1392 libraryDeclarations | |
| 1393 .add(new TopLevelDeclarationInSource(file.source, declaration)); | |
| 1394 } | |
| 1395 } | |
| 1396 } | |
| 1397 | |
| 1398 // We're not done yet. | |
| 1399 return false; | |
| 1400 } | |
| 1401 } | |
| OLD | NEW |