OLD | NEW |
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'; | 5 import 'dart:convert'; |
6 import 'dart:typed_data'; | 6 import 'dart:typed_data'; |
7 | 7 |
8 import 'package:analyzer/dart/ast/ast.dart'; | 8 import 'package:analyzer/dart/ast/ast.dart'; |
9 import 'package:analyzer/dart/ast/token.dart'; | 9 import 'package:analyzer/dart/ast/token.dart'; |
10 import 'package:analyzer/error/listener.dart'; | 10 import 'package:analyzer/error/listener.dart'; |
11 import 'package:analyzer/file_system/file_system.dart'; | 11 import 'package:analyzer/file_system/file_system.dart'; |
12 import 'package:analyzer/src/dart/analysis/byte_store.dart'; | 12 import 'package:analyzer/src/dart/analysis/byte_store.dart'; |
13 import 'package:analyzer/src/dart/analysis/driver.dart'; | 13 import 'package:analyzer/src/dart/analysis/driver.dart'; |
14 import 'package:analyzer/src/dart/scanner/reader.dart'; | 14 import 'package:analyzer/src/dart/scanner/reader.dart'; |
15 import 'package:analyzer/src/dart/scanner/scanner.dart'; | 15 import 'package:analyzer/src/dart/scanner/scanner.dart'; |
16 import 'package:analyzer/src/generated/engine.dart'; | 16 import 'package:analyzer/src/generated/engine.dart'; |
17 import 'package:analyzer/src/generated/parser.dart'; | 17 import 'package:analyzer/src/generated/parser.dart'; |
18 import 'package:analyzer/src/generated/source.dart'; | 18 import 'package:analyzer/src/generated/source.dart'; |
19 import 'package:analyzer/src/generated/utilities_dart.dart'; | 19 import 'package:analyzer/src/generated/utilities_dart.dart'; |
20 import 'package:analyzer/src/source/source_resource.dart'; | 20 import 'package:analyzer/src/source/source_resource.dart'; |
21 import 'package:analyzer/src/summary/api_signature.dart'; | 21 import 'package:analyzer/src/summary/api_signature.dart'; |
22 import 'package:analyzer/src/summary/format.dart'; | 22 import 'package:analyzer/src/summary/format.dart'; |
23 import 'package:analyzer/src/summary/idl.dart'; | 23 import 'package:analyzer/src/summary/idl.dart'; |
24 import 'package:analyzer/src/summary/summarize_ast.dart'; | 24 import 'package:analyzer/src/summary/summarize_ast.dart'; |
25 import 'package:analyzer/src/util/fast_uri.dart'; | 25 import 'package:analyzer/src/util/fast_uri.dart'; |
26 import 'package:convert/convert.dart'; | 26 import 'package:convert/convert.dart'; |
27 import 'package:crypto/crypto.dart'; | 27 import 'package:crypto/crypto.dart'; |
| 28 import 'package:meta/meta.dart'; |
28 | 29 |
29 /** | 30 /** |
30 * [FileContentOverlay] is used to temporary override content of files. | 31 * [FileContentOverlay] is used to temporary override content of files. |
31 */ | 32 */ |
32 class FileContentOverlay { | 33 class FileContentOverlay { |
33 final _map = <String, String>{}; | 34 final _map = <String, String>{}; |
34 | 35 |
35 /** | 36 /** |
36 * Return the content of the file with the given [path], or `null` the | 37 * Return the content of the file with the given [path], or `null` the |
37 * overlay does not override the content of the file. | 38 * overlay does not override the content of the file. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 | 84 |
84 String _content; | 85 String _content; |
85 String _contentHash; | 86 String _contentHash; |
86 LineInfo _lineInfo; | 87 LineInfo _lineInfo; |
87 UnlinkedUnit _unlinked; | 88 UnlinkedUnit _unlinked; |
88 List<int> _apiSignature; | 89 List<int> _apiSignature; |
89 | 90 |
90 List<FileState> _importedFiles; | 91 List<FileState> _importedFiles; |
91 List<FileState> _exportedFiles; | 92 List<FileState> _exportedFiles; |
92 List<FileState> _partedFiles; | 93 List<FileState> _partedFiles; |
93 List<FileState> _dependencies; | 94 Set<FileState> _directReferencedFiles = new Set<FileState>(); |
| 95 Set<FileState> _transitiveFiles; |
94 | 96 |
95 FileState._(this._fsState, this.path, this.uri, this.source); | 97 FileState._(this._fsState, this.path, this.uri, this.source); |
96 | 98 |
97 /** | 99 /** |
98 * The unlinked API signature of the file. | 100 * The unlinked API signature of the file. |
99 */ | 101 */ |
100 List<int> get apiSignature => _apiSignature; | 102 List<int> get apiSignature => _apiSignature; |
101 | 103 |
102 /** | 104 /** |
103 * The content of the file. | 105 * The content of the file. |
104 */ | 106 */ |
105 String get content => _content; | 107 String get content => _content; |
106 | 108 |
107 /** | 109 /** |
108 * The MD5 hash of the [content]. | 110 * The MD5 hash of the [content]. |
109 */ | 111 */ |
110 String get contentHash => _contentHash; | 112 String get contentHash => _contentHash; |
111 | 113 |
112 /** | 114 /** |
113 * Return the list of all direct dependencies. | 115 * Return the set of all directly referenced files - imported, exported or |
| 116 * parted. |
114 */ | 117 */ |
115 List<FileState> get dependencies => _dependencies; | 118 Set<FileState> get directReferencedFiles => _directReferencedFiles; |
116 | 119 |
117 /** | 120 /** |
118 * The list of files this file exports. | 121 * The list of files this file exports. |
119 */ | 122 */ |
120 List<FileState> get exportedFiles => _exportedFiles; | 123 List<FileState> get exportedFiles => _exportedFiles; |
121 | 124 |
122 @override | 125 @override |
123 int get hashCode => uri.hashCode; | 126 int get hashCode => uri.hashCode; |
124 | 127 |
125 /** | 128 /** |
(...skipping 24 matching lines...) Expand all Loading... |
150 * Return information about line in the file. | 153 * Return information about line in the file. |
151 */ | 154 */ |
152 LineInfo get lineInfo => _lineInfo; | 155 LineInfo get lineInfo => _lineInfo; |
153 | 156 |
154 /** | 157 /** |
155 * The list of files this library file references as parts. | 158 * The list of files this library file references as parts. |
156 */ | 159 */ |
157 List<FileState> get partedFiles => _partedFiles; | 160 List<FileState> get partedFiles => _partedFiles; |
158 | 161 |
159 /** | 162 /** |
| 163 * Return the set of transitive files - the file itself and all of the |
| 164 * directly or indirectly referenced files. |
| 165 */ |
| 166 Set<FileState> get transitiveFiles { |
| 167 if (_transitiveFiles == null) { |
| 168 _transitiveFiles = new Set<FileState>(); |
| 169 |
| 170 void appendReferenced(FileState file) { |
| 171 if (_transitiveFiles.add(file)) { |
| 172 file._directReferencedFiles.forEach(appendReferenced); |
| 173 } |
| 174 } |
| 175 |
| 176 appendReferenced(this); |
| 177 } |
| 178 return _transitiveFiles; |
| 179 } |
| 180 |
| 181 /** |
160 * The [UnlinkedUnit] of the file. | 182 * The [UnlinkedUnit] of the file. |
161 */ | 183 */ |
162 UnlinkedUnit get unlinked => _unlinked; | 184 UnlinkedUnit get unlinked => _unlinked; |
163 | 185 |
164 @override | 186 @override |
165 bool operator ==(Object other) { | 187 bool operator ==(Object other) { |
166 return other is FileState && other.uri == uri; | 188 return other is FileState && other.uri == uri; |
167 } | 189 } |
168 | 190 |
169 /** | 191 /** |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 if (file != null) { | 304 if (file != null) { |
283 _partedFiles.add(file); | 305 _partedFiles.add(file); |
284 // TODO(scheglov) Sort for stable results? | 306 // TODO(scheglov) Sort for stable results? |
285 _fsState._partToLibraries | 307 _fsState._partToLibraries |
286 .putIfAbsent(file, () => <FileState>[]) | 308 .putIfAbsent(file, () => <FileState>[]) |
287 .add(this); | 309 .add(this); |
288 } | 310 } |
289 } | 311 } |
290 } | 312 } |
291 | 313 |
292 // Compute direct dependencies. | 314 // Compute referenced files. |
293 _dependencies = (new Set<FileState>() | 315 Set<FileState> oldDirectReferencedFiles = _directReferencedFiles; |
294 ..addAll(_importedFiles) | 316 _directReferencedFiles = new Set<FileState>() |
295 ..addAll(_exportedFiles) | 317 ..addAll(_importedFiles) |
296 ..addAll(_partedFiles)) | 318 ..addAll(_exportedFiles) |
297 .toList(); | 319 ..addAll(_partedFiles); |
| 320 |
| 321 // If the set of directly referenced files of this file is changed, |
| 322 // then the transitive sets of files that include this file are also |
| 323 // changed. Reset these transitive sets. |
| 324 if (_directReferencedFiles.length != oldDirectReferencedFiles.length || |
| 325 !_directReferencedFiles.containsAll(oldDirectReferencedFiles)) { |
| 326 for (FileState file in _fsState._uriToFile.values) { |
| 327 if (file._transitiveFiles != null && |
| 328 file._transitiveFiles.contains(this)) { |
| 329 file._transitiveFiles = null; |
| 330 } |
| 331 } |
| 332 } |
298 | 333 |
299 // Return whether the API signature changed. | 334 // Return whether the API signature changed. |
300 return apiSignatureChanged; | 335 return apiSignatureChanged; |
301 } | 336 } |
302 | 337 |
303 @override | 338 @override |
304 String toString() => path; | 339 String toString() => path; |
305 | 340 |
306 /** | 341 /** |
307 * Return the [FileState] for the given [relativeUri]. | 342 * Return the [FileState] for the given [relativeUri]. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 /** | 396 /** |
362 * Mapping from a path to the corresponding canonical [FileState]. | 397 * Mapping from a path to the corresponding canonical [FileState]. |
363 */ | 398 */ |
364 final Map<String, FileState> _pathToCanonicalFile = {}; | 399 final Map<String, FileState> _pathToCanonicalFile = {}; |
365 | 400 |
366 /** | 401 /** |
367 * Mapping from a part to the libraries it is a part of. | 402 * Mapping from a part to the libraries it is a part of. |
368 */ | 403 */ |
369 final Map<FileState, List<FileState>> _partToLibraries = {}; | 404 final Map<FileState, List<FileState>> _partToLibraries = {}; |
370 | 405 |
| 406 FileSystemStateTestView _testView; |
| 407 |
371 FileSystemState( | 408 FileSystemState( |
372 this._logger, | 409 this._logger, |
373 this._byteStore, | 410 this._byteStore, |
374 this._contentOverlay, | 411 this._contentOverlay, |
375 this._resourceProvider, | 412 this._resourceProvider, |
376 this._sourceFactory, | 413 this._sourceFactory, |
377 this._analysisOptions, | 414 this._analysisOptions, |
378 this._salt); | 415 this._salt) { |
| 416 _testView = new FileSystemStateTestView(this); |
| 417 } |
379 | 418 |
380 /** | 419 /** |
381 * Return the set of known files. | 420 * Return the set of known files. |
382 */ | 421 */ |
383 Set<String> get knownFiles => _pathToFiles.keys.toSet(); | 422 Set<String> get knownFiles => _pathToFiles.keys.toSet(); |
384 | 423 |
| 424 @visibleForTesting |
| 425 FileSystemStateTestView get test => _testView; |
| 426 |
385 /** | 427 /** |
386 * Return the canonical [FileState] for the given absolute [path]. The | 428 * Return the canonical [FileState] for the given absolute [path]. The |
387 * returned file has the last known state since if was last refreshed. | 429 * returned file has the last known state since if was last refreshed. |
388 * | 430 * |
389 * Here "canonical" means that if the [path] is in a package `lib` then the | 431 * Here "canonical" means that if the [path] is in a package `lib` then the |
390 * returned file will have the `package:` style URI. | 432 * returned file will have the `package:` style URI. |
391 */ | 433 */ |
392 FileState getFileForPath(String path) { | 434 FileState getFileForPath(String path) { |
393 FileState file = _pathToCanonicalFile[path]; | 435 FileState file = _pathToCanonicalFile[path]; |
394 if (file == null) { | 436 if (file == null) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 FileState canonicalFile = getFileForPath(path); | 488 FileState canonicalFile = getFileForPath(path); |
447 List<FileState> allFiles = _pathToFiles[path].toList(); | 489 List<FileState> allFiles = _pathToFiles[path].toList(); |
448 if (allFiles.length == 1) { | 490 if (allFiles.length == 1) { |
449 return allFiles; | 491 return allFiles; |
450 } | 492 } |
451 return allFiles | 493 return allFiles |
452 ..remove(canonicalFile) | 494 ..remove(canonicalFile) |
453 ..insert(0, canonicalFile); | 495 ..insert(0, canonicalFile); |
454 } | 496 } |
455 } | 497 } |
| 498 |
| 499 @visibleForTesting |
| 500 class FileSystemStateTestView { |
| 501 final FileSystemState state; |
| 502 |
| 503 FileSystemStateTestView(this.state); |
| 504 |
| 505 Set<FileState> get filesWithoutTransitive { |
| 506 return state._uriToFile.values |
| 507 .where((f) => f._transitiveFiles == null) |
| 508 .toSet(); |
| 509 } |
| 510 } |
OLD | NEW |