| 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'; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 /** | 69 /** |
| 70 * The absolute path of the file. | 70 * The absolute path of the file. |
| 71 */ | 71 */ |
| 72 final String path; | 72 final String path; |
| 73 | 73 |
| 74 /** | 74 /** |
| 75 * The absolute URI of the file. | 75 * The absolute URI of the file. |
| 76 */ | 76 */ |
| 77 final Uri uri; | 77 final Uri uri; |
| 78 | 78 |
| 79 Source _source; | 79 /** |
| 80 * The [Source] of the file with the [uri]. |
| 81 */ |
| 82 Source source; |
| 80 | 83 |
| 81 String _content; | 84 String _content; |
| 82 String _contentHash; | 85 String _contentHash; |
| 83 LineInfo _lineInfo; | 86 LineInfo _lineInfo; |
| 84 UnlinkedUnit _unlinked; | 87 UnlinkedUnit _unlinked; |
| 85 List<int> _apiSignature; | 88 List<int> _apiSignature; |
| 86 | 89 |
| 87 List<FileState> _importedFiles; | 90 List<FileState> _importedFiles; |
| 88 List<FileState> _exportedFiles; | 91 List<FileState> _exportedFiles; |
| 89 List<FileState> _partedFiles; | 92 List<FileState> _partedFiles; |
| 90 List<FileState> _dependencies; | 93 List<FileState> _dependencies; |
| 91 | 94 |
| 92 FileState(this._fsState, this.path, this.uri) { | 95 FileState._(this._fsState, this.path, this.uri, this.source); |
| 93 _source = new FileSource(_fsState._resourceProvider.getFile(path), uri); | |
| 94 } | |
| 95 | 96 |
| 96 /** | 97 /** |
| 97 * The unlinked API signature of the file. | 98 * The unlinked API signature of the file. |
| 98 */ | 99 */ |
| 99 List<int> get apiSignature => _apiSignature; | 100 List<int> get apiSignature => _apiSignature; |
| 100 | 101 |
| 101 /** | 102 /** |
| 102 * The content of the file. | 103 * The content of the file. |
| 103 */ | 104 */ |
| 104 String get content => _content; | 105 String get content => _content; |
| 105 | 106 |
| 106 /** | 107 /** |
| 107 * The MD5 hash of the [content]. | 108 * The MD5 hash of the [content]. |
| 108 */ | 109 */ |
| 109 String get contentHash => _contentHash; | 110 String get contentHash => _contentHash; |
| 110 | 111 |
| 111 /** | 112 /** |
| 112 * Return information about line in the file. | |
| 113 */ | |
| 114 LineInfo get lineInfo => _lineInfo; | |
| 115 | |
| 116 /** | |
| 117 * Return the list of all direct dependencies. | 113 * Return the list of all direct dependencies. |
| 118 */ | 114 */ |
| 119 List<FileState> get dependencies => _dependencies; | 115 List<FileState> get dependencies => _dependencies; |
| 120 | 116 |
| 121 /** | 117 /** |
| 122 * The list of files this file exports. | 118 * The list of files this file exports. |
| 123 */ | 119 */ |
| 124 List<FileState> get exportedFiles => _exportedFiles; | 120 List<FileState> get exportedFiles => _exportedFiles; |
| 125 | 121 |
| 126 /** | 122 /** |
| 127 * The list of files this file imports. | 123 * The list of files this file imports. |
| 128 */ | 124 */ |
| 129 List<FileState> get importedFiles => _importedFiles; | 125 List<FileState> get importedFiles => _importedFiles; |
| 130 | 126 |
| 131 /** | 127 /** |
| 128 * Return information about line in the file. |
| 129 */ |
| 130 LineInfo get lineInfo => _lineInfo; |
| 131 |
| 132 /** |
| 132 * The list of files this library file references as parts. | 133 * The list of files this library file references as parts. |
| 133 */ | 134 */ |
| 134 List<FileState> get partedFiles => _partedFiles; | 135 List<FileState> get partedFiles => _partedFiles; |
| 135 | 136 |
| 136 /** | 137 /** |
| 137 * The [Source] of the file in the [SourceFactory]. | |
| 138 */ | |
| 139 Source get source => _source; | |
| 140 | |
| 141 /** | |
| 142 * The [UnlinkedUnit] of the file. | 138 * The [UnlinkedUnit] of the file. |
| 143 */ | 139 */ |
| 144 UnlinkedUnit get unlinked => _unlinked; | 140 UnlinkedUnit get unlinked => _unlinked; |
| 145 | 141 |
| 146 /** | 142 /** |
| 147 * Read the file content and ensure that all of the file properties are | 143 * Read the file content and ensure that all of the file properties are |
| 148 * consistent with the read content, including API signature. | 144 * consistent with the read content, including API signature. |
| 149 * | 145 * |
| 150 * Return `true` if the API signature changed since the last refresh. | 146 * Return `true` if the API signature changed since the last refresh. |
| 151 */ | 147 */ |
| (...skipping 28 matching lines...) Expand all Loading... |
| 180 signature.addBytes(contentBytes); | 176 signature.addBytes(contentBytes); |
| 181 unlinkedKey = '${signature.toHex()}.unlinked'; | 177 unlinkedKey = '${signature.toHex()}.unlinked'; |
| 182 } | 178 } |
| 183 | 179 |
| 184 // Prepare bytes of the unlinked bundle - existing or new. | 180 // Prepare bytes of the unlinked bundle - existing or new. |
| 185 List<int> bytes; | 181 List<int> bytes; |
| 186 { | 182 { |
| 187 bytes = _fsState._byteStore.get(unlinkedKey); | 183 bytes = _fsState._byteStore.get(unlinkedKey); |
| 188 if (bytes == null) { | 184 if (bytes == null) { |
| 189 CompilationUnit unit = | 185 CompilationUnit unit = |
| 190 _parse(_source, _content, _fsState._analysisOptions); | 186 _parse(source, _content, _fsState._analysisOptions); |
| 191 _fsState._logger.run('Create unlinked for $path', () { | 187 _fsState._logger.run('Create unlinked for $path', () { |
| 192 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit); | 188 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit); |
| 193 bytes = unlinkedUnit.toBuffer(); | 189 bytes = unlinkedUnit.toBuffer(); |
| 194 _fsState._byteStore.put(unlinkedKey, bytes); | 190 _fsState._byteStore.put(unlinkedKey, bytes); |
| 195 }); | 191 }); |
| 196 } | 192 } |
| 197 } | 193 } |
| 198 | 194 |
| 199 // Read the unlinked bundle. | 195 // Read the unlinked bundle. |
| 200 _unlinked = new UnlinkedUnit.fromBuffer(bytes); | 196 _unlinked = new UnlinkedUnit.fromBuffer(bytes); |
| 201 _lineInfo = new LineInfo(_unlinked.lineStarts); | 197 _lineInfo = new LineInfo(_unlinked.lineStarts); |
| 202 List<int> newApiSignature = _unlinked.apiSignature; | 198 List<int> newApiSignature = _unlinked.apiSignature; |
| 203 bool apiSignatureChanged = _apiSignature != null && | 199 bool apiSignatureChanged = _apiSignature != null && |
| 204 !_equalByteLists(_apiSignature, newApiSignature); | 200 !_equalByteLists(_apiSignature, newApiSignature); |
| 205 _apiSignature = newApiSignature; | 201 _apiSignature = newApiSignature; |
| 206 | 202 |
| 207 // Build the graph. | 203 // Build the graph. |
| 208 _importedFiles = <FileState>[]; | 204 _importedFiles = <FileState>[]; |
| 209 _exportedFiles = <FileState>[]; | 205 _exportedFiles = <FileState>[]; |
| 210 _partedFiles = <FileState>[]; | 206 _partedFiles = <FileState>[]; |
| 211 for (UnlinkedImport import in _unlinked.imports) { | 207 for (UnlinkedImport import in _unlinked.imports) { |
| 212 if (!import.isImplicit) { | 208 if (!import.isImplicit) { |
| 213 String uri = import.uri; | 209 String uri = import.uri; |
| 214 if (!_isDartUri(uri)) { | 210 if (!_isDartUri(uri)) { |
| 215 FileState file = _fileForRelativeUri(uri); | 211 FileState file = _fileForRelativeUri(uri); |
| 216 _importedFiles.add(file); | 212 if (file != null) { |
| 213 _importedFiles.add(file); |
| 214 } |
| 217 } | 215 } |
| 218 } | 216 } |
| 219 } | 217 } |
| 220 for (UnlinkedExportPublic export in _unlinked.publicNamespace.exports) { | 218 for (UnlinkedExportPublic export in _unlinked.publicNamespace.exports) { |
| 221 String uri = export.uri; | 219 String uri = export.uri; |
| 222 if (!_isDartUri(uri)) { | 220 if (!_isDartUri(uri)) { |
| 223 FileState file = _fileForRelativeUri(uri); | 221 FileState file = _fileForRelativeUri(uri); |
| 224 _exportedFiles.add(file); | 222 if (file != null) { |
| 223 _exportedFiles.add(file); |
| 224 } |
| 225 } | 225 } |
| 226 } | 226 } |
| 227 for (String uri in _unlinked.publicNamespace.parts) { | 227 for (String uri in _unlinked.publicNamespace.parts) { |
| 228 if (!_isDartUri(uri)) { | 228 if (!_isDartUri(uri)) { |
| 229 FileState file = _fileForRelativeUri(uri); | 229 FileState file = _fileForRelativeUri(uri); |
| 230 _partedFiles.add(file); | 230 if (file != null) { |
| 231 _partedFiles.add(file); |
| 232 } |
| 231 } | 233 } |
| 232 } | 234 } |
| 233 | 235 |
| 234 // Compute direct dependencies. | 236 // Compute direct dependencies. |
| 235 _dependencies = (new Set<FileState>() | 237 _dependencies = (new Set<FileState>() |
| 236 ..addAll(_importedFiles) | 238 ..addAll(_importedFiles) |
| 237 ..addAll(_exportedFiles) | 239 ..addAll(_exportedFiles) |
| 238 ..addAll(_partedFiles)) | 240 ..addAll(_partedFiles)) |
| 239 .toList(); | 241 .toList(); |
| 240 | 242 |
| 241 // Return whether the API signature changed. | 243 // Return whether the API signature changed. |
| 242 return apiSignatureChanged; | 244 return apiSignatureChanged; |
| 243 } | 245 } |
| 244 | 246 |
| 245 @override | 247 @override |
| 246 String toString() => path; | 248 String toString() => path; |
| 247 | 249 |
| 248 /** | 250 /** |
| 249 * Return the [FileState] for the given [relativeUri]. | 251 * Return the [FileState] for the given [relativeUri]. |
| 250 */ | 252 */ |
| 251 FileState _fileForRelativeUri(String relativeUri) { | 253 FileState _fileForRelativeUri(String relativeUri) { |
| 252 Uri absoluteUri = resolveRelativeUri(uri, FastUri.parse(relativeUri)); | 254 Uri absoluteUri = resolveRelativeUri(uri, FastUri.parse(relativeUri)); |
| 253 String absolutePath = _fsState._sourceFactory | 255 return _fsState.getFileForUri(absoluteUri); |
| 254 .resolveUri(null, absoluteUri.toString()) | |
| 255 .fullName; | |
| 256 return _fsState.getFile(absolutePath, absoluteUri); | |
| 257 } | 256 } |
| 258 | 257 |
| 259 /** | 258 /** |
| 260 * Return `true` if the given byte lists are equal. | 259 * Return `true` if the given byte lists are equal. |
| 261 */ | 260 */ |
| 262 static bool _equalByteLists(List<int> a, List<int> b) { | 261 static bool _equalByteLists(List<int> a, List<int> b) { |
| 263 if (a == null) { | 262 if (a == null) { |
| 264 return b == null; | 263 return b == null; |
| 265 } else if (b == null) { | 264 } else if (b == null) { |
| 266 return false; | 265 return false; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 */ | 305 */ |
| 307 class FileSystemState { | 306 class FileSystemState { |
| 308 final PerformanceLog _logger; | 307 final PerformanceLog _logger; |
| 309 final ResourceProvider _resourceProvider; | 308 final ResourceProvider _resourceProvider; |
| 310 final ByteStore _byteStore; | 309 final ByteStore _byteStore; |
| 311 final FileContentOverlay _contentOverlay; | 310 final FileContentOverlay _contentOverlay; |
| 312 final SourceFactory _sourceFactory; | 311 final SourceFactory _sourceFactory; |
| 313 final AnalysisOptions _analysisOptions; | 312 final AnalysisOptions _analysisOptions; |
| 314 final Uint32List _salt; | 313 final Uint32List _salt; |
| 315 | 314 |
| 316 final Map<String, FileState> _pathToFile = <String, FileState>{}; | 315 /** |
| 316 * Mapping from a URI to the corresponding [FileState]. |
| 317 */ |
| 318 final Map<Uri, FileState> _uriToFile = {}; |
| 319 |
| 320 /** |
| 321 * Mapping from a path to the corresponding [FileState]s, canonical or not. |
| 322 */ |
| 323 final Map<String, List<FileState>> _pathToFiles = {}; |
| 324 |
| 325 /** |
| 326 * Mapping from a path to the corresponding canonical [FileState]. |
| 327 */ |
| 328 final Map<String, FileState> _pathToCanonicalFile = {}; |
| 317 | 329 |
| 318 FileSystemState( | 330 FileSystemState( |
| 319 this._logger, | 331 this._logger, |
| 320 this._byteStore, | 332 this._byteStore, |
| 321 this._contentOverlay, | 333 this._contentOverlay, |
| 322 this._resourceProvider, | 334 this._resourceProvider, |
| 323 this._sourceFactory, | 335 this._sourceFactory, |
| 324 this._analysisOptions, | 336 this._analysisOptions, |
| 325 this._salt); | 337 this._salt); |
| 326 | 338 |
| 327 /** | 339 /** |
| 328 * Return the [FileState] for the give [path]. The returned file has the | 340 * Return the canonical [FileState] for the given absolute [path]. The |
| 329 * last known state since if was last refreshed. | 341 * returned file has the last known state since if was last refreshed. |
| 342 * |
| 343 * Here "canonical" means that if the [path] is in a package `lib` then the |
| 344 * returned file will have the `package:` style URI. |
| 330 */ | 345 */ |
| 331 FileState getFile(String path, [Uri uri]) { | 346 FileState getFileForPath(String path) { |
| 332 FileState file = _pathToFile[path]; | 347 FileState file = _pathToCanonicalFile[path]; |
| 333 if (file == null) { | 348 if (file == null) { |
| 334 uri ??= _uriForPath(path); | 349 File resource = _resourceProvider.getFile(path); |
| 335 file = new FileState(this, path, uri); | 350 Source fileSource = resource.createSource(); |
| 336 _pathToFile[path] = file; | 351 Uri uri = _sourceFactory.restoreUri(fileSource); |
| 352 // Try to get the existing instance. |
| 353 file = _uriToFile[uri]; |
| 354 // If we have a file, call it the canonical one and return it. |
| 355 if (file != null) { |
| 356 _pathToCanonicalFile[path] = file; |
| 357 return file; |
| 358 } |
| 359 // Create a new file. |
| 360 FileSource uriSource = new FileSource(resource, uri); |
| 361 file = new FileState._(this, path, uri, uriSource); |
| 362 _uriToFile[uri] = file; |
| 363 _pathToFiles.putIfAbsent(path, () => <FileState>[]).add(file); |
| 364 _pathToCanonicalFile[path] = file; |
| 337 file.refresh(); | 365 file.refresh(); |
| 338 } | 366 } |
| 339 return file; | 367 return file; |
| 340 } | 368 } |
| 341 | 369 |
| 342 /** | 370 /** |
| 343 * Return the default [Uri] for the given path in [_sourceFactory]. | 371 * Return the [FileState] for the given absolute [uri]. May return `null` if |
| 372 * the [uri] is invalid, e.g. a `package:` URI without a package name. The |
| 373 * returned file has the last known state since if was last refreshed. |
| 344 */ | 374 */ |
| 345 Uri _uriForPath(String path) { | 375 FileState getFileForUri(Uri uri) { |
| 346 Source fileSource = _resourceProvider.getFile(path).createSource(); | 376 FileState file = _uriToFile[uri]; |
| 347 return _sourceFactory.restoreUri(fileSource); | 377 if (file == null) { |
| 378 Source uriSource = _sourceFactory.resolveUri(null, uri.toString()); |
| 379 // If the URI is invalid, for example package:/test/d.dart (note the |
| 380 // leading '/'), then `null` is returned. We should ignore this URI. |
| 381 if (uriSource == null) { |
| 382 return null; |
| 383 } |
| 384 String path = uriSource.fullName; |
| 385 File resource = _resourceProvider.getFile(path); |
| 386 FileSource source = new FileSource(resource, uri); |
| 387 file = new FileState._(this, path, uri, source); |
| 388 _uriToFile[uri] = file; |
| 389 _pathToFiles.putIfAbsent(path, () => <FileState>[]).add(file); |
| 390 file.refresh(); |
| 391 } |
| 392 return file; |
| 393 } |
| 394 |
| 395 /** |
| 396 * Return the list of all [FileState]s corresponding to the given [path]. The |
| 397 * list has at least one item, and the first item is the canonical file. |
| 398 */ |
| 399 List<FileState> getFilesForPath(String path) { |
| 400 FileState canonicalFile = getFileForPath(path); |
| 401 List<FileState> allFiles = _pathToFiles[path].toList(); |
| 402 if (allFiles.length == 1) { |
| 403 return allFiles; |
| 404 } |
| 405 return allFiles |
| 406 ..remove(canonicalFile) |
| 407 ..insert(0, canonicalFile); |
| 348 } | 408 } |
| 349 } | 409 } |
| OLD | NEW |