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

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: 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
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 ==(o) {
Brian Wilkerson 2014/05/25 15:29:58 I really dislike single character variable names f
scheglov 2014/05/25 16:16:38 Done.
90 return identical(this, o);
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 => _provider._pathToContent[_path];
123
124 int get _timestamp => _provider._pathToTimestamp[_path];
125 }
126
127
128 /**
129 * An in-memory implementation of [Source].
130 */
131 class _MemoryFileSource implements Source {
132 final _MemoryFile _file;
133
134 final UriKind uriKind;
135
136 _MemoryFileSource(this._file, this.uriKind);
137
138 @override
139 TimestampedData<String> get contents {
140 return new TimestampedData<String>(modificationStamp, _file._content);
141 }
142
143 @override
144 String get encoding {
145 return '${new String.fromCharCode(uriKind.encoding)}${_file.fullName}';
146 }
147
148 @override
149 bool exists() => _file.exists;
150
151 @override
152 String get fullName => _file.fullName;
153
154 @override
155 bool get isInSystemLibrary => false;
156
157 @override
158 int get modificationStamp => _file._timestamp;
159
160 @override
161 Source resolveRelative(Uri relativeUri) {
162 String relativePath = fromUri(relativeUri);
163 String folderPath = dirname(_file._path);
164 String path = join(folderPath, relativePath);
165 path = normalize(path);
166 _MemoryFile file = new _MemoryFile(_file._provider, path);
167 return new _MemoryFileSource(file, uriKind);
168 }
169
170 @override
171 String get shortName => _file.shortName;
172 }
173
174
175 /**
176 * An in-memory implementation of [Folder].
177 */
178 class _MemoryFolder extends _MemoryResource implements Folder {
179 _MemoryFolder(MemoryResourceProvider provider, String path) :
180 super(provider, path);
181 @override
182 Resource getChild(String relPath) {
183 relPath = normalize(relPath);
184 String childPath = join(_path, relPath);
185 childPath = normalize(childPath);
186 _MemoryResource resource = _provider._pathToResource[childPath];
187 if (resource == null) {
188 resource = new _MemoryFile(_provider, childPath);
189 }
190 return resource;
191 }
192
193 @override
194 List<Resource> getChildren() {
195 List<Resource> children = [];
Brian Wilkerson 2014/05/25 15:29:58 I think we should include a type annotation with l
scheglov 2014/05/25 16:16:38 Done.
196 _provider._pathToResource.forEach((path, resource) {
197 if (dirname(path) == _path) {
198 children.add(resource);
199 }
200 });
201 return children;
202 }
203 }
204
205
206 /**
207 * An in-memory implementation of [ResourceProvider].
208 * Use `/` as a path separator.
209 */
210 class MemoryResourceProvider implements ResourceProvider {
211 final Map<String, _MemoryResource> _pathToResource = {};
212 final Map<String, String> _pathToContent = {};
213 final Map<String, int> _pathToTimestamp = {};
214 int nextStamp = 0;
215
216 @override
217 Resource getResource(String path) {
218 path = normalize(path);
219 Resource resource = _pathToResource[path];
220 if (resource == null) {
221 resource = new _MemoryFile(this, path);
222 }
223 return resource;
224 }
225
226 Folder newFolder(String path) {
227 path = normalize(path);
228 if (path.isEmpty) {
229 throw new ArgumentError('Empty paths are not supported');
230 }
231 if (!path.startsWith('/')) {
232 throw new ArgumentError('Path must start with \'/\'');
Brian Wilkerson 2014/05/25 15:29:58 It would be better to use double quotes so that yo
scheglov 2014/05/25 16:16:38 Done.
233 }
234 _MemoryFolder folder = null;
235 String partialPath = "";
Brian Wilkerson 2014/05/25 15:29:58 It's probably more efficient to use a StringBuffer
scheglov 2014/05/25 16:16:38 It is surprising, but no, it is not faster. Actual
236 for (String pathPart in path.split('/')) {
237 if (pathPart.isEmpty) {
238 continue;
239 }
240 partialPath += '/' + pathPart;
241 _MemoryResource resource = _pathToResource[partialPath];
242 if (resource == null) {
243 folder = new _MemoryFolder(this, partialPath);
244 _pathToResource[partialPath] = folder;
245 _pathToTimestamp[partialPath] = nextStamp++;
246 } else if (resource is _MemoryFolder) {
247 folder = resource;
248 } else {
249 String message = 'Folder expected at ';
250 message += "'$partialPath'";
251 message += 'but ${resource.runtimeType} found';
Brian Wilkerson 2014/05/25 15:29:58 It looks really strange to have a mixture of "+" a
scheglov 2014/05/25 16:16:38 Mostly because it does not fit one 80 characters l
252 throw new ArgumentError(message);
253 }
254 }
255 return folder;
256 }
257
258 File newFile(String path, String content) {
259 path = normalize(path);
260 newFolder(dirname(path));
261 _MemoryFile file = new _MemoryFile(this, path);
262 _pathToResource[path] = file;
263 _pathToContent[path] = content;
264 _pathToTimestamp[path] = nextStamp++;
265 return file;
266 }
267 }
268
269
270 /**
271 * A `dart:io` based implementation of [File].
272 */
273 class _PhysicalFile extends _PhysicalResource implements File {
274 _PhysicalFile(io.File file) : super(file);
275
276 @override
277 Source createSource(UriKind uriKind) {
278 io.File file = _entry as io.File;
279 JavaFile javaFile = new JavaFile(file.absolute.path);
280 return new FileBasedSource.con2(javaFile, uriKind);
281 }
282 }
283
284
285 /**
286 * A `dart:io` based implementation of [Folder].
287 */
288 class _PhysicalFolder extends _PhysicalResource implements Folder {
289 _PhysicalFolder(io.Directory directory) : super(directory);
290
291 @override
292 Resource getChild(String relPath) {
293 String childPath = join(_entry.absolute.path, relPath);
294 return PhysicalResourceProvider.INSTANCE.getResource(childPath);
295 }
296
297 @override
298 List<Resource> getChildren() {
299 List<Resource> children = [];
300 io.Directory directory = _entry as io.Directory;
301 List<io.FileSystemEntity> entries = directory.listSync(recursive: false);
302 int numEntries = entries.length;
303 for (int i = 0; i < numEntries; i++) {
304 io.FileSystemEntity entity = entries[i];
305 if (entity is io.Directory) {
306 children.add(new _PhysicalFolder(entity));
307 } else if (entity is io.File) {
308 children.add(new _PhysicalFile(entity));
309 }
310 }
311 return children;
312 }
313 }
314
315
316 /**
317 * A `dart:io` based implementation of [Resource].
318 */
319 abstract class _PhysicalResource implements Resource {
320 final io.FileSystemEntity _entry;
321
322 _PhysicalResource(this._entry);
323
324 @override
325 bool get exists => _entry.existsSync();
326
327 @override
328 String get fullName => _entry.absolute.path;
329
330 @override
331 get hashCode => _entry.hashCode;
332
333 @override
334 String get shortName => basename(fullName);
335
336 @override
337 String toString() => fullName;
338 }
339
340
341 /**
342 * A `dart:io` based implementation of [ResourceProvider].
343 */
344 class PhysicalResourceProvider implements ResourceProvider {
345 static final PhysicalResourceProvider INSTANCE = new PhysicalResourceProvider. _();
346
347 PhysicalResourceProvider._();
348
349 @override
350 Resource getResource(String path) {
351 if (io.FileSystemEntity.isDirectorySync(path)) {
352 io.Directory directory = new io.Directory(path);
353 return new _PhysicalFolder(directory);
354 } else {
355 io.File file = new io.File(path);
356 return new _PhysicalFile(file);
357 }
358 }
359 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/pubspec.yaml » ('j') | pkg/analysis_server/test/resource_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698