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 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 _sourceFactory.context = null; | 408 _sourceFactory.context = null; |
409 } | 409 } |
410 factory.context = this; | 410 factory.context = this; |
411 _sourceFactory = factory; | 411 _sourceFactory = factory; |
412 _cache = createCacheFromSourceFactory(factory); | 412 _cache = createCacheFromSourceFactory(factory); |
413 for (WorkManager workManager in workManagers) { | 413 for (WorkManager workManager in workManagers) { |
414 workManager.onSourceFactoryChanged(); | 414 workManager.onSourceFactoryChanged(); |
415 } | 415 } |
416 } | 416 } |
417 | 417 |
418 /** | |
419 * Invalidate analysis cache. | |
420 */ | |
421 void invalidateCachedResults() { | |
422 _cache = createCacheFromSourceFactory(_sourceFactory); | |
423 } | |
424 | |
425 @override | 418 @override |
426 List<Source> get sources { | 419 List<Source> get sources { |
427 return _cache.sources.toList(); | 420 return _cache.sources.toList(); |
428 } | 421 } |
429 | 422 |
430 /** | 423 /** |
431 * Return a list of the sources that would be processed by | 424 * Return a list of the sources that would be processed by |
432 * [performAnalysisTask]. This method duplicates, and must therefore be kept | 425 * [performAnalysisTask]. This method duplicates, and must therefore be kept |
433 * in sync with, [getNextAnalysisTask]. This method is intended to be used for | 426 * in sync with, [getNextAnalysisTask]. This method is intended to be used for |
434 * testing purposes only. | 427 * testing purposes only. |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1022 } | 1015 } |
1023 } | 1016 } |
1024 } | 1017 } |
1025 if (notify && changed) { | 1018 if (notify && changed) { |
1026 _onSourcesChangedController | 1019 _onSourcesChangedController |
1027 .add(new SourcesChangedEvent.changedContent(source, newContents)); | 1020 .add(new SourcesChangedEvent.changedContent(source, newContents)); |
1028 } | 1021 } |
1029 return changed; | 1022 return changed; |
1030 } | 1023 } |
1031 | 1024 |
| 1025 /** |
| 1026 * Invalidate analysis cache. |
| 1027 */ |
| 1028 void invalidateCachedResults() { |
| 1029 _cache = createCacheFromSourceFactory(_sourceFactory); |
| 1030 } |
| 1031 |
1032 @override | 1032 @override |
1033 void invalidateLibraryHints(Source librarySource) { | 1033 void invalidateLibraryHints(Source librarySource) { |
1034 List<Source> sources = getResult(librarySource, UNITS); | 1034 List<Source> sources = getResult(librarySource, UNITS); |
1035 if (sources != null) { | 1035 if (sources != null) { |
1036 for (Source source in sources) { | 1036 for (Source source in sources) { |
1037 getCacheEntry(source).setState(HINTS, CacheState.INVALID); | 1037 getCacheEntry(source).setState(HINTS, CacheState.INVALID); |
1038 } | 1038 } |
1039 } | 1039 } |
1040 } | 1040 } |
1041 | 1041 |
1042 @override | 1042 @override |
1043 bool isClientLibrary(Source librarySource) { | 1043 bool isClientLibrary(Source librarySource) { |
1044 CacheEntry entry = _cache.get(librarySource); | 1044 CacheEntry entry = _cache.get(librarySource); |
1045 return entry.getValue(IS_CLIENT) && entry.getValue(IS_LAUNCHABLE); | 1045 return _referencesDartHtml(librarySource) && entry.getValue(IS_LAUNCHABLE); |
1046 } | 1046 } |
1047 | 1047 |
1048 @override | 1048 @override |
1049 bool isServerLibrary(Source librarySource) { | 1049 bool isServerLibrary(Source librarySource) { |
1050 CacheEntry entry = _cache.get(librarySource); | 1050 CacheEntry entry = _cache.get(librarySource); |
1051 return !entry.getValue(IS_CLIENT) && entry.getValue(IS_LAUNCHABLE); | 1051 return !_referencesDartHtml(librarySource) && entry.getValue(IS_LAUNCHABLE); |
1052 } | 1052 } |
1053 | 1053 |
1054 @override | 1054 @override |
1055 Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor) { | 1055 Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor) { |
1056 return driver.onResultComputed(descriptor); | 1056 return driver.onResultComputed(descriptor); |
1057 } | 1057 } |
1058 | 1058 |
1059 @override | 1059 @override |
1060 CompilationUnit parseCompilationUnit(Source source) { | 1060 CompilationUnit parseCompilationUnit(Source source) { |
1061 if (!AnalysisEngine.isDartFileName(source.shortName)) { | 1061 if (!AnalysisEngine.isDartFileName(source.shortName)) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 // CLASS_ELEMENTS | 1118 // CLASS_ELEMENTS |
1119 setValue(COMPILATION_UNIT_ELEMENT, library.definingCompilationUnit); | 1119 setValue(COMPILATION_UNIT_ELEMENT, library.definingCompilationUnit); |
1120 // CONSTRUCTORS | 1120 // CONSTRUCTORS |
1121 // CONSTRUCTORS_ERRORS | 1121 // CONSTRUCTORS_ERRORS |
1122 entry.setState(CONTENT, CacheState.FLUSHED); | 1122 entry.setState(CONTENT, CacheState.FLUSHED); |
1123 setValue(EXPORTED_LIBRARIES, Source.EMPTY_LIST); | 1123 setValue(EXPORTED_LIBRARIES, Source.EMPTY_LIST); |
1124 // EXPORT_SOURCE_CLOSURE | 1124 // EXPORT_SOURCE_CLOSURE |
1125 setValue(IMPORTED_LIBRARIES, Source.EMPTY_LIST); | 1125 setValue(IMPORTED_LIBRARIES, Source.EMPTY_LIST); |
1126 // IMPORT_SOURCE_CLOSURE | 1126 // IMPORT_SOURCE_CLOSURE |
1127 setValue(INCLUDED_PARTS, Source.EMPTY_LIST); | 1127 setValue(INCLUDED_PARTS, Source.EMPTY_LIST); |
1128 setValue(IS_CLIENT, true); | |
1129 setValue(IS_LAUNCHABLE, false); | 1128 setValue(IS_LAUNCHABLE, false); |
1130 setValue(LIBRARY_ELEMENT, library); | 1129 setValue(LIBRARY_ELEMENT, library); |
1131 setValue(LIBRARY_ELEMENT1, library); | 1130 setValue(LIBRARY_ELEMENT1, library); |
1132 setValue(LIBRARY_ELEMENT2, library); | 1131 setValue(LIBRARY_ELEMENT2, library); |
1133 setValue(LIBRARY_ELEMENT3, library); | 1132 setValue(LIBRARY_ELEMENT3, library); |
1134 setValue(LIBRARY_ELEMENT4, library); | 1133 setValue(LIBRARY_ELEMENT4, library); |
1135 setValue(LIBRARY_ELEMENT5, library); | 1134 setValue(LIBRARY_ELEMENT5, library); |
1136 setValue(LINE_INFO, new LineInfo(<int>[0])); | 1135 setValue(LINE_INFO, new LineInfo(<int>[0])); |
1137 setValue(PARSE_ERRORS, AnalysisError.NO_ERRORS); | 1136 setValue(PARSE_ERRORS, AnalysisError.NO_ERRORS); |
1138 entry.setState(PARSED_UNIT, CacheState.FLUSHED); | 1137 entry.setState(PARSED_UNIT, CacheState.FLUSHED); |
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1695 * given [source] has been updated to the given [errors]. | 1694 * given [source] has been updated to the given [errors]. |
1696 */ | 1695 */ |
1697 void _notifyErrors( | 1696 void _notifyErrors( |
1698 Source source, List<AnalysisError> errors, LineInfo lineInfo) { | 1697 Source source, List<AnalysisError> errors, LineInfo lineInfo) { |
1699 int count = _listeners.length; | 1698 int count = _listeners.length; |
1700 for (int i = 0; i < count; i++) { | 1699 for (int i = 0; i < count; i++) { |
1701 _listeners[i].computedErrors(this, source, errors, lineInfo); | 1700 _listeners[i].computedErrors(this, source, errors, lineInfo); |
1702 } | 1701 } |
1703 } | 1702 } |
1704 | 1703 |
| 1704 bool _referencesDartHtml(Source librarySource) { |
| 1705 Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML); |
| 1706 Set<Source> checkedSources = new Set<Source>(); |
| 1707 bool _refHtml(Source source) { |
| 1708 if (!checkedSources.add(source)) { |
| 1709 return false; |
| 1710 } |
| 1711 if (source == htmlSource) { |
| 1712 return true; |
| 1713 } |
| 1714 LibraryElement library = _cache.getValue(source, LIBRARY_ELEMENT); |
| 1715 if (library != null) { |
| 1716 return library.importedLibraries.any((x) => _refHtml(x.source)) || |
| 1717 library.exportedLibraries.any((x) => _refHtml(x.source)); |
| 1718 } |
| 1719 return false; |
| 1720 } |
| 1721 return _refHtml(librarySource); |
| 1722 } |
| 1723 |
1705 void _removeFromCache(Source source) { | 1724 void _removeFromCache(Source source) { |
1706 CacheEntry entry = _cache.remove(source); | 1725 CacheEntry entry = _cache.remove(source); |
1707 if (entry != null && !entry.explicitlyAdded) { | 1726 if (entry != null && !entry.explicitlyAdded) { |
1708 _implicitAnalysisEventsController | 1727 _implicitAnalysisEventsController |
1709 .add(new ImplicitAnalysisEvent(source, false)); | 1728 .add(new ImplicitAnalysisEvent(source, false)); |
1710 } | 1729 } |
1711 } | 1730 } |
1712 | 1731 |
1713 /** | 1732 /** |
1714 * Remove the given [source] from the priority order if it is in the list. | 1733 * Remove the given [source] from the priority order if it is in the list. |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1925 } | 1944 } |
1926 // schedule | 1945 // schedule |
1927 dartWorkManager.unitIncrementallyResolved(librarySource, unitSource); | 1946 dartWorkManager.unitIncrementallyResolved(librarySource, unitSource); |
1928 // OK | 1947 // OK |
1929 return true; | 1948 return true; |
1930 }); | 1949 }); |
1931 } | 1950 } |
1932 } | 1951 } |
1933 | 1952 |
1934 /** | 1953 /** |
| 1954 * A helper class used to create futures for [AnalysisContextImpl]. |
| 1955 * Using a helper class allows us to preserve the generic parameter T. |
| 1956 */ |
| 1957 class AnalysisFutureHelper<T> { |
| 1958 final AnalysisContextImpl _context; |
| 1959 final AnalysisTarget _target; |
| 1960 final ResultDescriptor<T> _descriptor; |
| 1961 |
| 1962 AnalysisFutureHelper(this._context, this._target, this._descriptor); |
| 1963 |
| 1964 /** |
| 1965 * Return a future that will be completed with the result specified |
| 1966 * in the constructor. If the result is cached, the future will be |
| 1967 * completed immediately with the resulting value. If not, then |
| 1968 * analysis is scheduled that will produce the required result. |
| 1969 * If the result cannot be generated, then the future will be completed with |
| 1970 * the error AnalysisNotScheduledError. |
| 1971 */ |
| 1972 CancelableFuture<T> computeAsync() { |
| 1973 if (_context.isDisposed) { |
| 1974 // No further analysis is expected, so return a future that completes |
| 1975 // immediately with AnalysisNotScheduledError. |
| 1976 return new CancelableFuture.error(new AnalysisNotScheduledError()); |
| 1977 } |
| 1978 CacheEntry entry = _context.getCacheEntry(_target); |
| 1979 PendingFuture pendingFuture = |
| 1980 new PendingFuture<T>(_context, _target, (CacheEntry entry) { |
| 1981 CacheState state = entry.getState(_descriptor); |
| 1982 if (state == CacheState.ERROR) { |
| 1983 throw entry.exception; |
| 1984 } else if (state == CacheState.INVALID) { |
| 1985 return null; |
| 1986 } |
| 1987 return entry.getValue(_descriptor); |
| 1988 }); |
| 1989 if (!pendingFuture.evaluate(entry)) { |
| 1990 _context._pendingFutureTargets |
| 1991 .putIfAbsent(_target, () => <PendingFuture>[]) |
| 1992 .add(pendingFuture); |
| 1993 _context.dartWorkManager.addPriorityResult(_target, _descriptor); |
| 1994 } |
| 1995 return pendingFuture.future; |
| 1996 } |
| 1997 } |
| 1998 |
| 1999 /** |
1935 * An object that manages the partitions that can be shared between analysis | 2000 * An object that manages the partitions that can be shared between analysis |
1936 * contexts. | 2001 * contexts. |
1937 */ | 2002 */ |
1938 class PartitionManager { | 2003 class PartitionManager { |
1939 /** | 2004 /** |
1940 * A table mapping SDK's to the partitions used for those SDK's. | 2005 * A table mapping SDK's to the partitions used for those SDK's. |
1941 */ | 2006 */ |
1942 HashMap<DartSdk, SdkCachePartition> _sdkPartitions = | 2007 HashMap<DartSdk, SdkCachePartition> _sdkPartitions = |
1943 new HashMap<DartSdk, SdkCachePartition>(); | 2008 new HashMap<DartSdk, SdkCachePartition>(); |
1944 | 2009 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2063 DartSdk sdk = factory.dartSdk; | 2128 DartSdk sdk = factory.dartSdk; |
2064 if (sdk == null) { | 2129 if (sdk == null) { |
2065 throw new IllegalArgumentException( | 2130 throw new IllegalArgumentException( |
2066 "The source factory for an SDK analysis context must have a DartUriRes
olver"); | 2131 "The source factory for an SDK analysis context must have a DartUriRes
olver"); |
2067 } | 2132 } |
2068 return new AnalysisCache(<CachePartition>[ | 2133 return new AnalysisCache(<CachePartition>[ |
2069 AnalysisEngine.instance.partitionManager_new.forSdk(sdk) | 2134 AnalysisEngine.instance.partitionManager_new.forSdk(sdk) |
2070 ]); | 2135 ]); |
2071 } | 2136 } |
2072 } | 2137 } |
2073 | |
2074 /** | |
2075 * A helper class used to create futures for [AnalysisContextImpl]. | |
2076 * Using a helper class allows us to preserve the generic parameter T. | |
2077 */ | |
2078 class AnalysisFutureHelper<T> { | |
2079 final AnalysisContextImpl _context; | |
2080 final AnalysisTarget _target; | |
2081 final ResultDescriptor<T> _descriptor; | |
2082 | |
2083 AnalysisFutureHelper(this._context, this._target, this._descriptor); | |
2084 | |
2085 /** | |
2086 * Return a future that will be completed with the result specified | |
2087 * in the constructor. If the result is cached, the future will be | |
2088 * completed immediately with the resulting value. If not, then | |
2089 * analysis is scheduled that will produce the required result. | |
2090 * If the result cannot be generated, then the future will be completed with | |
2091 * the error AnalysisNotScheduledError. | |
2092 */ | |
2093 CancelableFuture<T> computeAsync() { | |
2094 if (_context.isDisposed) { | |
2095 // No further analysis is expected, so return a future that completes | |
2096 // immediately with AnalysisNotScheduledError. | |
2097 return new CancelableFuture.error(new AnalysisNotScheduledError()); | |
2098 } | |
2099 CacheEntry entry = _context.getCacheEntry(_target); | |
2100 PendingFuture pendingFuture = | |
2101 new PendingFuture<T>(_context, _target, (CacheEntry entry) { | |
2102 CacheState state = entry.getState(_descriptor); | |
2103 if (state == CacheState.ERROR) { | |
2104 throw entry.exception; | |
2105 } else if (state == CacheState.INVALID) { | |
2106 return null; | |
2107 } | |
2108 return entry.getValue(_descriptor); | |
2109 }); | |
2110 if (!pendingFuture.evaluate(entry)) { | |
2111 _context._pendingFutureTargets | |
2112 .putIfAbsent(_target, () => <PendingFuture>[]) | |
2113 .add(pendingFuture); | |
2114 _context.dartWorkManager.addPriorityResult(_target, _descriptor); | |
2115 } | |
2116 return pendingFuture.future; | |
2117 } | |
2118 } | |
OLD | NEW |