| 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/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
| 11 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; |
| 11 import 'package:analyzer/dart/element/element.dart'; | 12 import 'package:analyzer/dart/element/element.dart'; |
| 12 import 'package:analyzer/error/error.dart'; | 13 import 'package:analyzer/error/error.dart'; |
| 13 import 'package:analyzer/exception/exception.dart'; | 14 import 'package:analyzer/exception/exception.dart'; |
| 15 import 'package:analyzer/instrumentation/instrumentation.dart'; |
| 14 import 'package:analyzer/plugin/resolver_provider.dart'; | 16 import 'package:analyzer/plugin/resolver_provider.dart'; |
| 15 import 'package:analyzer/plugin/task.dart'; | 17 import 'package:analyzer/plugin/task.dart'; |
| 16 import 'package:analyzer/src/cancelable_future.dart'; | 18 import 'package:analyzer/src/cancelable_future.dart'; |
| 17 import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator; | 19 import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator; |
| 18 import 'package:analyzer/src/context/cache.dart'; | 20 import 'package:analyzer/src/context/cache.dart'; |
| 19 import 'package:analyzer/src/dart/element/element.dart'; | 21 import 'package:analyzer/src/dart/element/element.dart'; |
| 20 import 'package:analyzer/src/generated/constant.dart'; | 22 import 'package:analyzer/src/generated/constant.dart'; |
| 21 import 'package:analyzer/src/generated/engine.dart'; | 23 import 'package:analyzer/src/generated/engine.dart'; |
| 24 import 'package:analyzer/src/generated/incremental_resolver.dart'; |
| 22 import 'package:analyzer/src/generated/resolver.dart'; | 25 import 'package:analyzer/src/generated/resolver.dart'; |
| 23 import 'package:analyzer/src/generated/sdk.dart' show DartSdk; | 26 import 'package:analyzer/src/generated/sdk.dart' show DartSdk; |
| 24 import 'package:analyzer/src/generated/source.dart'; | 27 import 'package:analyzer/src/generated/source.dart'; |
| 25 import 'package:analyzer/src/generated/utilities_collection.dart'; | 28 import 'package:analyzer/src/generated/utilities_collection.dart'; |
| 26 import 'package:analyzer/src/task/dart.dart'; | 29 import 'package:analyzer/src/task/dart.dart'; |
| 27 import 'package:analyzer/src/task/dart_work_manager.dart'; | 30 import 'package:analyzer/src/task/dart_work_manager.dart'; |
| 28 import 'package:analyzer/src/task/driver.dart'; | 31 import 'package:analyzer/src/task/driver.dart'; |
| 29 import 'package:analyzer/src/task/manager.dart'; | 32 import 'package:analyzer/src/task/manager.dart'; |
| 30 import 'package:analyzer/task/dart.dart'; | 33 import 'package:analyzer/task/dart.dart'; |
| 31 import 'package:analyzer/task/general.dart'; | 34 import 'package:analyzer/task/general.dart'; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 46 * it should be free of side effects so that it doesn't cause reentrant changes | 49 * it should be free of side effects so that it doesn't cause reentrant changes |
| 47 * to the analysis state. | 50 * to the analysis state. |
| 48 */ | 51 */ |
| 49 typedef T PendingFutureComputer<T>(CacheEntry entry); | 52 typedef T PendingFutureComputer<T>(CacheEntry entry); |
| 50 | 53 |
| 51 /** | 54 /** |
| 52 * An [AnalysisContext] in which analysis can be performed. | 55 * An [AnalysisContext] in which analysis can be performed. |
| 53 */ | 56 */ |
| 54 class AnalysisContextImpl implements InternalAnalysisContext { | 57 class AnalysisContextImpl implements InternalAnalysisContext { |
| 55 /** | 58 /** |
| 59 * The next context identifier. |
| 60 */ |
| 61 static int _NEXT_ID = 0; |
| 62 |
| 63 /** |
| 64 * The unique identifier of this context. |
| 65 */ |
| 66 final int _id = _NEXT_ID++; |
| 67 |
| 68 /** |
| 56 * The flag that is `true` if the context is being analyzed. | 69 * The flag that is `true` if the context is being analyzed. |
| 57 */ | 70 */ |
| 58 bool _isActive = false; | 71 bool _isActive = false; |
| 59 | 72 |
| 60 /** | 73 /** |
| 61 * A client-provided name used to identify this context, or `null` if the | 74 * A client-provided name used to identify this context, or `null` if the |
| 62 * client has not provided a name. | 75 * client has not provided a name. |
| 63 */ | 76 */ |
| 64 @override | 77 @override |
| 65 String name; | 78 String name; |
| (...skipping 984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1050 TimestampedData<String> fileContents = source.contents; | 1063 TimestampedData<String> fileContents = source.contents; |
| 1051 if (fileContents.modificationTime == entry.modificationTime) { | 1064 if (fileContents.modificationTime == entry.modificationTime) { |
| 1052 originalContents = fileContents.data; | 1065 originalContents = fileContents.data; |
| 1053 } | 1066 } |
| 1054 } catch (e) {} | 1067 } catch (e) {} |
| 1055 } | 1068 } |
| 1056 bool changed = newContents != originalContents; | 1069 bool changed = newContents != originalContents; |
| 1057 if (newContents != null) { | 1070 if (newContents != null) { |
| 1058 if (changed) { | 1071 if (changed) { |
| 1059 entry.modificationTime = _contentCache.getModificationStamp(source); | 1072 entry.modificationTime = _contentCache.getModificationStamp(source); |
| 1060 if (!analysisOptions.incremental) { | 1073 if (!analysisOptions.incremental || |
| 1074 !_tryPoorMansIncrementalResolution(source, newContents)) { |
| 1061 // Don't compare with old contents because the cache has already been | 1075 // Don't compare with old contents because the cache has already been |
| 1062 // updated, and we know at this point that it changed. | 1076 // updated, and we know at this point that it changed. |
| 1063 _sourceChanged(source, compareWithOld: false); | 1077 _sourceChanged(source, compareWithOld: false); |
| 1064 } | 1078 } |
| 1065 entry.setValue(CONTENT, newContents, TargetedResult.EMPTY_LIST); | 1079 entry.setValue(CONTENT, newContents, TargetedResult.EMPTY_LIST); |
| 1066 } else { | 1080 } else { |
| 1067 entry.modificationTime = _contentCache.getModificationStamp(source); | 1081 entry.modificationTime = _contentCache.getModificationStamp(source); |
| 1068 } | 1082 } |
| 1069 } else if (originalContents != null) { | 1083 } else if (originalContents != null) { |
| 1070 // We are removing the overlay for the file, check if the file's | 1084 // We are removing the overlay for the file, check if the file's |
| 1071 // contents is the same as it was in the overlay. | 1085 // contents is the same as it was in the overlay. |
| 1072 try { | 1086 try { |
| 1073 TimestampedData<String> fileContents = getContents(source); | 1087 TimestampedData<String> fileContents = getContents(source); |
| 1074 newContents = fileContents.data; | 1088 newContents = fileContents.data; |
| 1075 entry.modificationTime = fileContents.modificationTime; | 1089 entry.modificationTime = fileContents.modificationTime; |
| 1076 if (newContents == originalContents) { | 1090 if (newContents == originalContents) { |
| 1077 entry.setValue(CONTENT, newContents, TargetedResult.EMPTY_LIST); | 1091 entry.setValue(CONTENT, newContents, TargetedResult.EMPTY_LIST); |
| 1078 changed = false; | 1092 changed = false; |
| 1079 } | 1093 } |
| 1080 } catch (e) {} | 1094 } catch (e) {} |
| 1081 // If not the same content (e.g. the file is being closed without save), | 1095 // If not the same content (e.g. the file is being closed without save), |
| 1082 // then force analysis. | 1096 // then force analysis. |
| 1083 if (changed) { | 1097 if (changed) { |
| 1084 if (newContents == null || !analysisOptions.incremental) { | 1098 if (newContents == null || |
| 1099 !analysisOptions.incremental || |
| 1100 !_tryPoorMansIncrementalResolution(source, newContents)) { |
| 1085 _sourceChanged(source); | 1101 _sourceChanged(source); |
| 1086 } | 1102 } |
| 1087 } | 1103 } |
| 1088 } | 1104 } |
| 1089 if (notify && changed) { | 1105 if (notify && changed) { |
| 1090 _onSourcesChangedController | 1106 _onSourcesChangedController |
| 1091 .add(new SourcesChangedEvent.changedContent(source, newContents)); | 1107 .add(new SourcesChangedEvent.changedContent(source, newContents)); |
| 1092 } | 1108 } |
| 1093 return changed; | 1109 return changed; |
| 1094 } | 1110 } |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1505 return null; | 1521 return null; |
| 1506 } | 1522 } |
| 1507 return ChangeNoticeImpl.EMPTY_LIST; | 1523 return ChangeNoticeImpl.EMPTY_LIST; |
| 1508 } | 1524 } |
| 1509 List<ChangeNotice> notices = new List.from(_pendingNotices.values); | 1525 List<ChangeNotice> notices = new List.from(_pendingNotices.values); |
| 1510 _pendingNotices.clear(); | 1526 _pendingNotices.clear(); |
| 1511 return notices; | 1527 return notices; |
| 1512 } | 1528 } |
| 1513 | 1529 |
| 1514 /** | 1530 /** |
| 1531 * Return a [CompilationUnit] for the given library and unit sources, which |
| 1532 * can be incrementally resolved. |
| 1533 */ |
| 1534 CompilationUnit _getIncrementallyResolvableUnit( |
| 1535 Source librarySource, Source unitSource) { |
| 1536 LibrarySpecificUnit target = |
| 1537 new LibrarySpecificUnit(librarySource, unitSource); |
| 1538 for (ResultDescriptor<CompilationUnit> result in [ |
| 1539 RESOLVED_UNIT, |
| 1540 RESOLVED_UNIT12, |
| 1541 RESOLVED_UNIT11, |
| 1542 RESOLVED_UNIT10, |
| 1543 RESOLVED_UNIT9, |
| 1544 RESOLVED_UNIT8 |
| 1545 ]) { |
| 1546 CompilationUnit unit = getResult(target, result); |
| 1547 if (unit != null) { |
| 1548 return unit; |
| 1549 } |
| 1550 } |
| 1551 return null; |
| 1552 } |
| 1553 |
| 1554 /** |
| 1515 * Return a list containing all of the sources known to this context that have | 1555 * Return a list containing all of the sources known to this context that have |
| 1516 * the given [kind]. | 1556 * the given [kind]. |
| 1517 */ | 1557 */ |
| 1518 List<Source> _getSources(SourceKind kind) { | 1558 List<Source> _getSources(SourceKind kind) { |
| 1519 List<Source> sources = <Source>[]; | 1559 List<Source> sources = <Source>[]; |
| 1520 if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) { | 1560 if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) { |
| 1521 for (Source source in _cache.sources) { | 1561 for (Source source in _cache.sources) { |
| 1522 CacheEntry entry = _cache.get(source); | 1562 CacheEntry entry = _cache.get(source); |
| 1523 if (entry.getValue(SOURCE_KIND) == kind) { | 1563 if (entry.getValue(SOURCE_KIND) == kind) { |
| 1524 sources.add(source); | 1564 sources.add(source); |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1811 | 1851 |
| 1812 /** | 1852 /** |
| 1813 * Record that the given [source] has been removed. | 1853 * Record that the given [source] has been removed. |
| 1814 */ | 1854 */ |
| 1815 void _sourceRemoved(Source source) { | 1855 void _sourceRemoved(Source source) { |
| 1816 driver.reset(); | 1856 driver.reset(); |
| 1817 _removeFromCache(source); | 1857 _removeFromCache(source); |
| 1818 _removeFromPriorityOrder(source); | 1858 _removeFromPriorityOrder(source); |
| 1819 } | 1859 } |
| 1820 | 1860 |
| 1861 /** |
| 1862 * TODO(scheglov) A hackish, limited incremental resolution implementation. |
| 1863 */ |
| 1864 bool _tryPoorMansIncrementalResolution(Source unitSource, String newCode) { |
| 1865 return PerformanceStatistics.incrementalAnalysis.makeCurrentWhile(() { |
| 1866 incrementalResolutionValidation_lastUnitSource = null; |
| 1867 incrementalResolutionValidation_lastLibrarySource = null; |
| 1868 incrementalResolutionValidation_lastUnit = null; |
| 1869 // prepare the source entry |
| 1870 CacheEntry sourceEntry = _cache.get(unitSource); |
| 1871 if (sourceEntry == null) { |
| 1872 return false; |
| 1873 } |
| 1874 // prepare the (only) library source |
| 1875 List<Source> librarySources = getLibrariesContaining(unitSource); |
| 1876 if (librarySources.length != 1) { |
| 1877 return false; |
| 1878 } |
| 1879 Source librarySource = librarySources[0]; |
| 1880 // prepare the unit entry |
| 1881 CacheEntry unitEntry = |
| 1882 _cache.get(new LibrarySpecificUnit(librarySource, unitSource)); |
| 1883 if (unitEntry == null) { |
| 1884 return false; |
| 1885 } |
| 1886 // prepare the existing unit |
| 1887 CompilationUnit oldUnit = |
| 1888 _getIncrementallyResolvableUnit(librarySource, unitSource); |
| 1889 if (oldUnit == null) { |
| 1890 return false; |
| 1891 } |
| 1892 // do resolution |
| 1893 Stopwatch perfCounter = new Stopwatch()..start(); |
| 1894 PoorMansIncrementalResolver resolver = new PoorMansIncrementalResolver( |
| 1895 typeProvider, |
| 1896 unitSource, |
| 1897 _cache, |
| 1898 sourceEntry, |
| 1899 unitEntry, |
| 1900 oldUnit, |
| 1901 analysisOptions.incrementalApi); |
| 1902 bool success = resolver.resolve(newCode); |
| 1903 AnalysisEngine.instance.instrumentationService.logPerformance( |
| 1904 AnalysisPerformanceKind.INCREMENTAL, |
| 1905 perfCounter, |
| 1906 'success=$success,context_id=$_id,code_length=${newCode.length}'); |
| 1907 if (!success) { |
| 1908 return false; |
| 1909 } |
| 1910 // if validation, remember the result, but throw it away |
| 1911 if (analysisOptions.incrementalValidation) { |
| 1912 CompilationUnitElement compilationUnitElement = |
| 1913 resolutionMap.elementDeclaredByCompilationUnit(oldUnit); |
| 1914 incrementalResolutionValidation_lastUnitSource = |
| 1915 compilationUnitElement.source; |
| 1916 incrementalResolutionValidation_lastLibrarySource = |
| 1917 compilationUnitElement.library.source; |
| 1918 incrementalResolutionValidation_lastUnit = oldUnit; |
| 1919 return false; |
| 1920 } |
| 1921 // prepare notice |
| 1922 { |
| 1923 ChangeNoticeImpl notice = getNotice(unitSource); |
| 1924 notice.resolvedDartUnit = oldUnit; |
| 1925 AnalysisErrorInfo errorInfo = getErrors(unitSource); |
| 1926 notice.setErrors(errorInfo.errors, errorInfo.lineInfo); |
| 1927 } |
| 1928 // schedule |
| 1929 dartWorkManager.unitIncrementallyResolved(librarySource, unitSource); |
| 1930 // OK |
| 1931 driver.reset(); |
| 1932 return true; |
| 1933 }); |
| 1934 } |
| 1935 |
| 1821 static bool _samePatchPaths( | 1936 static bool _samePatchPaths( |
| 1822 Map<String, List<String>> a, Map<String, List<String>> b) { | 1937 Map<String, List<String>> a, Map<String, List<String>> b) { |
| 1823 if (a.length != b.length) return false; | 1938 if (a.length != b.length) return false; |
| 1824 for (var key in a.keys) { | 1939 for (var key in a.keys) { |
| 1825 if (!b.containsKey(key)) return false; | 1940 if (!b.containsKey(key)) return false; |
| 1826 var aValue = a[key]; | 1941 var aValue = a[key]; |
| 1827 var bValue = b[key]; | 1942 var bValue = b[key]; |
| 1828 if (aValue.length != bValue.length) return false; | 1943 if (aValue.length != bValue.length) return false; |
| 1829 for (var i = 0; i < aValue.length; i++) { | 1944 for (var i = 0; i < aValue.length; i++) { |
| 1830 if (aValue[i] != bValue[i]) return false; | 1945 if (aValue[i] != bValue[i]) return false; |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2112 } | 2227 } |
| 2113 DartSdk sdk = factory.dartSdk; | 2228 DartSdk sdk = factory.dartSdk; |
| 2114 if (sdk == null) { | 2229 if (sdk == null) { |
| 2115 throw new ArgumentError( | 2230 throw new ArgumentError( |
| 2116 "The source factory for an SDK analysis context must have a DartUriRes
olver"); | 2231 "The source factory for an SDK analysis context must have a DartUriRes
olver"); |
| 2117 } | 2232 } |
| 2118 return new AnalysisCache( | 2233 return new AnalysisCache( |
| 2119 <CachePartition>[AnalysisEngine.instance.partitionManager.forSdk(sdk)]); | 2234 <CachePartition>[AnalysisEngine.instance.partitionManager.forSdk(sdk)]); |
| 2120 } | 2235 } |
| 2121 } | 2236 } |
| OLD | NEW |