blob: 63b906cb3c884cbfc89ea4bf170fce82acc9cb49 [file] [log] [blame]
// 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;
}
}