OLD | NEW |
---|---|
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library sourcemap.helper; | 5 library sourcemap.helper; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'package:compiler/compiler_new.dart'; | 8 import 'package:compiler/compiler_new.dart'; |
9 import 'package:compiler/src/apiimpl.dart' as api; | 9 import 'package:compiler/src/apiimpl.dart' as api; |
10 import 'package:compiler/src/null_compiler_output.dart' show NullSink; | 10 import 'package:compiler/src/null_compiler_output.dart' show NullSink; |
11 import 'package:compiler/src/elements/elements.dart'; | 11 import 'package:compiler/src/elements/elements.dart'; |
12 import 'package:compiler/src/helpers/helpers.dart'; | 12 import 'package:compiler/src/helpers/helpers.dart'; |
13 import 'package:compiler/src/filenames.dart'; | 13 import 'package:compiler/src/filenames.dart'; |
14 import 'package:compiler/src/io/code_output.dart'; | |
14 import 'package:compiler/src/io/source_file.dart'; | 15 import 'package:compiler/src/io/source_file.dart'; |
15 import 'package:compiler/src/io/source_information.dart'; | 16 import 'package:compiler/src/io/source_information.dart'; |
17 import 'package:compiler/src/io/position_information.dart'; | |
16 import 'package:compiler/src/js/js.dart' as js; | 18 import 'package:compiler/src/js/js.dart' as js; |
17 import 'package:compiler/src/js/js_debug.dart'; | 19 import 'package:compiler/src/js/js_debug.dart'; |
18 import 'package:compiler/src/js/js_source_mapping.dart'; | 20 import 'package:compiler/src/js/js_source_mapping.dart'; |
19 import 'package:compiler/src/js_backend/js_backend.dart'; | 21 import 'package:compiler/src/js_backend/js_backend.dart'; |
20 import 'package:compiler/src/source_file_provider.dart'; | 22 import 'package:compiler/src/source_file_provider.dart'; |
21 import '../memory_compiler.dart'; | 23 import '../memory_compiler.dart'; |
22 import '../output_collector.dart'; | 24 import '../output_collector.dart'; |
23 | 25 |
26 class SourceFileSink implements EventSink<String> { | |
27 final String filename; | |
28 StringBuffer sb = new StringBuffer(); | |
29 SourceFile sourceFile; | |
30 | |
31 SourceFileSink(this.filename); | |
32 | |
33 @override | |
34 void add(String event) { | |
35 sb.write(event); | |
36 } | |
37 | |
38 @override | |
39 void addError(errorEvent, [StackTrace stackTrace]) { | |
40 // Ignore. | |
41 } | |
42 | |
43 @override | |
44 void close() { | |
45 sourceFile = new StringSourceFile.fromName(filename, sb.toString()); | |
46 } | |
47 } | |
48 | |
24 class OutputProvider implements CompilerOutput { | 49 class OutputProvider implements CompilerOutput { |
25 BufferedEventSink jsMapOutput; | 50 Map<Uri, SourceFileSink> outputMap = <Uri, SourceFileSink>{}; |
51 | |
52 SourceFile getSourceFile(Uri uri) { | |
53 SourceFileSink sink = outputMap[uri]; | |
54 if (sink != null) { | |
55 return sink.sourceFile; | |
56 } | |
57 return null; | |
58 } | |
59 | |
60 SourceFileSink createSourceFileSink(String name, String extension) { | |
61 String filename = '$name.$extension'; | |
62 SourceFileSink sink = new SourceFileSink(filename); | |
63 Uri uri = Uri.parse(filename); | |
64 outputMap[uri] = sink; | |
65 return sink; | |
66 } | |
26 | 67 |
27 @override | 68 @override |
28 EventSink<String> createEventSink(String name, String extension) { | 69 EventSink<String> createEventSink(String name, String extension) { |
29 if (extension == 'js.map') { | 70 return createSourceFileSink(name, extension); |
30 return jsMapOutput = new BufferedEventSink(); | |
31 } | |
32 return new NullSink('$name.$extension'); | |
33 } | 71 } |
34 } | 72 } |
35 | 73 |
36 class CloningOutputProvider extends OutputProvider { | 74 class CloningOutputProvider extends OutputProvider { |
37 RandomAccessFileOutputProvider outputProvider; | 75 RandomAccessFileOutputProvider outputProvider; |
38 | 76 |
39 CloningOutputProvider(Uri jsUri, Uri jsMapUri) | 77 CloningOutputProvider(Uri jsUri, Uri jsMapUri) |
40 : outputProvider = new RandomAccessFileOutputProvider(jsUri, jsMapUri); | 78 : outputProvider = new RandomAccessFileOutputProvider(jsUri, jsMapUri); |
41 | 79 |
42 @override | 80 @override |
43 EventSink<String> createEventSink(String name, String extension) { | 81 EventSink<String> createEventSink(String name, String extension) { |
44 EventSink<String> output = outputProvider(name, extension); | 82 EventSink<String> output = outputProvider(name, extension); |
45 if (extension == 'js.map') { | 83 return new CloningEventSink( |
46 output = new CloningEventSink( | 84 [output, createSourceFileSink(name, extension)]); |
47 [output, jsMapOutput = new BufferedEventSink()]); | |
48 } | |
49 return output; | |
50 } | 85 } |
51 } | 86 } |
52 | 87 |
53 abstract class SourceFileManager { | 88 abstract class SourceFileManager { |
54 SourceFile getSourceFile(var uri); | 89 SourceFile getSourceFile(var uri); |
55 } | 90 } |
56 | 91 |
57 class ProviderSourceFileManager implements SourceFileManager { | 92 class ProviderSourceFileManager implements SourceFileManager { |
58 final SourceFileProvider sourceFileProvider; | 93 final SourceFileProvider sourceFileProvider; |
94 final OutputProvider outputProvider; | |
59 | 95 |
60 ProviderSourceFileManager(this.sourceFileProvider); | 96 ProviderSourceFileManager(this.sourceFileProvider, this.outputProvider); |
61 | 97 |
62 @override | 98 @override |
63 SourceFile getSourceFile(uri) { | 99 SourceFile getSourceFile(uri) { |
64 return sourceFileProvider.getSourceFile(uri); | 100 SourceFile sourceFile = sourceFileProvider.getSourceFile(uri); |
101 if (sourceFile == null) { | |
102 sourceFile = outputProvider.getSourceFile(uri); | |
103 } | |
104 return sourceFile; | |
65 } | 105 } |
66 } | 106 } |
67 | 107 |
68 class RecordingPrintingContext extends LenientPrintingContext { | 108 class RecordingPrintingContext extends LenientPrintingContext { |
69 CodePositionListener listener; | 109 CodePositionListener listener; |
110 Map<js.Node, CodePosition> codePositions = <js.Node, CodePosition>{}; | |
70 | 111 |
71 RecordingPrintingContext(this.listener); | 112 RecordingPrintingContext(this.listener); |
72 | 113 |
73 @override | 114 @override |
74 void exitNode(js.Node node, | 115 void exitNode(js.Node node, |
75 int startPosition, | 116 int startPosition, |
76 int endPosition, | 117 int endPosition, |
77 int closingPosition) { | 118 int closingPosition) { |
119 codePositions[node] = | |
120 new CodePosition(startPosition, endPosition, closingPosition); | |
78 listener.onPositions( | 121 listener.onPositions( |
79 node, startPosition, endPosition, closingPosition); | 122 node, startPosition, endPosition, closingPosition); |
80 } | 123 } |
81 } | 124 } |
82 | 125 |
126 class SourceMapperWrapper implements SourceMapper { | |
Siggi Cherem (dart-lang)
2016/01/21 18:18:34
+ dartdoc, maybe rename to something more descript
Johnni Winther
2016/01/22 15:12:39
Done.
| |
127 final SourceMapper sourceMapper; | |
128 final NodeToSourceLocationRecorder nodeToSourceLocationsMap; | |
129 | |
130 SourceMapperWrapper(this.sourceMapper, this.nodeToSourceLocationsMap); | |
131 | |
132 @override | |
133 void register(js.Node node, int codeOffset, SourceLocation sourceLocation) { | |
134 nodeToSourceLocationsMap.register(node, codeOffset, sourceLocation); | |
135 sourceMapper.register(node, codeOffset, sourceLocation); | |
136 } | |
137 } | |
138 | |
139 class SourceInformationProcessorWrapper implements SourceInformationProcessor { | |
140 final SourceInformationStrategyWrapper wrapper; | |
141 final SourceInformationProcessor processor; | |
142 final CodePositionRecorder codePositions; | |
143 final NodeToSourceLocationsMap nodeToSourceLocationsMap; | |
144 | |
145 SourceInformationProcessorWrapper( | |
146 this.wrapper, | |
147 this.processor, | |
148 this.codePositions, | |
149 this.nodeToSourceLocationsMap); | |
150 | |
151 @override | |
152 void onPositions(js.Node node, | |
153 int startPosition, | |
154 int endPosition, | |
155 int closingPosition) { | |
156 codePositions.registerPositions( | |
157 node, startPosition, endPosition, closingPosition); | |
158 processor.onPositions(node, startPosition, endPosition, closingPosition); | |
159 } | |
160 | |
161 @override | |
162 void process(js.Node node, BufferedCodeOutput code) { | |
163 processor.process(node, code); | |
164 wrapper.registerProcess( | |
165 node, code, codePositions, nodeToSourceLocationsMap); | |
166 } | |
167 } | |
168 | |
169 class SourceInformationSubProcess { | |
Siggi Cherem (dart-lang)
2016/01/21 18:18:35
rename? SubProcess really makes me think that you
Johnni Winther
2016/01/22 15:12:39
Renamed to 'RecordedSourceInformationProcess'.
| |
170 final js.Node root; | |
171 final String code; | |
172 final CodePositionRecorder codePositions; | |
173 final NodeToSourceLocationsMap nodeToSourceLocationsMap; | |
174 | |
175 SourceInformationSubProcess( | |
176 this.root, | |
177 this.code, | |
178 this.codePositions, | |
179 this.nodeToSourceLocationsMap); | |
180 } | |
181 | |
182 | |
183 class SourceInformationStrategyWrapper | |
Siggi Cherem (dart-lang)
2016/01/21 18:18:35
it took me some time to figure out what these wrap
Johnni Winther
2016/01/22 15:12:38
It's (only) per element (also) output units. Updat
| |
184 extends JavaScriptSourceInformationStrategy { | |
185 final JavaScriptSourceInformationStrategy strategy; | |
186 final Map<SourceInformationSubProcess, js.Node> processMap = | |
187 <SourceInformationSubProcess, js.Node>{}; | |
188 final Map<js.Node, SourceInformationSubProcess> nodeMap = | |
189 <js.Node, SourceInformationSubProcess>{}; | |
190 | |
191 SourceInformationStrategyWrapper(this.strategy); | |
192 | |
193 @override | |
194 SourceInformationBuilder createBuilderForContext(AstElement element) { | |
195 return strategy.createBuilderForContext(element); | |
196 } | |
197 | |
198 @override | |
199 SourceInformationProcessor createProcessor(SourceMapper sourceMapper) { | |
200 NodeToSourceLocationsMap nodeToSourceLocationsMap = | |
201 new NodeToSourceLocationRecorder(); | |
202 CodePositionRecorder codePositions = new CodePositionRecorder(); | |
203 return new SourceInformationProcessorWrapper( | |
204 this, | |
205 strategy.createProcessor(new SourceMapperWrapper( | |
206 sourceMapper, nodeToSourceLocationsMap)), | |
207 codePositions, nodeToSourceLocationsMap); | |
208 } | |
209 | |
210 void registerProcess(js.Node root, | |
211 BufferedCodeOutput code, | |
212 CodePositionRecorder codePositions, | |
213 NodeToSourceLocationsMap nodeToSourceLocationsMap) { | |
214 SourceInformationSubProcess subProcess = new SourceInformationSubProcess( | |
215 root, code.getText(), codePositions, nodeToSourceLocationsMap); | |
216 processMap[subProcess] = root; | |
217 } | |
218 | |
219 SourceInformationSubProcess subProcessForNode(js.Node node) { | |
220 return nodeMap.putIfAbsent(node, () { | |
221 for (SourceInformationSubProcess subProcess in processMap.keys) { | |
222 js.Node root = processMap[subProcess]; | |
223 FindVisitor visitor = new FindVisitor(node); | |
224 root.accept(visitor); | |
225 if (visitor.found) { | |
226 return new SourceInformationSubProcess( | |
227 node, | |
228 subProcess.code, | |
229 subProcess.codePositions, | |
230 new NodeToSourceLocationsMapWrapper( | |
231 visitor.nodes, subProcess.nodeToSourceLocationsMap)); | |
232 } | |
233 return null; | |
234 } | |
235 }); | |
236 } | |
237 } | |
238 | |
239 class FindVisitor extends js.BaseVisitor { | |
Siggi Cherem (dart-lang)
2016/01/21 18:18:34
+dartdoc:
/// Visitor that collects all nodes tha
| |
240 final js.Node soughtNode; | |
241 bool found = false; | |
242 bool add = false; | |
243 final Set<js.Node> nodes = new Set<js.Node>(); | |
244 | |
245 FindVisitor(this.soughtNode); | |
246 | |
247 visitNode(js.Node node) { | |
248 if (node == soughtNode) { | |
249 found = true; | |
250 add = true; | |
251 } | |
252 if (add) { | |
253 nodes.add(node); | |
254 } | |
255 node.visitChildren(this); | |
256 if (node == soughtNode) { | |
257 add = false; | |
258 } | |
259 } | |
260 } | |
261 | |
262 const String USE_NEW_SOURCE_INFO = '--use-new-source-info'; | |
263 const String DISABLE_INLINING = '--disable-inlining'; | |
264 | |
83 /// Processor that computes [SourceMapInfo] for the JavaScript compiled for a | 265 /// Processor that computes [SourceMapInfo] for the JavaScript compiled for a |
84 /// given Dart file. | 266 /// given Dart file. |
85 class SourceMapProcessor { | 267 class SourceMapProcessor { |
86 /// If `true` the output from the compilation is written to files. | 268 /// If `true` the output from the compilation is written to files. |
87 final bool outputToFile; | 269 final bool outputToFile; |
88 | 270 |
89 /// The [Uri] of the Dart entrypoint. | 271 /// The [Uri] of the Dart entrypoint. |
90 Uri inputUri; | 272 Uri inputUri; |
91 | 273 |
92 /// The name of the JavaScript output file. | 274 /// The name of the JavaScript output file. |
(...skipping 12 matching lines...) Expand all Loading... | |
105 SourceMapProcessor(String filename, {this.outputToFile: false}) { | 287 SourceMapProcessor(String filename, {this.outputToFile: false}) { |
106 inputUri = Uri.base.resolve(nativeToUriPath(filename)); | 288 inputUri = Uri.base.resolve(nativeToUriPath(filename)); |
107 jsPath = 'out.js'; | 289 jsPath = 'out.js'; |
108 targetUri = Uri.base.resolve(jsPath); | 290 targetUri = Uri.base.resolve(jsPath); |
109 sourceMapFileUri = Uri.base.resolve('${jsPath}.map'); | 291 sourceMapFileUri = Uri.base.resolve('${jsPath}.map'); |
110 } | 292 } |
111 | 293 |
112 /// Computes the [SourceMapInfo] for the compiled elements. | 294 /// Computes the [SourceMapInfo] for the compiled elements. |
113 Future<List<SourceMapInfo>> process( | 295 Future<List<SourceMapInfo>> process( |
114 List<String> options, | 296 List<String> options, |
115 {bool verbose: true}) async { | 297 {bool verbose: true, |
298 bool perElement: true}) async { | |
116 OutputProvider outputProvider = outputToFile | 299 OutputProvider outputProvider = outputToFile |
117 ? new OutputProvider() | 300 ? new CloningOutputProvider(targetUri, sourceMapFileUri) |
118 : new CloningOutputProvider(targetUri, sourceMapFileUri); | 301 : new OutputProvider(); |
119 if (options.contains('--use-new-source-info')) { | 302 if (options.contains(USE_NEW_SOURCE_INFO)) { |
120 if (verbose) print('Using the new source information system.'); | 303 if (verbose) print('Using the new source information system.'); |
121 useNewSourceInfo = true; | 304 useNewSourceInfo = true; |
122 } | 305 } |
123 api.CompilerImpl compiler = await compilerFor( | 306 api.CompilerImpl compiler = await compilerFor( |
124 outputProvider: outputProvider, | 307 outputProvider: outputProvider, |
125 // TODO(johnniwinther): Use [verbose] to avoid showing diagnostics. | 308 // TODO(johnniwinther): Use [verbose] to avoid showing diagnostics. |
126 options: ['--out=$targetUri', '--source-map=$sourceMapFileUri'] | 309 options: ['--out=$targetUri', '--source-map=$sourceMapFileUri'] |
127 ..addAll(options)); | 310 ..addAll(options)); |
128 if (options.contains('--disable-inlining')) { | 311 if (options.contains(DISABLE_INLINING)) { |
129 if (verbose) print('Inlining disabled'); | 312 if (verbose) print('Inlining disabled'); |
130 compiler.disableInlining = true; | 313 compiler.disableInlining = true; |
131 } | 314 } |
132 | 315 |
133 JavaScriptBackend backend = compiler.backend; | 316 JavaScriptBackend backend = compiler.backend; |
134 var handler = compiler.handler; | 317 var handler = compiler.handler; |
135 SourceFileProvider sourceFileProvider = handler.provider; | 318 SourceFileProvider sourceFileProvider = handler.provider; |
136 sourceFileManager = new ProviderSourceFileManager(sourceFileProvider); | 319 sourceFileManager = new ProviderSourceFileManager( |
320 sourceFileProvider, | |
321 outputProvider); | |
322 SourceInformationStrategyWrapper strategy = | |
323 new SourceInformationStrategyWrapper(backend.sourceInformationStrategy); | |
324 backend.sourceInformationStrategy = strategy; | |
137 await compiler.run(inputUri); | 325 await compiler.run(inputUri); |
138 | 326 |
139 List<SourceMapInfo> infoList = <SourceMapInfo>[]; | 327 List<SourceMapInfo> infoList = <SourceMapInfo>[]; |
140 backend.generatedCode.forEach((Element element, js.Expression node) { | 328 if (perElement) { |
141 js.JavaScriptPrintingOptions options = | 329 backend.generatedCode.forEach((Element element, js.Expression node) { |
142 new js.JavaScriptPrintingOptions(); | 330 SourceInformationSubProcess subProcess = |
143 JavaScriptSourceInformationStrategy sourceInformationStrategy = | 331 strategy.subProcessForNode(node); |
144 compiler.backend.sourceInformationStrategy; | 332 if (subProcess == null) { |
145 NodeToSourceLocationsMap nodeMap = new NodeToSourceLocationsMap(); | 333 // TODO(johnniwinther): Find out when this is happening and if it |
146 SourceInformationProcessor sourceInformationProcessor = | 334 // is benign. (Known to happen for `bool#fromString`) |
147 sourceInformationStrategy.createProcessor(nodeMap); | 335 print('No subProcess found for $element'); |
148 RecordingPrintingContext printingContext = | 336 return; |
149 new RecordingPrintingContext(sourceInformationProcessor); | 337 } |
150 new js.Printer(options, printingContext).visit(node); | 338 NodeToSourceLocationsMap nodeMap = subProcess.nodeToSourceLocationsMap; |
151 sourceInformationProcessor.process(node); | 339 String code = subProcess.code; |
152 | 340 CodePositionRecorder codePositions = subProcess.codePositions; |
153 String code = printingContext.getText(); | 341 CodePointComputer visitor = |
342 new CodePointComputer(sourceFileManager, code, nodeMap); | |
343 visitor.apply(node); | |
344 List<CodePoint> codePoints = visitor.codePoints; | |
345 infoList.add(new SourceMapInfo( | |
346 element, code, node, | |
347 codePoints, | |
348 codePositions/*strategy.codePositions*/, | |
349 nodeMap)); | |
350 }); | |
351 } else { | |
352 // TODO(johnniwinther): Supported multiple output units. | |
353 SourceInformationSubProcess process = strategy.processMap.keys.first; | |
354 js.Node node = strategy.processMap[process]; | |
355 String code; | |
356 NodeToSourceLocationsMap nodeMap; | |
357 CodePositionRecorder codePositions; | |
358 nodeMap = process.nodeToSourceLocationsMap; | |
359 code = process.code; | |
360 codePositions = process.codePositions; | |
154 CodePointComputer visitor = | 361 CodePointComputer visitor = |
155 new CodePointComputer(sourceFileManager, code, nodeMap); | 362 new CodePointComputer(sourceFileManager, code, nodeMap); |
156 visitor.apply(node); | 363 visitor.apply(node); |
157 List<CodePoint> codePoints = visitor.codePoints; | 364 List<CodePoint> codePoints = visitor.codePoints; |
158 infoList.add(new SourceMapInfo(element, code, node, codePoints, nodeMap)); | 365 infoList.add(new SourceMapInfo( |
159 }); | 366 null, code, node, |
367 codePoints, | |
368 codePositions, | |
369 nodeMap)); | |
370 } | |
160 | 371 |
161 return infoList; | 372 return infoList; |
162 } | 373 } |
163 } | 374 } |
164 | 375 |
165 /// Source mapping information for the JavaScript code of an [Element]. | 376 /// Source mapping information for the JavaScript code of an [Element]. |
166 class SourceMapInfo { | 377 class SourceMapInfo { |
167 final String name; | 378 final String name; |
168 final Element element; | 379 final Element element; |
169 final String code; | 380 final String code; |
170 final js.Expression node; | 381 final js.Node node; |
171 final List<CodePoint> codePoints; | 382 final List<CodePoint> codePoints; |
383 final CodePositionMap jsCodePositions; | |
172 final NodeToSourceLocationsMap nodeMap; | 384 final NodeToSourceLocationsMap nodeMap; |
173 | 385 |
174 SourceMapInfo( | 386 SourceMapInfo( |
175 Element element, this.code, this.node, this.codePoints, this.nodeMap) | 387 Element element, |
176 : this.name = computeElementNameForSourceMaps(element), | 388 this.code, |
389 this.node, | |
390 this.codePoints, | |
391 this.jsCodePositions, | |
392 this.nodeMap) | |
393 : this.name = | |
394 element != null ? computeElementNameForSourceMaps(element) : '', | |
177 this.element = element; | 395 this.element = element; |
396 | |
397 String toString() { | |
398 return '$name:$element'; | |
399 } | |
178 } | 400 } |
179 | 401 |
180 /// Collection of JavaScript nodes with their source mapped target offsets | 402 /// Collection of JavaScript nodes with their source mapped target offsets |
181 /// and source locations. | 403 /// and source locations. |
182 class NodeToSourceLocationsMap implements SourceMapper { | 404 abstract class NodeToSourceLocationsMap { |
405 Iterable<js.Node> get nodes; | |
406 | |
407 Map<int, List<SourceLocation>> operator[] (js.Node node); | |
408 } | |
409 | |
410 class NodeToSourceLocationRecorder | |
411 implements SourceMapper, NodeToSourceLocationsMap { | |
183 final Map<js.Node, Map<int, List<SourceLocation>>> _nodeMap = {}; | 412 final Map<js.Node, Map<int, List<SourceLocation>>> _nodeMap = {}; |
184 | 413 |
185 @override | 414 @override |
186 void register(js.Node node, int codeOffset, SourceLocation sourceLocation) { | 415 void register(js.Node node, int codeOffset, SourceLocation sourceLocation) { |
187 _nodeMap.putIfAbsent(node, () => {}) | 416 _nodeMap.putIfAbsent(node, () => {}) |
188 .putIfAbsent(codeOffset, () => []) | 417 .putIfAbsent(codeOffset, () => []) |
189 .add(sourceLocation); | 418 .add(sourceLocation); |
190 } | 419 } |
191 | 420 |
192 Iterable<js.Node> get nodes => _nodeMap.keys; | 421 Iterable<js.Node> get nodes => _nodeMap.keys; |
193 | 422 |
194 Map<int, List<SourceLocation>> operator[] (js.Node node) { | 423 Map<int, List<SourceLocation>> operator[] (js.Node node) { |
195 return _nodeMap[node]; | 424 return _nodeMap[node]; |
196 } | 425 } |
197 } | 426 } |
198 | 427 |
428 class NodeToSourceLocationsMapWrapper implements NodeToSourceLocationsMap { | |
Siggi Cherem (dart-lang)
2016/01/21 18:18:35
nits/ideas:
- rename to PerElementNodeToSourceLoc
| |
429 final Set<js.Node> _nodes; | |
430 final NodeToSourceLocationsMap map; | |
431 | |
432 NodeToSourceLocationsMapWrapper(this._nodes, this.map); | |
433 | |
434 Iterable<js.Node> get nodes => map.nodes.where((n) => _nodes.contains(n)); | |
435 | |
436 Map<int, List<SourceLocation>> operator[] (js.Node node) { | |
437 return map[node]; | |
438 } | |
439 } | |
440 | |
441 | |
199 /// Visitor that computes the [CodePoint]s for source mapping locations. | 442 /// Visitor that computes the [CodePoint]s for source mapping locations. |
200 class CodePointComputer extends js.BaseVisitor { | 443 class CodePointComputer extends js.BaseVisitor { |
201 final SourceFileManager sourceFileManager; | 444 final SourceFileManager sourceFileManager; |
202 final String code; | 445 final String code; |
203 final NodeToSourceLocationsMap nodeMap; | 446 final NodeToSourceLocationsMap nodeMap; |
204 List<CodePoint> codePoints = []; | 447 List<CodePoint> codePoints = []; |
205 | 448 |
206 CodePointComputer(this.sourceFileManager, this.code, this.nodeMap); | 449 CodePointComputer(this.sourceFileManager, this.code, this.nodeMap); |
207 | 450 |
208 String nodeToString(js.Node node) { | 451 String nodeToString(js.Node node) { |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
329 this.jsCode, | 572 this.jsCode, |
330 this.sourceLocation, | 573 this.sourceLocation, |
331 this.dartCode, | 574 this.dartCode, |
332 {this.isMissing: false}); | 575 {this.isMissing: false}); |
333 | 576 |
334 String toString() { | 577 String toString() { |
335 return 'CodePoint[kind=$kind,js=$jsCode,dart=$dartCode,' | 578 return 'CodePoint[kind=$kind,js=$jsCode,dart=$dartCode,' |
336 'location=$sourceLocation]'; | 579 'location=$sourceLocation]'; |
337 } | 580 } |
338 } | 581 } |
OLD | NEW |