OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library analyzer.src.context.context; | 5 library analyzer.src.context.context; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:collection'; | 8 import 'dart:collection'; |
9 | 9 |
10 import 'package:analyzer/instrumentation/instrumentation.dart'; | 10 import 'package:analyzer/instrumentation/instrumentation.dart'; |
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 return null; | 644 return null; |
645 } | 645 } |
646 | 646 |
647 @override | 647 @override |
648 CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync( | 648 CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync( |
649 Source unitSource, Source librarySource) { | 649 Source unitSource, Source librarySource) { |
650 if (!AnalysisEngine.isDartFileName(unitSource.shortName) || | 650 if (!AnalysisEngine.isDartFileName(unitSource.shortName) || |
651 !AnalysisEngine.isDartFileName(librarySource.shortName)) { | 651 !AnalysisEngine.isDartFileName(librarySource.shortName)) { |
652 return new CancelableFuture.error(new AnalysisNotScheduledError()); | 652 return new CancelableFuture.error(new AnalysisNotScheduledError()); |
653 } | 653 } |
654 var unitTarget = new LibrarySpecificUnit(librarySource, unitSource); | 654 return new AnalysisFutureHelper<CompilationUnit>( |
655 return new _AnalysisFutureHelper<CompilationUnit>(this) | 655 this, |
656 .computeAsync(unitTarget, (CacheEntry entry) { | 656 new LibrarySpecificUnit(librarySource, unitSource), |
657 CacheState state = entry.getState(RESOLVED_UNIT); | 657 RESOLVED_UNIT).computeAsync(); |
658 if (state == CacheState.ERROR) { | |
659 throw entry.exception; | |
660 } else if (state == CacheState.INVALID) { | |
661 return null; | |
662 } | |
663 return entry.getValue(RESOLVED_UNIT); | |
664 }, () { | |
665 dartWorkManager.addPriorityResult(unitTarget, RESOLVED_UNIT); | |
666 }); | |
667 } | 658 } |
668 | 659 |
669 @override | 660 @override |
670 Object /*V*/ computeResult( | 661 Object /*V*/ computeResult( |
671 AnalysisTarget target, ResultDescriptor /*<V>*/ descriptor) { | 662 AnalysisTarget target, ResultDescriptor /*<V>*/ descriptor) { |
672 // Make sure we are not trying to invoke the task model in a reentrant | 663 // Make sure we are not trying to invoke the task model in a reentrant |
673 // fashion. | 664 // fashion. |
674 assert(!driver.isTaskRunning); | 665 assert(!driver.isTaskRunning); |
675 CacheEntry entry = getCacheEntry(target); | 666 CacheEntry entry = getCacheEntry(target); |
676 CacheState state = entry.getState(descriptor); | 667 CacheState state = entry.getState(descriptor); |
(...skipping 1394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2071 return new AnalysisCache(<CachePartition>[ | 2062 return new AnalysisCache(<CachePartition>[ |
2072 AnalysisEngine.instance.partitionManager_new.forSdk(sdk) | 2063 AnalysisEngine.instance.partitionManager_new.forSdk(sdk) |
2073 ]); | 2064 ]); |
2074 } | 2065 } |
2075 } | 2066 } |
2076 | 2067 |
2077 /** | 2068 /** |
2078 * A helper class used to create futures for [AnalysisContextImpl]. | 2069 * A helper class used to create futures for [AnalysisContextImpl]. |
2079 * Using a helper class allows us to preserve the generic parameter T. | 2070 * Using a helper class allows us to preserve the generic parameter T. |
2080 */ | 2071 */ |
2081 class _AnalysisFutureHelper<T> { | 2072 class AnalysisFutureHelper<T> { |
2082 final AnalysisContextImpl _context; | 2073 final AnalysisContextImpl _context; |
| 2074 final AnalysisTarget _target; |
| 2075 final ResultDescriptor<T> _descriptor; |
2083 | 2076 |
2084 _AnalysisFutureHelper(this._context); | 2077 AnalysisFutureHelper(this._context, this._target, this._descriptor); |
2085 | 2078 |
2086 /** | 2079 /** |
2087 * Return a future that will be completed with the result of calling | 2080 * Return a future that will be completed with the result specified |
2088 * [computeValue]. If [computeValue] returns non-`null`, the future will be | 2081 * in the constructor. If the result is cached, the future will be |
2089 * completed immediately with the resulting value. If it returns `null`, then | 2082 * completed immediately with the resulting value. If not, then |
2090 * [scheduleComputation] is invoked to schedule analysis that will produce | 2083 * analysis is scheduled that will produce the required result. |
2091 * the required result, and [computeValue] will be re-executed in the future, | 2084 * If the result cannot be generated, then the future will be completed with |
2092 * after the next time the cached information for [target] has changed. If | |
2093 * [computeValue] throws an exception, the future will fail with that | |
2094 * exception. | |
2095 * | |
2096 * If the [computeValue] still returns `null` after there is no further | |
2097 * analysis to be done for [target], then the future will be completed with | |
2098 * the error AnalysisNotScheduledError. | 2085 * the error AnalysisNotScheduledError. |
2099 * | |
2100 * Since [computeValue] will be called while the state of analysis is being | |
2101 * updated, it should be free of side effects so that it doesn't cause | |
2102 * reentrant changes to the analysis state. | |
2103 */ | 2086 */ |
2104 CancelableFuture<T> computeAsync(AnalysisTarget target, | 2087 CancelableFuture<T> computeAsync() { |
2105 T computeValue(CacheEntry entry), void scheduleComputation()) { | |
2106 if (_context.isDisposed) { | 2088 if (_context.isDisposed) { |
2107 // No further analysis is expected, so return a future that completes | 2089 // No further analysis is expected, so return a future that completes |
2108 // immediately with AnalysisNotScheduledError. | 2090 // immediately with AnalysisNotScheduledError. |
2109 return new CancelableFuture.error(new AnalysisNotScheduledError()); | 2091 return new CancelableFuture.error(new AnalysisNotScheduledError()); |
2110 } | 2092 } |
2111 CacheEntry entry = _context.getCacheEntry(target); | 2093 CacheEntry entry = _context.getCacheEntry(_target); |
2112 PendingFuture pendingFuture = | 2094 PendingFuture pendingFuture = |
2113 new PendingFuture<T>(_context, target, computeValue); | 2095 new PendingFuture<T>(_context, _target, (CacheEntry entry) { |
| 2096 CacheState state = entry.getState(_descriptor); |
| 2097 if (state == CacheState.ERROR) { |
| 2098 throw entry.exception; |
| 2099 } else if (state == CacheState.INVALID) { |
| 2100 return null; |
| 2101 } |
| 2102 return entry.getValue(_descriptor); |
| 2103 }); |
2114 if (!pendingFuture.evaluate(entry)) { | 2104 if (!pendingFuture.evaluate(entry)) { |
2115 _context._pendingFutureTargets | 2105 _context._pendingFutureTargets |
2116 .putIfAbsent(target, () => <PendingFuture>[]) | 2106 .putIfAbsent(_target, () => <PendingFuture>[]) |
2117 .add(pendingFuture); | 2107 .add(pendingFuture); |
2118 scheduleComputation(); | 2108 _context.dartWorkManager.addPriorityResult(_target, _descriptor); |
2119 } | 2109 } |
2120 return pendingFuture.future; | 2110 return pendingFuture.future; |
2121 } | 2111 } |
2122 } | 2112 } |
OLD | NEW |