Skip to content

Commit

Permalink
Add implementations of the front end FileSystem API.
Browse files Browse the repository at this point in the history
This required some small changes to the API contract.

Note that the tests use supermixins.  I'm assuming that supermixin
functionality will be available on all platforms by the time this is
needed.  If not, I will be happy to rewrite them.

[email protected], [email protected]

Review URL: https://codereview.chromium.org/2471283002 .
  • Loading branch information
stereotype441 committed Nov 3, 2016
1 parent 4682ea9 commit 28b6a1f
Show file tree
Hide file tree
Showing 8 changed files with 643 additions and 6 deletions.
1 change: 1 addition & 0 deletions .packages
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dartdoc:third_party/pkg/dartdoc/lib
dev_compiler:pkg/dev_compiler/lib
expect:pkg/expect/lib
fixnum:third_party/pkg/fixnum/lib
front_end:pkg/front_end/lib
func:third_party/pkg/func/lib
glob:third_party/pkg/glob/lib
html:third_party/pkg/html/lib
Expand Down
12 changes: 7 additions & 5 deletions pkg/front_end/lib/file_system.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,19 @@ abstract class FileSystem {

/// Returns a [FileSystemEntity] corresponding to the given [uri].
///
/// Uses of `..` and `.` in the URI are normalized before returning. Relative
/// paths are also converted to absolute paths.
/// Uses of `..` and `.` in the URI are normalized before returning.
///
/// If [uri] is not a `file:` URI, an [Error] will be thrown.
/// If [uri] is not an absolute `file:` URI, an [Error] will be thrown.
///
/// Does not check whether a file or folder exists at the given location.
FileSystemEntity entityForUri(Uri uri);
}

/// Abstract representation of a file system entity that may or may not exist.
///
/// Instances of this class have suitable implementations of equality tests and
/// hashCode.
///
/// Not intended to be implemented or extended by clients.
abstract class FileSystemEntity {
/// Returns the absolute normalized path represented by this file system
Expand All @@ -67,7 +69,7 @@ abstract class FileSystemEntity {
/// The file is assumed to be UTF-8 encoded.
///
/// If an error occurs while attempting to read the file (e.g. because no such
/// file exists, or the entity is a directory), the future is completed with
/// an [Exception].
/// file exists, the entity is a directory, or the file is not valid UTF-8),
/// the future is completed with an [Exception].
Future<String> readAsString();
}
100 changes: 100 additions & 0 deletions pkg/front_end/lib/memory_file_system.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// 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 front_end.memory_file_system;

import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';

import 'package:path/path.dart' as p;

import 'file_system.dart';

/// Concrete implementation of [FileSystem] which performs its operations on an
/// in-memory virtual file system.
///
/// Not intended to be implemented or extended by clients.
class MemoryFileSystem implements FileSystem {
@override
final p.Context context;

final Map<String, Uint8List> _files = {};

/// The "current directory" in the in-memory virtual file system.
///
/// This is used to convert relative paths to absolute paths.
String currentDirectory;

MemoryFileSystem(this.context, this.currentDirectory);

@override
MemoryFileSystemEntity entityForPath(String path) =>
new MemoryFileSystemEntity._(
this, context.normalize(context.join(currentDirectory, path)));

@override
MemoryFileSystemEntity entityForUri(Uri uri) {
if (uri.scheme != 'file') throw new ArgumentError('File URI expected');
// Note: we don't have to verify that the URI's path is absolute, because
// URIs with non-empty schemes always have absolute paths.
return entityForPath(context.fromUri(uri));
}
}

/// Concrete implementation of [FileSystemEntity] for use by
/// [MemoryFileSystem].
class MemoryFileSystemEntity implements FileSystemEntity {
final MemoryFileSystem _fileSystem;

@override
final String path;

MemoryFileSystemEntity._(this._fileSystem, this.path);

@override
int get hashCode => path.hashCode;

@override
bool operator ==(Object other) =>
other is MemoryFileSystemEntity &&
other.path == path &&
identical(other._fileSystem, _fileSystem);

@override
Future<List<int>> readAsBytes() async {
List<int> contents = _fileSystem._files[path];
if (contents != null) {
return contents.toList();
}
throw new Exception('File does not exist');
}

@override
Future<String> readAsString() async {
List<int> contents = await readAsBytes();
return UTF8.decode(contents);
}

/// Writes the given raw bytes to this file system entity.
///
/// If no file exists, one is created. If a file exists already, it is
/// overwritten.
void writeAsBytesSync(List<int> bytes) {
_fileSystem._files[path] = new Uint8List.fromList(bytes);
}

/// Writes the given string to this file system entity.
///
/// The string is encoded as UTF-8.
///
/// If no file exists, one is created. If a file exists already, it is
/// overwritten.
void writeAsStringSync(String s) {
// Note: the return type of UTF8.encode is List<int>, but in practice it
// always returns Uint8List. We rely on that for efficiency, so that we
// don't have to make an extra copy.
_fileSystem._files[path] = UTF8.encode(s) as Uint8List;
}
}
59 changes: 59 additions & 0 deletions pkg/front_end/lib/physical_file_system.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// 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 front_end.physical_file_system;

import 'dart:async';
import 'dart:io' as io;

import 'package:path/path.dart' as p;

import 'file_system.dart';

/// Concrete implementation of [FileSystem] which performs its operations using
/// I/O.
///
/// Not intended to be implemented or extended by clients.
class PhysicalFileSystem implements FileSystem {
static final PhysicalFileSystem instance = new PhysicalFileSystem._();

PhysicalFileSystem._();

@override
p.Context get context => p.context;

@override
FileSystemEntity entityForPath(String path) =>
new _PhysicalFileSystemEntity(context.normalize(context.absolute(path)));

@override
FileSystemEntity entityForUri(Uri uri) {
if (uri.scheme != 'file') throw new ArgumentError('File URI expected');
// Note: we don't have to verify that the URI's path is absolute, because
// URIs with non-empty schemes always have absolute paths.
return entityForPath(context.fromUri(uri));
}
}

/// Concrete implementation of [FileSystemEntity] for use by
/// [PhysicalFileSystem].
class _PhysicalFileSystemEntity implements FileSystemEntity {
@override
final String path;

_PhysicalFileSystemEntity(this.path);

@override
int get hashCode => path.hashCode;

@override
bool operator ==(Object other) =>
other is _PhysicalFileSystemEntity && other.path == path;

@override
Future<List<int>> readAsBytes() => new io.File(path).readAsBytes();

@override
Future<String> readAsString() => new io.File(path).readAsString();
}
4 changes: 3 additions & 1 deletion pkg/front_end/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ dependencies:
path: '^1.3.9'
source_span: '^1.2.3'
dev_dependencies:
package_config: '^1.0.0'
# TODO(sigmund): update to a version constraint once we roll the latest kernel
# to the repo.
kernel: {path: ../../third_party/pkg/kernel}
package_config: '^1.0.0'
test: ^0.12.0
test_reflective_loader: ^0.1.0
# TODO(sigmund): remove once kernel is moved into the sdk repo.
dependency_overrides:
analyzer: '^0.29.0'
Loading

0 comments on commit 28b6a1f

Please sign in to comment.