| 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 |