Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: pkg/analyzer/lib/src/summary/incremental_cache.dart

Issue 1814013004: Add source kind to the incremental cache. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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 import 'dart:convert' show UTF8; 5 import 'dart:convert' show UTF8;
6 import 'dart:core' hide Resource; 6 import 'dart:core' hide Resource;
7 7
8 import 'package:analyzer/dart/element/element.dart'; 8 import 'package:analyzer/dart/element/element.dart';
9 import 'package:analyzer/file_system/file_system.dart'; 9 import 'package:analyzer/file_system/file_system.dart';
10 import 'package:analyzer/src/generated/engine.dart'; 10 import 'package:analyzer/src/generated/engine.dart';
(...skipping 25 matching lines...) Expand all
36 * The context in which this cache is used. 36 * The context in which this cache is used.
37 */ 37 */
38 final AnalysisContext context; 38 final AnalysisContext context;
39 39
40 /** 40 /**
41 * Opaque data that reflects the current configuration, such as the [context] 41 * Opaque data that reflects the current configuration, such as the [context]
42 * options, and is mixed into the hashes. 42 * options, and is mixed into the hashes.
43 */ 43 */
44 final List<int> configSalt; 44 final List<int> configSalt;
45 45
46 final Map<Source, CacheLibraryUris> _libraryUrisMap = 46 final Map<Source, CacheSourceContent> _sourceContentMap =
47 <Source, CacheLibraryUris>{}; 47 <Source, CacheSourceContent>{};
48 final Map<Source, List<Source>> _libraryClosureMap = <Source, List<Source>>{}; 48 final Map<Source, List<Source>> _libraryClosureMap = <Source, List<Source>>{};
49 final Map<Source, List<int>> _sourceContentHashMap = <Source, List<int>>{}; 49 final Map<Source, List<int>> _sourceContentHashMap = <Source, List<int>>{};
50 50
51 LibraryBundleCache( 51 LibraryBundleCache(
52 this.tempFileName, this.cacheFolder, this.context, this.configSalt); 52 this.tempFileName, this.cacheFolder, this.context, this.configSalt);
53 53
54 /** 54 /**
55 * Clear internal caches so that we read from file system again. 55 * Clear internal caches so that we read from file system again.
56 */ 56 */
57 void clearInternalCaches() { 57 void clearInternalCaches() {
58 _libraryUrisMap.clear(); 58 _sourceContentMap.clear();
59 _libraryClosureMap.clear(); 59 _libraryClosureMap.clear();
60 _sourceContentHashMap.clear(); 60 _sourceContentHashMap.clear();
61 } 61 }
62 62
63 /** 63 /**
64 * Return the kind of the given [source], or `null` if unknown.
65 */
66 SourceKind getSourceKind(Source source) {
67 try {
68 CacheSourceContent contentSource = _getCacheSourceContent(source);
69 if (contentSource != null) {
70 if (contentSource.kind == CacheSourceKind.library) {
71 return SourceKind.LIBRARY;
72 }
73 if (contentSource.kind == CacheSourceKind.part) {
74 return SourceKind.PART;
75 }
76 }
77 } catch (e) {}
78 return null;
79 }
80
81 /**
64 * Write information about the [library] into the cache. 82 * Write information about the [library] into the cache.
65 */ 83 */
66 void putLibrary(LibraryElement library) { 84 void putLibrary(LibraryElement library) {
67 try { 85 try {
68 _writeUris(library); 86 _writeCacheSourceContents(library);
69 List<int> hash = _getLibraryClosureHash(library.source); 87 List<int> hash = _getLibraryClosureHash(library.source);
70 String hashStr = CryptoUtils.bytesToHex(hash); 88 String hashStr = CryptoUtils.bytesToHex(hash);
71 PackageBundleAssembler assembler = new PackageBundleAssembler(); 89 PackageBundleAssembler assembler = new PackageBundleAssembler();
72 assembler.serializeLibraryElement(library); 90 assembler.serializeLibraryElement(library);
73 List<int> bytes = assembler.assemble().toBuffer(); 91 List<int> bytes = assembler.assemble().toBuffer();
74 _safeWriteBytes('$hashStr.sum', bytes); 92 _safeWriteBytes('$hashStr.sum', bytes);
75 } catch (e) {} 93 } catch (e) {}
76 } 94 }
77 95
78 /** 96 /**
(...skipping 16 matching lines...) Expand all
95 } 113 }
96 } 114 }
97 115
98 /** 116 /**
99 * Fill the whole source closure of the library with the given 117 * Fill the whole source closure of the library with the given
100 * [librarySource]. It includes defining units and parts of the library and 118 * [librarySource]. It includes defining units and parts of the library and
101 * all its directly or indirectly imported or exported libraries. 119 * all its directly or indirectly imported or exported libraries.
102 */ 120 */
103 void _appendLibraryClosure(Set<Source> closure, Source librarySource) { 121 void _appendLibraryClosure(Set<Source> closure, Source librarySource) {
104 if (closure.add(librarySource)) { 122 if (closure.add(librarySource)) {
105 CacheLibraryUris libraryUris = _getUris(librarySource); 123 CacheSourceContent contentSource = _getCacheSourceContent(librarySource);
106 if (libraryUris == null) { 124 if (contentSource == null) {
107 throw new StateError('No URIs for $librarySource'); 125 throw new StateError('No structure for $librarySource');
108 } 126 }
109 // Append parts. 127 // Append parts.
110 for (String partUri in libraryUris.partUris) { 128 for (String partUri in contentSource.partUris) {
111 Source partSource = 129 Source partSource =
112 context.sourceFactory.resolveUri(librarySource, partUri); 130 context.sourceFactory.resolveUri(librarySource, partUri);
113 if (partSource == null) { 131 if (partSource == null) {
114 throw new StateError('Unable to resolve $partUri in $librarySource'); 132 throw new StateError('Unable to resolve $partUri in $librarySource');
115 } 133 }
116 closure.add(partSource); 134 closure.add(partSource);
117 } 135 }
118 // Append imports and exports. 136 // Append imports and exports.
119 void appendLibrarySources(String refUri) { 137 void appendLibrarySources(String refUri) {
120 Source refSource = 138 Source refSource =
121 context.sourceFactory.resolveUri(librarySource, refUri); 139 context.sourceFactory.resolveUri(librarySource, refUri);
122 if (refSource == null) { 140 if (refSource == null) {
123 throw new StateError('Unable to resolve $refUri in $librarySource'); 141 throw new StateError('Unable to resolve $refUri in $librarySource');
124 } 142 }
125 _appendLibraryClosure(closure, refSource); 143 _appendLibraryClosure(closure, refSource);
126 } 144 }
127 libraryUris.importedUris.forEach(appendLibrarySources); 145 contentSource.importedUris.forEach(appendLibrarySources);
128 libraryUris.exportedUris.forEach(appendLibrarySources); 146 contentSource.exportedUris.forEach(appendLibrarySources);
129 } 147 }
130 } 148 }
131 149
132 /** 150 /**
151 * Get the content based information about the given [source], maybe `null`
152 * if the information is not in the cache.
153 */
154 CacheSourceContent _getCacheSourceContent(Source source) {
155 CacheSourceContent content = _sourceContentMap[source];
156 if (content == null) {
157 String fileName = _getCacheSourceContentFileName(source);
158 List<int> bytes = _safeReadBytes(fileName);
159 if (bytes == null) {
160 return null;
161 }
162 content = new CacheSourceContent.fromBuffer(bytes);
163 _sourceContentMap[source] = content;
164 }
165 return content;
166 }
167
168 /**
169 * Return the name of the file with the content based [source] information.
170 */
171 String _getCacheSourceContentFileName(Source source) {
172 List<int> hash = _getSourceContentHash(source);
173 String hashStr = CryptoUtils.bytesToHex(hash);
174 return '$hashStr.content';
175 }
176
177 /**
133 * Return the whole source closure of the library with the given 178 * Return the whole source closure of the library with the given
134 * [librarySource]. It includes defining units and parts of the library and 179 * [librarySource]. It includes defining units and parts of the library and
135 * of all its directly or indirectly imported or exported libraries. 180 * of all its directly or indirectly imported or exported libraries.
136 */ 181 */
137 List<Source> _getLibraryClosure(Source librarySource) { 182 List<Source> _getLibraryClosure(Source librarySource) {
138 return _libraryClosureMap.putIfAbsent(librarySource, () { 183 return _libraryClosureMap.putIfAbsent(librarySource, () {
139 Set<Source> closure = new Set<Source>(); 184 Set<Source> closure = new Set<Source>();
140 _appendLibraryClosure(closure, librarySource); 185 _appendLibraryClosure(closure, librarySource);
141 return closure.toList(); 186 return closure.toList();
142 }); 187 });
(...skipping 19 matching lines...) Expand all
162 */ 207 */
163 List<int> _getSourceContentHash(Source source) { 208 List<int> _getSourceContentHash(Source source) {
164 return _sourceContentHashMap.putIfAbsent(source, () { 209 return _sourceContentHashMap.putIfAbsent(source, () {
165 String sourceText = source.contents.data; 210 String sourceText = source.contents.data;
166 List<int> sourceBytes = UTF8.encode(sourceText); 211 List<int> sourceBytes = UTF8.encode(sourceText);
167 return (new MD5()..add(sourceBytes)).close(); 212 return (new MD5()..add(sourceBytes)).close();
168 }); 213 });
169 } 214 }
170 215
171 /** 216 /**
172 * Get the URIs information of the library with the given [librarySource],
173 * maybe `null` if the information is not in the cache.
174 */
175 CacheLibraryUris _getUris(Source librarySource) {
176 CacheLibraryUris uris = _libraryUrisMap[librarySource];
177 if (uris == null) {
178 String fileName = _getUrisFileName(librarySource);
179 List<int> bytes = _safeReadBytes(fileName);
180 if (bytes == null) {
181 return null;
182 }
183 uris = new CacheLibraryUris.fromBuffer(bytes);
184 _libraryUrisMap[librarySource] = uris;
185 }
186 return uris;
187 }
188
189 /**
190 * Return the name of the file with the [librarySource] URIs information.
191 */
192 String _getUrisFileName(Source librarySource) {
193 List<int> hash = _getSourceContentHash(librarySource);
194 String hashStr = CryptoUtils.bytesToHex(hash);
195 return '$hashStr.uris';
196 }
197
198 /**
199 * Return bytes of the file with the given [relPath] in the cache, or `null` 217 * Return bytes of the file with the given [relPath] in the cache, or `null`
200 * if the file does not exist. 218 * if the file does not exist.
201 */ 219 */
202 List<int> _safeReadBytes(String relPath) { 220 List<int> _safeReadBytes(String relPath) {
203 Resource urisFile = cacheFolder.getChild(relPath); 221 Resource file = cacheFolder.getChild(relPath);
204 if (urisFile is File) { 222 if (file is File) {
205 try { 223 try {
206 return urisFile.readAsBytesSync(); 224 return file.readAsBytesSync();
207 } on FileSystemException {} 225 } on FileSystemException {}
208 } 226 }
209 return null; 227 return null;
210 } 228 }
211 229
212 /** 230 /**
213 * Atomically write the given [bytes] into the file with the given [relPath]. 231 * Atomically write the given [bytes] into the file with the given [relPath].
214 * Silently ignores any errors. 232 * Silently ignores any errors.
215 */ 233 */
216 void _safeWriteBytes(String relPath, List<int> bytes) { 234 void _safeWriteBytes(String relPath, List<int> bytes) {
217 try { 235 try {
218 String absPath = cacheFolder.getChild(relPath).path; 236 String absPath = cacheFolder.getChild(relPath).path;
219 File tempFile = cacheFolder.getChild(tempFileName); 237 File tempFile = cacheFolder.getChild(tempFileName);
220 tempFile.writeAsBytesSync(bytes); 238 tempFile.writeAsBytesSync(bytes);
221 tempFile.renameSync(absPath); 239 tempFile.renameSync(absPath);
222 } catch (e) {} 240 } catch (e) {}
223 } 241 }
224 242
225 /** 243 /**
226 * Write URIs information for the given [library] and its direct and 244 * Write the content based information about the given [source].
227 * indirect imports/exports.
228 */ 245 */
229 void _writeUris(LibraryElement library, 246 void _writeCacheSourceContent(Source source, CacheSourceContentBuilder b) {
247 String fileName = _getCacheSourceContentFileName(source);
248 List<int> bytes = b.toBuffer();
249 _safeWriteBytes(fileName, bytes);
250 // Put into the cache to avoid reading it later.
251 _sourceContentMap[source] = new CacheSourceContent.fromBuffer(bytes);
252 }
253
254 /**
255 * Write [CacheSourceContent] for every unit of the given [library] and its
256 * direct and indirect imports/exports.
257 */
258 void _writeCacheSourceContents(LibraryElement library,
230 [Set<LibraryElement> writtenLibraries]) { 259 [Set<LibraryElement> writtenLibraries]) {
231 Source librarySource = library.source; 260 Source librarySource = library.source;
232 // Do nothing if already cached. 261 // Do nothing if already cached.
233 if (_libraryUrisMap.containsKey(librarySource)) { 262 if (_sourceContentMap.containsKey(librarySource)) {
234 return; 263 return;
235 } 264 }
236 // Stop recursion cycle. 265 // Stop recursion cycle.
237 writtenLibraries ??= new Set<LibraryElement>(); 266 writtenLibraries ??= new Set<LibraryElement>();
238 if (!writtenLibraries.add(library)) { 267 if (!writtenLibraries.add(library)) {
239 return; 268 return;
240 } 269 }
241 // Prepare import/export URIs. 270 // Write parts.
271 List<String> partUris = <String>[];
272 for (CompilationUnitElement part in library.parts) {
273 partUris.add(part.uri);
274 _writeCacheSourceContent(part.source,
Paul Berry 2016/03/18 18:38:14 As per our discussion, this could corrupt the cach
scheglov 2016/03/18 19:42:06 Done.
275 new CacheSourceContentBuilder(kind: CacheSourceKind.part));
276 }
277 // Write imports.
242 List<String> importUris = <String>[]; 278 List<String> importUris = <String>[];
243 List<String> exportUris = <String>[];
244 for (ImportElement element in library.imports) { 279 for (ImportElement element in library.imports) {
245 String uri = element.uri; 280 String uri = element.uri;
246 if (uri != null) { 281 if (uri != null) {
247 importUris.add(uri); 282 importUris.add(uri);
248 _writeUris(element.importedLibrary, writtenLibraries); 283 _writeCacheSourceContents(element.importedLibrary, writtenLibraries);
249 } 284 }
250 } 285 }
286 // Write exports.
287 List<String> exportUris = <String>[];
251 for (ExportElement element in library.exports) { 288 for (ExportElement element in library.exports) {
252 String uri = element.uri; 289 String uri = element.uri;
253 if (uri != null) { 290 if (uri != null) {
254 exportUris.add(uri); 291 exportUris.add(uri);
255 _writeUris(element.exportedLibrary, writtenLibraries); 292 _writeCacheSourceContents(element.exportedLibrary, writtenLibraries);
256 } 293 }
257 } 294 }
258 // Write the URIs. 295 // Write the library.
259 CacheLibraryUrisBuilder b = new CacheLibraryUrisBuilder( 296 _writeCacheSourceContent(
260 importedUris: importUris, 297 librarySource,
261 exportedUris: exportUris, 298 new CacheSourceContentBuilder(
262 partUris: library.parts.map((e) => e.uri).toList()); 299 kind: CacheSourceKind.library,
263 List<int> bytes = b.toBuffer(); 300 importedUris: importUris,
264 String fileName = _getUrisFileName(librarySource); 301 exportedUris: exportUris,
265 _safeWriteBytes(fileName, bytes); 302 partUris: partUris));
266 // Put into the cache to avoid reading it later.
267 _libraryUrisMap[librarySource] = new CacheLibraryUris.fromBuffer(bytes);
268 } 303 }
269 } 304 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698