| // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| library analyzer.src.source.source_resource; |
| |
| import 'dart:collection'; |
| |
| import 'package:analyzer/file_system/file_system.dart'; |
| import 'package:analyzer/src/generated/engine.dart'; |
| import 'package:analyzer/src/generated/source.dart'; |
| |
| /** |
| * A function that can translate the contents of files on disk as they are read. |
| * This is now obsolete, but supported the ability of server to deal with |
| * clients that convert all text to an internal format. |
| */ |
| typedef String FileReadMode(String s); |
| |
| /** |
| * A source that represents a file. |
| */ |
| class FileSource extends Source { |
| /** |
| * A function that changes the way that files are read off of disk. |
| */ |
| static FileReadMode fileReadMode = (String s) => s; |
| |
| /** |
| * Map from encoded URI/filepath pair to a unique integer identifier. This |
| * identifier is used for equality tests and hash codes. |
| * |
| * The URI and filepath are joined into a pair by separating them with an '@' |
| * character. |
| */ |
| static final Map<String, int> _idTable = new HashMap<String, int>(); |
| |
| /** |
| * The URI from which this source was originally derived. |
| */ |
| @override |
| final Uri uri; |
| |
| /** |
| * The unique ID associated with this source. |
| */ |
| final int id; |
| |
| /** |
| * The file represented by this source. |
| */ |
| final File file; |
| |
| /** |
| * The cached absolute path of this source. |
| */ |
| String _absolutePath; |
| |
| /** |
| * The cached encoding for this source. |
| */ |
| String _encoding; |
| |
| /** |
| * Initialize a newly created source object to represent the given [file]. If |
| * a [uri] is given, then it will be used as the URI from which the source was |
| * derived, otherwise a `file:` URI will be created based on the [file]. |
| */ |
| FileSource(File file, [Uri uri]) |
| : this.uri = uri ?? file.toUri(), |
| this.file = file, |
| id = _idTable.putIfAbsent( |
| '${uri ?? file.toUri()}@${file.path}', () => _idTable.length); |
| |
| @override |
| TimestampedData<String> get contents { |
| return PerformanceStatistics.io.makeCurrentWhile(() { |
| return contentsFromFile; |
| }); |
| } |
| |
| /** |
| * Get and return the contents and timestamp of the underlying file. |
| * |
| * Clients should consider using the method [AnalysisContext.getContents] |
| * because contexts can have local overrides of the content of a source that |
| * the source is not aware of. |
| * |
| * Throws an exception if the contents of this source could not be accessed. |
| * See [contents]. |
| */ |
| TimestampedData<String> get contentsFromFile { |
| return new TimestampedData<String>( |
| modificationStamp, fileReadMode(file.readAsStringSync())); |
| } |
| |
| @override |
| String get encoding => _encoding ??= uri.toString(); |
| |
| @override |
| String get fullName => _absolutePath ??= file.path; |
| |
| @override |
| int get hashCode => uri.hashCode; |
| |
| @override |
| bool get isInSystemLibrary => uri.scheme == DartUriResolver.DART_SCHEME; |
| |
| @override |
| int get modificationStamp { |
| try { |
| return file.modificationStamp; |
| } on FileSystemException { |
| return -1; |
| } |
| } |
| |
| @override |
| String get shortName => file.shortName; |
| |
| @override |
| UriKind get uriKind => UriKind.fromScheme(uri.scheme); |
| |
| @override |
| bool operator ==(Object object) { |
| if (object is FileSource) { |
| return id == object.id; |
| } else if (object is Source) { |
| return uri == object.uri; |
| } |
| return false; |
| } |
| |
| @override |
| bool exists() => file.exists; |
| |
| @override |
| String toString() { |
| if (file == null) { |
| return "<unknown source>"; |
| } |
| return file.path; |
| } |
| } |