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

Side by Side Diff: pkg/front_end/lib/src/incremental/file_state.dart

Issue 2877193003: Start actually adding incrementality into incremental kernel generator. (Closed)
Patch Set: Created 3 years, 7 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) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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:async'; 5 import 'dart:async';
6 import 'dart:typed_data'; 6 import 'dart:typed_data';
7 7
8 import 'package:crypto/crypto.dart';
8 import 'package:front_end/file_system.dart'; 9 import 'package:front_end/file_system.dart';
9 import 'package:front_end/src/dependency_walker.dart' as graph; 10 import 'package:front_end/src/dependency_walker.dart' as graph;
10 import 'package:front_end/src/fasta/parser/top_level_parser.dart'; 11 import 'package:front_end/src/fasta/parser/top_level_parser.dart';
11 import 'package:front_end/src/fasta/scanner.dart'; 12 import 'package:front_end/src/fasta/scanner.dart';
12 import 'package:front_end/src/fasta/source/directive_listener.dart'; 13 import 'package:front_end/src/fasta/source/directive_listener.dart';
13 import 'package:front_end/src/fasta/translate_uri.dart'; 14 import 'package:front_end/src/fasta/translate_uri.dart';
15 import 'package:kernel/target/vm.dart';
14 16
15 /// Information about a file being compiled, explicitly or implicitly. 17 /// Information about a file being compiled, explicitly or implicitly.
16 /// 18 ///
17 /// It provides a consistent view on its properties. 19 /// It provides a consistent view on its properties.
18 /// 20 ///
19 /// The properties are not guaranteed to represent the most recent state 21 /// The properties are not guaranteed to represent the most recent state
20 /// of the file system. To update the file to the most recent state, [refresh] 22 /// of the file system. To update the file to the most recent state, [refresh]
21 /// should be called. 23 /// should be called.
22 class FileState { 24 class FileState {
23 final FileSystemState _fsState; 25 final FileSystemState _fsState;
24 26
27 /// The absolute URI of the file.
28 final Uri uri;
29
25 /// The resolved URI of the file in the file system. 30 /// The resolved URI of the file in the file system.
26 final Uri fileUri; 31 final Uri fileUri;
27 32
28 bool _exists; 33 bool _exists;
29 List<int> _content; 34 List<int> _content;
35 List<int> _contentHash;
30 36
31 List<FileState> _importedLibraries; 37 List<FileState> _importedLibraries;
32 List<FileState> _exportedLibraries; 38 List<FileState> _exportedLibraries;
33 List<FileState> _partFiles; 39 List<FileState> _partFiles;
34 40
41 Set<FileState> _directReferencedFiles = new Set<FileState>();
35 List<FileState> _directReferencedLibraries = <FileState>[]; 42 List<FileState> _directReferencedLibraries = <FileState>[];
36 43
37 FileState._(this._fsState, this.fileUri); 44 FileState._(this._fsState, this.uri, this.fileUri);
38 45
39 /// The content of the file. 46 /// The content of the file.
40 List<int> get content => _content; 47 List<int> get content => _content;
41 48
49 /**
50 * The MD5 hash of the [content].
51 */
52 List<int> get contentHash => _contentHash;
53
42 /// Libraries that this library file directly imports or exports. 54 /// Libraries that this library file directly imports or exports.
43 List<FileState> get directReferencedLibraries => _directReferencedLibraries; 55 List<FileState> get directReferencedLibraries => _directReferencedLibraries;
44 56
45 /// Whether the file exists. 57 /// Whether the file exists.
46 bool get exists => _exists; 58 bool get exists => _exists;
47 59
48 /// The list of the libraries exported by this library. 60 /// The list of the libraries exported by this library.
49 List<FileState> get exportedLibraries => _exportedLibraries; 61 List<FileState> get exportedLibraries => _exportedLibraries;
50 62
51 @override 63 @override
52 int get hashCode => fileUri.hashCode; 64 int get hashCode => uri.hashCode;
53 65
54 /// The list of the libraries imported by this library. 66 /// The list of the libraries imported by this library.
55 List<FileState> get importedLibraries => _importedLibraries; 67 List<FileState> get importedLibraries => _importedLibraries;
56 68
57 /// The list of files this library file references as parts. 69 /// The list of files this library file references as parts.
58 List<FileState> get partFiles => _partFiles; 70 List<FileState> get partFiles => _partFiles;
59 71
60 /// Return topologically sorted cycles of dependencies for this library. 72 /// Return topologically sorted cycles of dependencies for this library.
61 List<LibraryCycle> get topologicalOrder { 73 List<LibraryCycle> get topologicalOrder {
62 var libraryWalker = new _LibraryWalker(); 74 var libraryWalker = new _LibraryWalker();
63 libraryWalker.walk(libraryWalker.getNode(this)); 75 libraryWalker.walk(libraryWalker.getNode(this));
64 return libraryWalker.topologicallySortedCycles; 76 return libraryWalker.topologicallySortedCycles;
65 } 77 }
66 78
79 /// Return the set of transitive files - the file itself and all of the
80 /// directly or indirectly referenced files.
81 Set<FileState> get transitiveFiles {
82 // TODO(scheglov) add caching.
83 var transitiveFiles = new Set<FileState>();
84
85 void appendReferenced(FileState file) {
86 if (transitiveFiles.add(file)) {
87 file._directReferencedFiles.forEach(appendReferenced);
88 }
89 }
90
91 appendReferenced(this);
92 return transitiveFiles;
93 }
94
67 @override 95 @override
68 bool operator ==(Object other) { 96 bool operator ==(Object other) {
69 return other is FileState && other.fileUri == fileUri; 97 return other is FileState && other.uri == uri;
70 } 98 }
71 99
72 /// Read the file content and ensure that all of the file properties are 100 /// Read the file content and ensure that all of the file properties are
73 /// consistent with the read content, including all its dependencies. 101 /// consistent with the read content, including all its dependencies.
74 Future<Null> refresh() async { 102 Future<Null> refresh() async {
75 // Read the content. 103 // Read the content.
76 try { 104 try {
77 FileSystemEntity entry = _fsState.fileSystem.entityForUri(fileUri); 105 FileSystemEntity entry = _fsState.fileSystem.entityForUri(fileUri);
78 _content = await entry.readAsBytes(); 106 _content = await entry.readAsBytes();
79 _exists = true; 107 _exists = true;
80 } catch (_) { 108 } catch (_) {
81 _content = new Uint8List(0); 109 _content = new Uint8List(0);
82 _exists = false; 110 _exists = false;
83 } 111 }
84 112
113 // Compute the content hash.
114 _contentHash = md5.convert(_content).bytes;
115
85 // Parse directives. 116 // Parse directives.
86 ScannerResult scannerResults = _scan(); 117 ScannerResult scannerResults = _scan();
87 var listener = new DirectiveListener(); 118 var listener = new DirectiveListener();
88 new TopLevelParser(listener).parseUnit(scannerResults.tokens); 119 new TopLevelParser(listener).parseUnit(scannerResults.tokens);
89 120
90 // Build the graph. 121 // Build the graph.
91 _importedLibraries = <FileState>[]; 122 _importedLibraries = <FileState>[];
92 _exportedLibraries = <FileState>[]; 123 _exportedLibraries = <FileState>[];
93 _partFiles = <FileState>[]; 124 _partFiles = <FileState>[];
94 await _addFileForRelativeUri(_importedLibraries, 'dart:core'); 125 await _addFileForRelativeUri(_importedLibraries, 'dart:core');
95 for (String uri in listener.imports) { 126 for (String uri in listener.imports) {
96 await _addFileForRelativeUri(_importedLibraries, uri); 127 await _addFileForRelativeUri(_importedLibraries, uri);
97 } 128 }
129 await _addVmTargetImportsForCore();
98 for (String uri in listener.exports) { 130 for (String uri in listener.exports) {
99 await _addFileForRelativeUri(_exportedLibraries, uri); 131 await _addFileForRelativeUri(_exportedLibraries, uri);
100 } 132 }
101 for (String uri in listener.parts) { 133 for (String uri in listener.parts) {
102 await _addFileForRelativeUri(_partFiles, uri); 134 await _addFileForRelativeUri(_partFiles, uri);
103 } 135 }
104 136
105 // Compute referenced libraries. 137 // Compute referenced files.
138 _directReferencedFiles = new Set<FileState>()
139 ..addAll(_importedLibraries)
140 ..addAll(_exportedLibraries)
141 ..addAll(_partFiles);
106 _directReferencedLibraries = (new Set<FileState>() 142 _directReferencedLibraries = (new Set<FileState>()
107 ..addAll(_importedLibraries) 143 ..addAll(_importedLibraries)
108 ..addAll(_exportedLibraries)) 144 ..addAll(_exportedLibraries))
109 .toList(); 145 .toList();
110 } 146 }
111 147
112 @override 148 @override
113 String toString() { 149 String toString() {
114 if (fileUri.scheme == 'file') return fileUri.path; 150 if (fileUri.scheme == 'file') return fileUri.path;
115 return fileUri.toString(); 151 return fileUri.toString();
116 } 152 }
117 153
118 /// Add the [FileState] for the given [relativeUri] to the [files]. 154 /// Add the [FileState] for the given [relativeUri] to the [files].
119 /// Do nothing if the URI cannot be parsed, cannot correspond any file, etc. 155 /// Do nothing if the URI cannot be parsed, cannot correspond any file, etc.
120 Future<Null> _addFileForRelativeUri( 156 Future<Null> _addFileForRelativeUri(
121 List<FileState> files, String relativeUri) async { 157 List<FileState> files, String relativeUri) async {
122 if (relativeUri.isEmpty) return; 158 if (relativeUri.isEmpty) return;
123 159
124 // Resolve the relative URI into absolute. 160 // Resolve the relative URI into absolute.
125 // The result is either: 161 // The result is either:
126 // 1) The absolute file URI. 162 // 1) The absolute file URI.
127 // 2) The absolute non-file URI, e.g. `package:foo/foo.dart`. 163 // 2) The absolute non-file URI, e.g. `package:foo/foo.dart`.
128 Uri absoluteUri; 164 Uri absoluteUri;
129 try { 165 try {
130 absoluteUri = fileUri.resolve(relativeUri); 166 absoluteUri = fileUri.resolve(relativeUri);
131 } on FormatException { 167 } on FormatException {
132 return; 168 return;
133 } 169 }
134 170
135 // Resolve the absolute URI into the absolute file URI. 171 FileState file = await _fsState.getFile(absoluteUri);
136 Uri resolvedUri; 172 if (file == null) return;
137 if (absoluteUri.isScheme('file')) { 173 files.add(file);
138 resolvedUri = absoluteUri; 174 }
139 } else { 175
140 resolvedUri = _fsState.uriTranslator.translate(absoluteUri); 176 /// Fasta unconditionally loads all VM libraries. In order to be able to
141 if (resolvedUri == null) return; 177 /// serve them using the file system view, pretend that all of them were
178 /// imported into `dart:core`.
Paul Berry 2017/05/12 22:24:57 I assume this is a temporary workaround, and we sh
scheglov 2017/05/13 02:32:58 I added TODO that we need to ask VM for requiremen
Paul Berry 2017/05/13 02:56:50 sgtm, thanks.
179 Future<Null> _addVmTargetImportsForCore() async {
180 if (uri.toString() != 'dart:core') return;
181 for (String uri in new VmTarget(null).extraRequiredLibraries) {
182 await _addFileForRelativeUri(_importedLibraries, uri);
142 } 183 }
143
144 FileState file = await _fsState.getFile(resolvedUri);
145 files.add(file);
146 } 184 }
147 185
148 /// Scan the content of the file. 186 /// Scan the content of the file.
149 ScannerResult _scan() { 187 ScannerResult _scan() {
150 var zeroTerminatedBytes = new Uint8List(_content.length + 1); 188 var zeroTerminatedBytes = new Uint8List(_content.length + 1);
151 zeroTerminatedBytes.setRange(0, _content.length, _content); 189 zeroTerminatedBytes.setRange(0, _content.length, _content);
152 return scan(zeroTerminatedBytes); 190 return scan(zeroTerminatedBytes);
153 } 191 }
154 } 192 }
155 193
(...skipping 10 matching lines...) Expand all
166 FileSystemState(this.fileSystem, this.uriTranslator); 204 FileSystemState(this.fileSystem, this.uriTranslator);
167 205
168 /// Return the [FileSystem] that is backed by this [FileSystemState]. The 206 /// Return the [FileSystem] that is backed by this [FileSystemState]. The
169 /// files in this [FileSystem] always have the same content as the 207 /// files in this [FileSystem] always have the same content as the
170 /// corresponding [FileState]s, thus avoiding race conditions when a file 208 /// corresponding [FileState]s, thus avoiding race conditions when a file
171 /// is updated on the actual file system. 209 /// is updated on the actual file system.
172 FileSystem get fileSystemView { 210 FileSystem get fileSystemView {
173 return _fileSystemView ??= new _FileSystemView(this); 211 return _fileSystemView ??= new _FileSystemView(this);
174 } 212 }
175 213
176 /// Return the [FileState] for the given resolved file [fileUri]. 214 /// Return the [FileState] for the given [absoluteUri], or `null` if the
215 /// [absoluteUri] cannot be resolved into a file URI.
216 ///
177 /// The returned file has the last known state since it was last refreshed. 217 /// The returned file has the last known state since it was last refreshed.
178 Future<FileState> getFile(Uri fileUri) async { 218 Future<FileState> getFile(Uri absoluteUri) async {
179 FileState file = _fileUriToFile[fileUri]; 219 // Resolve the absolute URI into the absolute file URI.
220 Uri fileUri;
221 if (absoluteUri.isScheme('file')) {
222 fileUri = absoluteUri;
223 } else {
224 fileUri = uriTranslator.translate(absoluteUri);
225 if (fileUri == null) return null;
226 }
227
228 FileState file = _fileUriToFile[absoluteUri];
180 if (file == null) { 229 if (file == null) {
181 file = new FileState._(this, fileUri); 230 file = new FileState._(this, absoluteUri, fileUri);
231 _fileUriToFile[absoluteUri] = file;
182 _fileUriToFile[fileUri] = file; 232 _fileUriToFile[fileUri] = file;
183 233
184 // Build the sub-graph of the file. 234 // Build the sub-graph of the file.
185 await file.refresh(); 235 await file.refresh();
186 } 236 }
187 return file; 237 return file;
188 } 238 }
189 } 239 }
190 240
191 /// List of libraries that reference each other, so form a cycle. 241 /// List of libraries that reference each other, so form a cycle.
192 class LibraryCycle { 242 class LibraryCycle {
193 final List<FileState> libraries = <FileState>[]; 243 final List<FileState> libraries = <FileState>[];
194 244
245 bool get _isForVm {
246 return libraries.any((l) => l.uri.toString().endsWith('dart:_vmservice'));
247 }
248
195 @override 249 @override
196 String toString() => '[' + libraries.join(', ') + ']'; 250 String toString() {
251 if (_isForVm) {
252 return '[core + vm]';
253 }
254 return '[' + libraries.join(', ') + ']';
255 }
197 } 256 }
198 257
199 /// [FileSystemState] based implementation of [FileSystem]. 258 /// [FileSystemState] based implementation of [FileSystem].
200 /// It provides a consistent view on the known file system state. 259 /// It provides a consistent view on the known file system state.
201 class _FileSystemView implements FileSystem { 260 class _FileSystemView implements FileSystem {
202 final FileSystemState fsState; 261 final FileSystemState fsState;
203 262
204 _FileSystemView(this.fsState); 263 _FileSystemView(this.fsState);
205 264
206 @override 265 @override
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 node.isEvaluated = true; 338 node.isEvaluated = true;
280 cycle.libraries.add(node.file); 339 cycle.libraries.add(node.file);
281 } 340 }
282 topologicallySortedCycles.add(cycle); 341 topologicallySortedCycles.add(cycle);
283 } 342 }
284 343
285 _LibraryNode getNode(FileState file) { 344 _LibraryNode getNode(FileState file) {
286 return nodesOfFiles.putIfAbsent(file, () => new _LibraryNode(this, file)); 345 return nodesOfFiles.putIfAbsent(file, () => new _LibraryNode(this, file));
287 } 346 }
288 } 347 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698