OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, 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:io'; | |
6 | |
7 import 'dart:async' show | |
8 EventSink, | |
9 Future, | |
10 Stream, | |
11 StreamController, | |
12 StreamSubscription; | |
13 | |
14 import 'package:dart2js_incremental/dart2js_incremental.dart' show | |
15 IncrementalCompilationFailed, | |
16 IncrementalCompiler; | |
17 | |
18 import 'package:compiler/compiler_new.dart' show | |
19 CompilerOutput; | |
20 | |
21 import 'package:compiler/src/old_to_new_api.dart' show | |
22 LegacyCompilerDiagnostics, | |
23 LegacyCompilerInput; | |
24 | |
25 import 'package:compiler/src/source_file_provider.dart' show | |
26 FormattingDiagnosticHandler; | |
27 | |
28 import 'watcher.dart'; | |
29 | |
30 main(List<String> arguments) { | |
31 int updateCount = 0; | |
32 StreamSubscription<CompilerEvent> subscription = | |
33 compile(Uri.base.resolve(arguments.first)).listen(null); | |
34 subscription.onData((CompilerEvent event) { | |
35 switch (event.kind) { | |
36 case IncrementalKind.FULL: | |
37 updateCount = 0; | |
38 print('// Compiled JavaScript:'); | |
39 print(event['.js']); | |
40 break; | |
41 | |
42 case IncrementalKind.INCREMENTAL: | |
43 Stopwatch sw = event.stopwatch..start(); | |
44 String updates = '${event.compiler.allUpdates()}'; | |
45 sw.stop(); | |
46 | |
47 print('// Patch after ${++updateCount} updates,'); | |
48 print('// computed in ${sw.elapsedMicroseconds/1000000} seconds:'); | |
49 print(updates); | |
50 break; | |
51 | |
52 case IncrementalKind.ERROR: | |
53 updateCount = 0; | |
54 print("Compilation failed"); | |
55 break; | |
56 | |
57 default: | |
58 throw "Unknown kind: ${event.kind}"; | |
59 } | |
60 }); | |
61 subscription.onError((error, StackTrace trace) { | |
62 if (error is IncrementalCompilationFailed) { | |
63 print("Incremental compilation failed due to:\n${error.reason}"); | |
64 } else { | |
65 throw error; | |
66 } | |
67 }); | |
68 } | |
69 | |
70 Stream<CompilerEvent> compile(Uri originalInput) { | |
71 StreamController<CompilerEvent> controller = | |
72 new StreamController<CompilerEvent>(); | |
73 compileToStream(originalInput, controller); | |
74 return controller.stream; | |
75 } | |
76 | |
77 compileToStream( | |
78 Uri originalInput, | |
79 StreamController<CompilerEvent> controller) async { | |
80 var watcher = new Watcher(); | |
81 | |
82 Uri libraryRoot = Uri.base.resolve('sdk/'); | |
83 Uri packageRoot = Uri.base.resolve('packages/'); | |
84 | |
85 FormattingDiagnosticHandler diagnosticHandler = | |
86 new FormattingDiagnosticHandler(); | |
87 | |
88 OutputProvider outputProvider = new OutputProvider(); | |
89 | |
90 void resilientDiagnosticHandler( | |
91 Uri uri, int begin, int end, String message, kind) { | |
92 try { | |
93 diagnosticHandler(uri, begin, end, message, kind); | |
94 } catch (e) { | |
95 String name = diagnosticHandler.provider.relativizeUri(uri); | |
96 print('$name@$begin+${end - begin}: [$kind] $message}'); | |
97 } | |
98 } | |
99 | |
100 Future inputProvider(Uri uri) { | |
101 if (uri.scheme == "file") { | |
102 if (!'$uri'.startsWith('$libraryRoot')) { | |
103 watcher.watchFile(uri); | |
104 } | |
105 } | |
106 return diagnosticHandler.provider(uri); | |
107 } | |
108 | |
109 while (true) { | |
110 Stopwatch sw = new Stopwatch()..start(); | |
111 IncrementalCompiler compiler = new IncrementalCompiler( | |
112 libraryRoot: libraryRoot, | |
113 packageRoot: packageRoot, | |
114 inputProvider: new LegacyCompilerInput(inputProvider), | |
115 diagnosticHandler: | |
116 new LegacyCompilerDiagnostics(resilientDiagnosticHandler), | |
117 outputProvider: outputProvider); | |
118 | |
119 bool success = await compiler.compile(originalInput); | |
120 sw.stop(); | |
121 if (success) { | |
122 controller.add( | |
123 new CompilerEvent( | |
124 IncrementalKind.FULL, compiler, outputProvider.output, sw)); | |
125 } else { | |
126 controller.add( | |
127 new CompilerEvent( | |
128 IncrementalKind.ERROR, compiler, outputProvider.output, sw)); | |
129 } | |
130 | |
131 while (await watcher.hasChanges()) { | |
132 try { | |
133 Map<Uri, Uri> changes = watcher.readChanges(); | |
134 | |
135 sw = new Stopwatch()..start(); | |
136 String updates = await compiler.compileUpdates(changes); | |
137 sw.stop(); | |
138 | |
139 controller.add( | |
140 new CompilerEvent( | |
141 IncrementalKind.INCREMENTAL, compiler, outputProvider.output, | |
142 sw, updates: updates)); | |
143 | |
144 } on IncrementalCompilationFailed catch (error, trace) { | |
145 controller.addError(error, trace); | |
146 break; | |
147 } | |
148 } | |
149 } | |
150 } | |
151 | |
152 /// Output provider which collects output in [output]. | |
153 class OutputProvider implements CompilerOutput { | |
154 final Map<String, String> output = new Map<String, String>(); | |
155 | |
156 EventSink<String> createEventSink(String name, String extension) { | |
157 return new StringEventSink((String data) { | |
158 output['$name.$extension'] = data; | |
159 }); | |
160 } | |
161 | |
162 String operator[](String key) => output[key]; | |
163 } | |
164 | |
165 /// Helper class to collect sources. | |
166 class StringEventSink implements EventSink<String> { | |
167 List<String> data = <String>[]; | |
168 | |
169 final Function onClose; | |
170 | |
171 StringEventSink(this.onClose); | |
172 | |
173 void add(String event) { | |
174 if (data == null) throw 'StringEventSink is closed.'; | |
175 data.add(event); | |
176 } | |
177 | |
178 void addError(errorEvent, [StackTrace stackTrace]) { | |
179 throw 'addError($errorEvent, $stackTrace)'; | |
180 } | |
181 | |
182 void close() { | |
183 if (data != null) { | |
184 onClose(data.join()); | |
185 data = null; | |
186 } | |
187 } | |
188 } | |
189 | |
190 enum IncrementalKind { | |
191 FULL, | |
192 INCREMENTAL, | |
193 ERROR, | |
194 } | |
195 | |
196 class CompilerEvent { | |
197 final IncrementalKind kind; | |
198 | |
199 final IncrementalCompiler compiler; | |
200 | |
201 final Map<String, String> _output; | |
202 | |
203 final Stopwatch stopwatch; | |
204 | |
205 final String updates; | |
206 | |
207 CompilerEvent( | |
208 this.kind, this.compiler, this._output, this.stopwatch, {this.updates}); | |
209 | |
210 String operator[](String key) => _output[key]; | |
211 } | |
OLD | NEW |