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 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 return null; | 601 return null; |
602 } | 602 } |
603 | 603 |
604 @override | 604 @override |
605 CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync( | 605 CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync( |
606 Source unitSource, Source librarySource) { | 606 Source unitSource, Source librarySource) { |
607 if (!AnalysisEngine.isDartFileName(unitSource.shortName) || | 607 if (!AnalysisEngine.isDartFileName(unitSource.shortName) || |
608 !AnalysisEngine.isDartFileName(librarySource.shortName)) { | 608 !AnalysisEngine.isDartFileName(librarySource.shortName)) { |
609 return new CancelableFuture.error(new AnalysisNotScheduledError()); | 609 return new CancelableFuture.error(new AnalysisNotScheduledError()); |
610 } | 610 } |
| 611 var unitTarget = new LibrarySpecificUnit(librarySource, unitSource); |
611 return new _AnalysisFutureHelper<CompilationUnit>(this).computeAsync( | 612 return new _AnalysisFutureHelper<CompilationUnit>(this).computeAsync( |
612 new LibrarySpecificUnit(librarySource, unitSource), (CacheEntry entry) { | 613 unitTarget, (CacheEntry entry) { |
613 CacheState state = entry.getState(RESOLVED_UNIT); | 614 CacheState state = entry.getState(RESOLVED_UNIT); |
614 if (state == CacheState.ERROR) { | 615 if (state == CacheState.ERROR) { |
615 throw entry.exception; | 616 throw entry.exception; |
616 } else if (state == CacheState.INVALID) { | 617 } else if (state == CacheState.INVALID) { |
617 return null; | 618 return null; |
618 } | 619 } |
619 return entry.getValue(RESOLVED_UNIT); | 620 return entry.getValue(RESOLVED_UNIT); |
| 621 }, () { |
| 622 dartWorkManager.addPriorityResult(unitTarget, RESOLVED_UNIT); |
620 }); | 623 }); |
621 } | 624 } |
622 | 625 |
623 /** | 626 /** |
624 * Create an analysis cache based on the given source [factory]. | 627 * Create an analysis cache based on the given source [factory]. |
625 */ | 628 */ |
626 AnalysisCache createCacheFromSourceFactory(SourceFactory factory) { | 629 AnalysisCache createCacheFromSourceFactory(SourceFactory factory) { |
627 if (factory == null) { | 630 if (factory == null) { |
628 return new AnalysisCache(<CachePartition>[_privatePartition]); | 631 return new AnalysisCache(<CachePartition>[_privatePartition]); |
629 } | 632 } |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
892 // Note that this is not part of the API of the interface. | 895 // Note that this is not part of the API of the interface. |
893 // TODO(brianwilkerson) The public namespace used to be cached, but no | 896 // TODO(brianwilkerson) The public namespace used to be cached, but no |
894 // longer is. Konstantin adds: | 897 // longer is. Konstantin adds: |
895 // The only client of this method is NamespaceBuilder._createExportMapping()
, | 898 // The only client of this method is NamespaceBuilder._createExportMapping()
, |
896 // and it is not used with tasks - instead we compute export namespace once | 899 // and it is not used with tasks - instead we compute export namespace once |
897 // using BuildExportNamespaceTask and reuse in scopes. | 900 // using BuildExportNamespaceTask and reuse in scopes. |
898 NamespaceBuilder builder = new NamespaceBuilder(); | 901 NamespaceBuilder builder = new NamespaceBuilder(); |
899 return builder.createPublicNamespaceForLibrary(library); | 902 return builder.createPublicNamespaceForLibrary(library); |
900 } | 903 } |
901 | 904 |
902 /** | |
903 * Return the cache entry associated with the given [target], or `null` if | |
904 * there is no entry associated with the target. | |
905 */ | |
906 CacheEntry getReadableSourceEntryOrNull(AnalysisTarget target) => | |
907 _cache.get(target); | |
908 | |
909 @override | 905 @override |
910 CompilationUnit getResolvedCompilationUnit( | 906 CompilationUnit getResolvedCompilationUnit( |
911 Source unitSource, LibraryElement library) { | 907 Source unitSource, LibraryElement library) { |
912 if (library == null || | 908 if (library == null || |
913 !AnalysisEngine.isDartFileName(unitSource.shortName)) { | 909 !AnalysisEngine.isDartFileName(unitSource.shortName)) { |
914 return null; | 910 return null; |
915 } | 911 } |
916 return getResolvedCompilationUnit2(unitSource, library.source); | 912 return getResolvedCompilationUnit2(unitSource, library.source); |
917 } | 913 } |
918 | 914 |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1038 if (!AnalysisEngine.isHtmlFileName(source.shortName)) { | 1034 if (!AnalysisEngine.isHtmlFileName(source.shortName)) { |
1039 return null; | 1035 return null; |
1040 } | 1036 } |
1041 // TODO(brianwilkerson) Implement HTML analysis. | 1037 // TODO(brianwilkerson) Implement HTML analysis. |
1042 return null; //_computeResult(source, null); | 1038 return null; //_computeResult(source, null); |
1043 } | 1039 } |
1044 | 1040 |
1045 @override | 1041 @override |
1046 AnalysisResult performAnalysisTask() { | 1042 AnalysisResult performAnalysisTask() { |
1047 return PerformanceStatistics.performAnaysis.makeCurrentWhile(() { | 1043 return PerformanceStatistics.performAnaysis.makeCurrentWhile(() { |
| 1044 _evaluatePendingFutures(); |
1048 bool done = !driver.performAnalysisTask(); | 1045 bool done = !driver.performAnalysisTask(); |
1049 if (done) { | 1046 if (done) { |
1050 done = !_validateCacheConsistency(); | 1047 done = !_validateCacheConsistency(); |
1051 } | 1048 } |
1052 List<ChangeNotice> notices = _getChangeNotices(done); | 1049 List<ChangeNotice> notices = _getChangeNotices(done); |
1053 if (notices != null) { | 1050 if (notices != null) { |
1054 int noticeCount = notices.length; | 1051 int noticeCount = notices.length; |
1055 for (int i = 0; i < noticeCount; i++) { | 1052 for (int i = 0; i < noticeCount; i++) { |
1056 ChangeNotice notice = notices[i]; | 1053 ChangeNotice notice = notices[i]; |
1057 _notifyErrors(notice.source, notice.errors, notice.lineInfo); | 1054 _notifyErrors(notice.source, notice.errors, notice.lineInfo); |
1058 } | 1055 } |
1059 } | 1056 } |
1060 return new AnalysisResult(notices, -1, '', -1); | 1057 return new AnalysisResult(notices, -1, '', -1); |
1061 }); | 1058 }); |
1062 } | 1059 } |
1063 | 1060 |
| 1061 void _evaluatePendingFutures() { |
| 1062 for (AnalysisTarget target in _pendingFutureTargets.keys) { |
| 1063 CacheEntry cacheEntry = _cache.get(target); |
| 1064 List<PendingFuture> pendingFutures = _pendingFutureTargets[target]; |
| 1065 for (int i = 0; i < pendingFutures.length;) { |
| 1066 if (pendingFutures[i].evaluate(cacheEntry)) { |
| 1067 pendingFutures.removeAt(i); |
| 1068 } else { |
| 1069 i++; |
| 1070 } |
| 1071 } |
| 1072 } |
| 1073 } |
| 1074 |
1064 @override | 1075 @override |
1065 void recordLibraryElements(Map<Source, LibraryElement> elementMap) { | 1076 void recordLibraryElements(Map<Source, LibraryElement> elementMap) { |
1066 elementMap.forEach((Source librarySource, LibraryElement library) { | 1077 elementMap.forEach((Source librarySource, LibraryElement library) { |
1067 // | 1078 // |
1068 // Cache the element in the library's info. | 1079 // Cache the element in the library's info. |
1069 // | 1080 // |
1070 CacheEntry entry = getCacheEntry(librarySource); | 1081 CacheEntry entry = getCacheEntry(librarySource); |
1071 setValue(ResultDescriptor result, value) { | 1082 setValue(ResultDescriptor result, value) { |
1072 entry.setValue(result, value, TargetedResult.EMPTY_LIST); | 1083 entry.setValue(result, value, TargetedResult.EMPTY_LIST); |
1073 } | 1084 } |
(...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1919 throw new IllegalArgumentException( | 1930 throw new IllegalArgumentException( |
1920 "The source factory for an SDK analysis context must have a DartUriRes
olver"); | 1931 "The source factory for an SDK analysis context must have a DartUriRes
olver"); |
1921 } | 1932 } |
1922 return new AnalysisCache(<CachePartition>[ | 1933 return new AnalysisCache(<CachePartition>[ |
1923 AnalysisEngine.instance.partitionManager_new.forSdk(sdk) | 1934 AnalysisEngine.instance.partitionManager_new.forSdk(sdk) |
1924 ]); | 1935 ]); |
1925 } | 1936 } |
1926 } | 1937 } |
1927 | 1938 |
1928 /** | 1939 /** |
1929 * A helper class used to create futures for AnalysisContextImpl. Using a helper | 1940 * A helper class used to create futures for [AnalysisContextImpl]. |
1930 * class allows us to preserve the generic parameter T. | 1941 * Using a helper class allows us to preserve the generic parameter T. |
1931 */ | 1942 */ |
1932 class _AnalysisFutureHelper<T> { | 1943 class _AnalysisFutureHelper<T> { |
1933 final AnalysisContextImpl _context; | 1944 final AnalysisContextImpl _context; |
1934 | 1945 |
1935 _AnalysisFutureHelper(this._context); | 1946 _AnalysisFutureHelper(this._context); |
1936 | 1947 |
1937 /** | 1948 /** |
1938 * Return a future that will be completed with the result of calling | 1949 * Return a future that will be completed with the result of calling |
1939 * [computeValue]. If [computeValue] returns non-`null`, the future will be | 1950 * [computeValue]. If [computeValue] returns non-`null`, the future will be |
1940 * completed immediately with the resulting value. If it returns `null`, then | 1951 * completed immediately with the resulting value. If it returns `null`, then |
1941 * it will be re-executed in the future, after the next time the cached | 1952 * [scheduleComputation] is invoked to schedule analysis that will produce |
1942 * information for [target] has changed. If [computeValue] throws an | 1953 * the required result, and [computeValue] will be re-executed in the future, |
1943 * exception, the future will fail with that exception. | 1954 * after the next time the cached information for [target] has changed. If |
| 1955 * [computeValue] throws an exception, the future will fail with that |
| 1956 * exception. |
1944 * | 1957 * |
1945 * If the [computeValue] still returns `null` after there is no further | 1958 * If the [computeValue] still returns `null` after there is no further |
1946 * analysis to be done for [target], then the future will be completed with | 1959 * analysis to be done for [target], then the future will be completed with |
1947 * the error AnalysisNotScheduledError. | 1960 * the error AnalysisNotScheduledError. |
1948 * | 1961 * |
1949 * Since [computeValue] will be called while the state of analysis is being | 1962 * Since [computeValue] will be called while the state of analysis is being |
1950 * updated, it should be free of side effects so that it doesn't cause | 1963 * updated, it should be free of side effects so that it doesn't cause |
1951 * reentrant changes to the analysis state. | 1964 * reentrant changes to the analysis state. |
1952 */ | 1965 */ |
1953 CancelableFuture<T> computeAsync( | 1966 CancelableFuture<T> computeAsync(AnalysisTarget target, |
1954 AnalysisTarget target, T computeValue(CacheEntry entry)) { | 1967 T computeValue(CacheEntry entry), void scheduleComputation()) { |
1955 if (_context.isDisposed) { | 1968 if (_context.isDisposed) { |
1956 // No further analysis is expected, so return a future that completes | 1969 // No further analysis is expected, so return a future that completes |
1957 // immediately with AnalysisNotScheduledError. | 1970 // immediately with AnalysisNotScheduledError. |
1958 return new CancelableFuture.error(new AnalysisNotScheduledError()); | 1971 return new CancelableFuture.error(new AnalysisNotScheduledError()); |
1959 } | 1972 } |
1960 CacheEntry entry = _context.getReadableSourceEntryOrNull(target); | 1973 CacheEntry entry = _context.getCacheEntry(target); |
1961 if (entry == null) { | |
1962 return new CancelableFuture.error(new AnalysisNotScheduledError()); | |
1963 } | |
1964 PendingFuture pendingFuture = | 1974 PendingFuture pendingFuture = |
1965 new PendingFuture<T>(_context, target, computeValue); | 1975 new PendingFuture<T>(_context, target, computeValue); |
1966 if (!pendingFuture.evaluate(entry)) { | 1976 if (!pendingFuture.evaluate(entry)) { |
1967 _context._pendingFutureTargets | 1977 _context._pendingFutureTargets |
1968 .putIfAbsent(target, () => <PendingFuture>[]) | 1978 .putIfAbsent(target, () => <PendingFuture>[]) |
1969 .add(pendingFuture); | 1979 .add(pendingFuture); |
| 1980 scheduleComputation(); |
1970 } | 1981 } |
1971 return pendingFuture.future; | 1982 return pendingFuture.future; |
1972 } | 1983 } |
1973 } | 1984 } |
OLD | NEW |