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

Side by Side Diff: pkg/front_end/lib/src/incremental_resolved_ast_generator_impl.dart

Issue 2624193003: Work in progress: front end hot reload API (Closed)
Patch Set: First steel thread of functionality. Created 3 years, 11 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
OLDNEW
(Empty)
1 // Copyright (c) 2017, 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 import 'dart:async';
6
7 import 'package:analyzer/file_system/file_system.dart';
8 import 'package:analyzer/src/context/context.dart';
9 import 'package:analyzer/src/dart/analysis/byte_store.dart';
10 import 'package:analyzer/src/dart/analysis/driver.dart' as driver;
11 import 'package:analyzer/src/dart/analysis/file_state.dart';
12 import 'package:analyzer/src/generated/engine.dart';
13 import 'package:analyzer/src/generated/sdk.dart';
14 import 'package:analyzer/src/generated/source.dart';
15 import 'package:analyzer/src/summary/idl.dart';
16 import 'package:analyzer/src/summary/summary_sdk.dart';
17 import 'package:analyzer/src/util/absolute_path.dart';
18 import 'package:front_end/incremental_resolved_ast_generator.dart';
19 import 'package:front_end/src/base/processed_options.dart';
20 import 'package:front_end/src/base/source.dart';
21 import 'package:front_end/src/dependency_grapher_impl.dart';
22 import 'package:path/src/context.dart';
23
24 dynamic unimplemented() {
25 // TODO(paulberry): get rid of this.
26 throw new UnimplementedError();
27 }
28
29 /// Implementation of [IncrementalKernelGenerator].
30 ///
31 /// Theory of operation: this class is a thin wrapper around
32 /// [driver.AnalysisDriver]. When the client requests a new delta, we forward
33 /// the request to the analysis driver. When the client calls an invalidate
34 /// method, we ensure that the proper files will be re-read next time a delta is
35 /// requested.
36 ///
37 /// Note that the analysis driver expects to be able to read file contents
38 /// synchronously based on filesystem path rather than asynchronously based on
39 /// URI, so the file contents are first read into memory using the asynchronous
40 /// FileSystem API, and then these are fed into the analysis driver using a
41 /// proxy implementation of [ResourceProvider]. TODO(paulberry): make this (and
42 /// other proxies in this file) unnecessary.
43 class IncrementalResolvedAstGeneratorImpl
44 implements IncrementalResolvedAstGenerator {
45 driver.AnalysisDriverScheduler _scheduler;
46 final _pathToUriMap = <String, Uri>{};
47 final _uriToPathMap = <Uri, String>{};
48 final _fileContents = <String, String>{};
49 _ResourceProviderProxy _resourceProvider;
50 driver.AnalysisDriver _driver;
51 bool _isInitialized = false;
52 final ProcessedOptions _options;
53 final Uri _source;
54
55 IncrementalResolvedAstGeneratorImpl(this._source, this._options);
56
57 @override
58 Future<DeltaLibraries> computeDelta() async {
59 if (!_isInitialized) {
60 await init();
61 }
62 // The analysis driver doesn't currently support an asynchronous file API,
63 // so we have to find all the files first to read their contents.
64 // TODO(paulberry): this is an unnecessary source of duplicate work and
65 // should be eliminated ASAP.
66 var graph = await graphForProgram([_source], _options);
67 var libraries = <Uri, ResolvedLibrary>{};
68 // TODO(paulberry): it should be possible to seed the driver using a URI,
69 // not a file path.
70 // TODO(paulberry): only start the scheduler the first time.
71 _scheduler.start();
72 _driver.addFile(_source.path);
73 for (var libraryCycle in graph.topologicallySortedCycles) {
74 for (var uri in libraryCycle.libraries.keys) {
75 var contents =
76 await _options.fileSystem.entityForUri(uri).readAsString();
77 _storeVirtualFile(uri, uri.path, contents);
78 }
79 // The driver will request files from dart:, even though it actually uses
80 // the data from the summary. TODO(paulberry): fix this.
81 _storeVirtualFile(_DartSdkProxy._dartCoreSource.uri, 'core.dart', '');
82 for (var uri in libraryCycle.libraries.keys) {
83 var result = await _driver.getResult(uri.path);
84 // TODO(paulberry): handle errors.
85 libraries[uri] = new ResolvedLibrary(result.unit);
86 }
87 }
88 // TODO(paulberry): stop the scheduler
89 return new DeltaLibraries(libraries);
90 }
91
92 Future<Null> init() async {
93 // TODO(paulberry): can we just use null?
94 var performanceLog = new driver.PerformanceLog(new _NullStringSink());
95 _scheduler = new driver.AnalysisDriverScheduler(performanceLog);
96 _resourceProvider =
97 new _ResourceProviderProxy(_fileContents, _pathToUriMap);
98 // TODO(paulberry): MemoryByteStore leaks memory (it never discards data).
99 // Do something better here.
100 var byteStore = new MemoryByteStore();
101 // TODO(paulberry): can we just use null?
102 var fileContentOverlay = new FileContentOverlay();
103 var sdkContext = new AnalysisContextImpl();
104 var dartSdk = new _DartSdkProxy(await _options.getSdkSummary(), sdkContext);
105 sdkContext.sourceFactory =
106 new SourceFactory([new DartUriResolver(dartSdk)]);
107 bool strongMode = true; // TODO(paulberry): support strong mode flag.
108 sdkContext.resultProvider = new SdkSummaryResultProvider(
109 sdkContext, await _options.getSdkSummary(), strongMode);
110
111 var sourceFactory =
112 new _SourceFactoryProxy(dartSdk, _pathToUriMap, _uriToPathMap);
113 var analysisOptions = new AnalysisOptionsImpl();
114 _driver = new driver.AnalysisDriver(
115 _scheduler,
116 performanceLog,
117 _resourceProvider,
118 byteStore,
119 fileContentOverlay,
120 sourceFactory,
121 analysisOptions);
122 _isInitialized = true;
123 }
124
125 @override
126 void invalidate(String path) {
127 throw new UnimplementedError();
128 }
129
130 @override
131 void invalidateAll() {
132 throw new UnimplementedError();
133 }
134
135 void _storeVirtualFile(Uri uri, String path, String contents) {
136 _pathToUriMap[path] = uri;
137 _uriToPathMap[uri] = path;
138 _fileContents[path] = contents;
139 }
140 }
141
142 class _DartSdkProxy implements DartSdk {
143 static final _dartCoreSource =
144 new _SourceProxy(Uri.parse('dart:core'), 'core.dart');
145
146 final PackageBundle summary;
147
148 final AnalysisContext context;
149
150 _DartSdkProxy(this.summary, this.context);
151
152 @override
153 PackageBundle getLinkedBundle() => summary;
154
155 @override
156 Source mapDartUri(String uri) {
157 // TODO(paulberry): this seems hacky.
158 return new _SourceProxy(Uri.parse(uri), '$uri.dart');
159 }
160
161 noSuchMethod(Invocation invocation) => unimplemented();
162 }
163
164 class _FileProxy implements File {
165 final _SourceProxy _source;
166
167 final _ResourceProviderProxy _resourceProvider;
168
169 _FileProxy(this._source, this._resourceProvider);
170
171 @override
172 String get path => _source.fullName;
173
174 @override
175 String get shortName => path;
176
177 @override
178 Source createSource([Uri uri]) {
179 assert(uri == null);
180 return _source;
181 }
182
183 noSuchMethod(Invocation invocation) => unimplemented();
184
185 @override
186 String readAsStringSync() {
187 assert(_resourceProvider.fileContents.containsKey(path));
188 return _resourceProvider.fileContents[path];
189 }
190 }
191
192 /// A string sink that ignores everything written to it.
193 class _NullStringSink implements StringSink {
194 void write(Object obj) {}
195 void writeAll(Iterable objects, [String separator = ""]) {}
196 void writeCharCode(int charCode) {}
197 void writeln([Object obj = ""]) {}
198 }
199
200 class _ResourceProviderProxy implements ResourceProvider {
201 final Map<String, String> fileContents;
202 final Map<String, Uri> pathToUriMap;
203
204 _ResourceProviderProxy(this.fileContents, this.pathToUriMap);
205
206 @override
207 AbsolutePathContext get absolutePathContext => throw new UnimplementedError();
208
209 @override
210 Context get pathContext => throw new UnimplementedError();
211
212 @override
213 File getFile(String path) {
214 assert(fileContents.containsKey(path));
215 assert(pathToUriMap.containsKey(path));
216 return new _FileProxy(new _SourceProxy(pathToUriMap[path], path), this);
217 }
218
219 @override
220 Folder getFolder(String path) => throw new UnimplementedError();
221
222 @override
223 Future<List<int>> getModificationTimes(List<Source> sources) =>
224 throw new UnimplementedError();
225
226 @override
227 Resource getResource(String path) => throw new UnimplementedError();
228
229 @override
230 Folder getStateLocation(String pluginId) => throw new UnimplementedError();
231 }
232
233 class _SourceFactoryProxy implements SourceFactory {
234 @override
235 final DartSdk dartSdk;
236
237 final Map<String, Uri> pathToUriMap;
238
239 final Map<Uri, String> uriToPathMap;
240
241 @override
242 AnalysisContext context;
243
244 _SourceFactoryProxy(this.dartSdk, this.pathToUriMap, this.uriToPathMap);
245
246 @override
247 SourceFactory clone() => this;
248
249 @override
250 Source forUri(String absoluteUri) {
251 if (absoluteUri == 'dart:core') return _DartSdkProxy._dartCoreSource;
252 Uri uri = Uri.parse(absoluteUri);
253 assert(uriToPathMap.containsKey(uri));
254 return new _SourceProxy(uri, uriToPathMap[uri]);
255 }
256
257 noSuchMethod(Invocation invocation) => unimplemented();
258
259 Source resolveUri(Source containingSource, String containedUri) {
260 // TODO(paulberry): re-use code from dependency_grapher_impl, and support
261 // SDK URI resolution logic.
262 var absoluteUri = containingSource.uri.resolve(containedUri);
263 return forUri(absoluteUri.toString());
264 }
265
266 @override
267 Uri restoreUri(Source source) => source.uri;
268 }
269
270 class _SourceProxy extends BasicSource {
271 @override
272 final String fullName;
273
274 _SourceProxy(Uri uri, this.fullName) : super(uri);
275
276 int get modificationStamp => 0;
277
278 noSuchMethod(Invocation invocation) => unimplemented();
279 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698