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 |