Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Side by Side Diff: pkg/analysis_server/lib/src/resource.dart

Issue 299403004: Resource/File/Folder interfaces and implementations for dart:io and memory. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fixes for review comments Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/analysis_server/pubspec.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
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.
4
5 library resource;
6
7 import 'dart:io' as io;
8
9 import 'package:analyzer/src/generated/engine.dart' show TimestampedData;
10 import 'package:analyzer/src/generated/java_io.dart';
11 import 'package:analyzer/src/generated/source_io.dart';
12 import 'package:path/path.dart';
13
14
15 /**
16 * [File]s are leaf [Resource]s which contain data.
17 */
18 abstract class File extends Resource {
19 /**
20 * Create a new [Source] instance that serves this file.
21 */
22 Source createSource(UriKind uriKind);
23 }
24
25
26 /**
27 * [Folder]s are [Resource]s which may contain files and/or other folders.
28 */
29 abstract class Folder extends Resource {
30 /**
31 * Return an existing child [Resource] with the given [relPath].
32 * Return a not existing [File] if no such child exist.
33 */
34 Resource getChild(String relPath);
35
36 /**
37 * Return a list of existing direct children [Resource]s (folders and files)
38 * in this folder, in no particular order.
39 */
40 List<Resource> getChildren();
41 }
42
43
44 /**
45 * The abstract class [Resource] is an abstraction of file or folder.
46 */
47 abstract class Resource {
48 /**
49 * Return `true` if this resource exists.
50 */
51 bool get exists;
52
53 /**
54 * Return the full (long) version of the name that can be displayed to the
55 * user to denote this resource.
56 */
57 String get fullName;
58
59 /**
60 * Return a short version of the name that can be displayed to the user to
61 * denote this resource.
62 */
63 String get shortName;
64 }
65
66
67 /**
68 * Instances of the class [ResourceProvider] convert [String] paths into
69 * [Resource]s.
70 */
71 abstract class ResourceProvider {
72 /**
73 * Return the [Resource] that corresponds to the given [path].
74 */
75 Resource getResource(String path);
76 }
77
78
79 /**
80 * An in-memory implementation of [Resource].
81 */
82 abstract class _MemoryResource implements Resource {
83 final MemoryResourceProvider _provider;
84 final String _path;
85
86 _MemoryResource(this._provider, this._path);
87
88 @override
89 bool operator ==(other) {
90 return identical(this, other);
91 }
92
93 @override
94 bool get exists => _provider._pathToResource.containsKey(_path);
95
96 @override
97 String get fullName => _path;
98
99 @override
100 get hashCode => _path.hashCode;
101
102 @override
103 String get shortName => basename(_path);
104
105 @override
106 String toString() => fullName;
107 }
108
109
110 /**
111 * An in-memory implementation of [File].
112 */
113 class _MemoryFile extends _MemoryResource implements File {
114 _MemoryFile(MemoryResourceProvider provider, String path) :
115 super(provider, path);
116
117 @override
118 Source createSource(UriKind uriKind) {
119 return new _MemoryFileSource(this, uriKind);
120 }
121
122 String get _content {
123 String content = _provider._pathToContent[_path];
124 if (content == null) {
125 throw new MemoryResourceException(_path, "File '$_path' does not exist");
126 }
127 return content;
128 }
129
130 int get _timestamp => _provider._pathToTimestamp[_path];
131 }
132
133
134 /**
135 * Exception thrown when a memory [Resource] file operation fails.
136 */
137 class MemoryResourceException {
138 final path;
139 final message;
140
141 MemoryResourceException(this.path, this.message);
142
143 @override
144 String toString() {
145 return "MemoryResourceException(path=$path; message=$message)";
146 }
147 }
148
149
150 /**
151 * An in-memory implementation of [Source].
152 */
153 class _MemoryFileSource implements Source {
154 final _MemoryFile _file;
155
156 final UriKind uriKind;
157
158 _MemoryFileSource(this._file, this.uriKind);
159
160 @override
161 TimestampedData<String> get contents {
162 return new TimestampedData<String>(modificationStamp, _file._content);
163 }
164
165 @override
166 String get encoding {
167 return '${new String.fromCharCode(uriKind.encoding)}${_file.fullName}';
168 }
169
170 @override
171 bool exists() => _file.exists;
172
173 @override
174 String get fullName => _file.fullName;
175
176 @override
177 bool get isInSystemLibrary => false;
178
179 @override
180 int get modificationStamp => _file._timestamp;
181
182 @override
183 Source resolveRelative(Uri relativeUri) {
184 String relativePath = fromUri(relativeUri);
185 String folderPath = dirname(_file._path);
186 String path = join(folderPath, relativePath);
187 path = normalize(path);
188 _MemoryFile file = new _MemoryFile(_file._provider, path);
189 return new _MemoryFileSource(file, uriKind);
190 }
191
192 @override
193 String get shortName => _file.shortName;
194 }
195
196
197 /**
198 * An in-memory implementation of [Folder].
199 */
200 class _MemoryFolder extends _MemoryResource implements Folder {
201 _MemoryFolder(MemoryResourceProvider provider, String path) :
202 super(provider, path);
203 @override
204 Resource getChild(String relPath) {
205 relPath = normalize(relPath);
206 String childPath = join(_path, relPath);
207 childPath = normalize(childPath);
208 _MemoryResource resource = _provider._pathToResource[childPath];
209 if (resource == null) {
210 resource = new _MemoryFile(_provider, childPath);
211 }
212 return resource;
213 }
214
215 @override
216 List<Resource> getChildren() {
217 List<Resource> children = <Resource>[];
218 _provider._pathToResource.forEach((path, resource) {
219 if (dirname(path) == _path) {
220 children.add(resource);
221 }
222 });
223 return children;
224 }
225 }
226
227
228 /**
229 * An in-memory implementation of [ResourceProvider].
230 * Use `/` as a path separator.
231 */
232 class MemoryResourceProvider implements ResourceProvider {
233 final Map<String, _MemoryResource> _pathToResource = <String, _MemoryResource> {};
234 final Map<String, String> _pathToContent = <String, String>{};
235 final Map<String, int> _pathToTimestamp = <String, int>{};
236 int nextStamp = 0;
237
238 @override
239 Resource getResource(String path) {
240 path = normalize(path);
241 Resource resource = _pathToResource[path];
242 if (resource == null) {
243 resource = new _MemoryFile(this, path);
244 }
245 return resource;
246 }
247
248 Folder newFolder(String path) {
249 path = normalize(path);
250 if (path.isEmpty) {
251 throw new ArgumentError('Empty paths are not supported');
252 }
253 if (!path.startsWith('/')) {
254 throw new ArgumentError("Path must start with '/'");
255 }
256 _MemoryFolder folder = null;
257 String partialPath = "";
258 for (String pathPart in path.split('/')) {
259 if (pathPart.isEmpty) {
260 continue;
261 }
262 partialPath += '/' + pathPart;
263 _MemoryResource resource = _pathToResource[partialPath];
264 if (resource == null) {
265 folder = new _MemoryFolder(this, partialPath);
266 _pathToResource[partialPath] = folder;
267 _pathToTimestamp[partialPath] = nextStamp++;
268 } else if (resource is _MemoryFolder) {
269 folder = resource;
270 } else {
271 String message = 'Folder expected at '
272 "'$partialPath'"
273 'but ${resource.runtimeType} found';
274 throw new ArgumentError(message);
275 }
276 }
277 return folder;
278 }
279
280 File newFile(String path, String content) {
281 path = normalize(path);
282 newFolder(dirname(path));
283 _MemoryFile file = new _MemoryFile(this, path);
284 _pathToResource[path] = file;
285 _pathToContent[path] = content;
286 _pathToTimestamp[path] = nextStamp++;
287 return file;
288 }
289 }
290
291
292 /**
293 * A `dart:io` based implementation of [File].
294 */
295 class _PhysicalFile extends _PhysicalResource implements File {
296 _PhysicalFile(io.File file) : super(file);
297
298 @override
299 Source createSource(UriKind uriKind) {
300 io.File file = _entry as io.File;
301 JavaFile javaFile = new JavaFile(file.absolute.path);
302 return new FileBasedSource.con2(javaFile, uriKind);
303 }
304 }
305
306
307 /**
308 * A `dart:io` based implementation of [Folder].
309 */
310 class _PhysicalFolder extends _PhysicalResource implements Folder {
311 _PhysicalFolder(io.Directory directory) : super(directory);
312
313 @override
314 Resource getChild(String relPath) {
315 String childPath = join(_entry.absolute.path, relPath);
316 return PhysicalResourceProvider.INSTANCE.getResource(childPath);
317 }
318
319 @override
320 List<Resource> getChildren() {
321 List<Resource> children = <Resource>[];
322 io.Directory directory = _entry as io.Directory;
323 List<io.FileSystemEntity> entries = directory.listSync(recursive: false);
324 int numEntries = entries.length;
325 for (int i = 0; i < numEntries; i++) {
326 io.FileSystemEntity entity = entries[i];
327 if (entity is io.Directory) {
328 children.add(new _PhysicalFolder(entity));
329 } else if (entity is io.File) {
330 children.add(new _PhysicalFile(entity));
331 }
332 }
333 return children;
334 }
335 }
336
337
338 /**
339 * A `dart:io` based implementation of [Resource].
340 */
341 abstract class _PhysicalResource implements Resource {
342 final io.FileSystemEntity _entry;
343
344 _PhysicalResource(this._entry);
345
346 @override
347 bool get exists => _entry.existsSync();
348
349 @override
350 String get fullName => _entry.absolute.path;
351
352 @override
353 get hashCode => _entry.hashCode;
354
355 @override
356 String get shortName => basename(fullName);
357
358 @override
359 String toString() => fullName;
360 }
361
362
363 /**
364 * A `dart:io` based implementation of [ResourceProvider].
365 */
366 class PhysicalResourceProvider implements ResourceProvider {
367 static final PhysicalResourceProvider INSTANCE = new PhysicalResourceProvider. _();
368
369 PhysicalResourceProvider._();
370
371 @override
372 Resource getResource(String path) {
373 if (io.FileSystemEntity.isDirectorySync(path)) {
374 io.Directory directory = new io.Directory(path);
375 return new _PhysicalFolder(directory);
376 } else {
377 io.File file = new io.File(path);
378 return new _PhysicalFile(file);
379 }
380 }
381 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698