OLD | NEW |
---|---|
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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.diff; | 5 library sourcemap.diff; |
6 | 6 |
7 import 'package:compiler/src/io/source_file.dart'; | 7 import 'package:compiler/src/io/source_file.dart'; |
8 | 8 |
9 import 'html_parts.dart'; | 9 import 'html_parts.dart'; |
10 import 'output_structure.dart'; | 10 import 'output_structure.dart'; |
11 import 'sourcemap_helper.dart'; | 11 import 'sourcemap_helper.dart'; |
12 import 'sourcemap_html_helper.dart'; | |
12 | 13 |
13 enum DiffKind { | 14 enum DiffKind { |
14 UNMATCHED, | 15 UNMATCHED, |
15 MATCHING, | 16 MATCHING, |
16 IDENTICAL, | 17 IDENTICAL, |
17 } | 18 } |
18 | 19 |
20 /// Id for an output column. | |
21 class DiffColumn { | |
22 final String type; | |
23 final int index; | |
24 | |
25 const DiffColumn(this.type, [this.index]); | |
26 | |
27 int get hashCode => type.hashCode * 19 + index.hashCode * 23; | |
28 | |
29 bool operator ==(other) { | |
30 if (identical(this, other)) return true; | |
31 if (other is! DiffColumn) return false; | |
32 return type == other.type && index == other.index; | |
33 } | |
34 | |
35 String toString() => '$type${index != null ? index : ''}'; | |
36 } | |
37 | |
38 /// A block of code in an output column. | |
39 abstract class DiffColumnBlock { | |
40 void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context); | |
41 } | |
42 | |
43 /// A block consisting of pure HTML parts. | |
44 class PartsColumnBlock extends DiffColumnBlock { | |
45 final List<HtmlPart> parts; | |
46 | |
47 PartsColumnBlock(this.parts); | |
48 | |
49 void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) { | |
50 if (parts.isNotEmpty) { | |
51 for (HtmlPart part in parts) { | |
52 part.printHtmlOn(htmlBuffer, context); | |
53 } | |
54 } | |
55 } | |
56 } | |
57 | |
58 /// A block consisting of line-per-line JavaScript and source mapped Dart code. | |
59 class CodeLinesColumnBlock extends DiffColumnBlock { | |
60 final List<CodeLine> jsCodeLines; | |
61 final Map<CodeLine, List<CodeLine>> jsToDartMap; | |
62 | |
63 CodeLinesColumnBlock(this.jsCodeLines, this.jsToDartMap); | |
64 | |
65 void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) { | |
66 if (jsCodeLines.isNotEmpty) { | |
67 htmlBuffer.write('<table style="width:100%">'); | |
68 for (CodeLine codeLine in jsCodeLines) { | |
69 htmlBuffer.write('<tr><td class="${ClassNames.innerCell}">'); | |
70 codeLine.printHtmlOn(htmlBuffer, context); | |
71 htmlBuffer.write( | |
72 '</td><td ' | |
73 'class="${ClassNames.innerCell} ${ClassNames.sourceMapped}">'); | |
74 List<CodeLine> lines = jsToDartMap[codeLine]; | |
75 if (lines != null) { | |
76 for (CodeLine line in lines) { | |
77 line.printHtmlOn(htmlBuffer, | |
78 context.from(includeAnnotation: (a) { | |
79 CodeLineAnnotation annotation = a.data; | |
80 return annotation.annotationType.isSourceMapped; | |
81 })); | |
82 } | |
83 } | |
84 htmlBuffer.write('</td></tr>'); | |
85 } | |
86 htmlBuffer.write('</table>'); | |
87 } | |
88 } | |
89 } | |
90 | |
19 /// A list of columns that should align in output. | 91 /// A list of columns that should align in output. |
20 class DiffBlock { | 92 class DiffBlock { |
21 final DiffKind kind; | 93 final DiffKind kind; |
22 List<List<HtmlPart>> columns = <List<HtmlPart>>[]; | 94 Map<DiffColumn, DiffColumnBlock> _columns = <DiffColumn, DiffColumnBlock>{}; |
23 | 95 |
24 DiffBlock(this.kind); | 96 DiffBlock(this.kind); |
25 | 97 |
26 void addColumn(int index, List<HtmlPart> lines) { | 98 void addColumnBlock(DiffColumn column, DiffColumnBlock block) { |
27 if (index >= columns.length) { | 99 _columns[column] = block; |
28 columns.length = index + 1; | |
29 } | |
30 columns[index] = lines; | |
31 } | 100 } |
32 | 101 |
33 List<HtmlPart> getColumn(int index) { | 102 Iterable<DiffColumn> get columns => _columns.keys; |
34 List<HtmlPart> lines; | 103 |
35 if (index < columns.length) { | 104 void printHtmlOn(DiffColumn column, |
36 lines = columns[index]; | 105 StringBuffer htmlBuffer, |
106 HtmlPrintContext context) { | |
107 DiffColumnBlock block = _columns[column]; | |
108 if (block != null) { | |
109 block.printHtmlOn(htmlBuffer, context); | |
37 } | 110 } |
38 return lines != null ? lines : const <HtmlPart>[]; | |
39 } | 111 } |
40 } | 112 } |
41 | 113 |
42 | 114 |
43 /// Align the content of [list1] and [list2]. | 115 /// Align the content of [list1] and [list2]. |
44 /// | 116 /// |
45 /// If provided, [range1] and [range2] aligned the subranges of [list1] and | 117 /// If provided, [range1] and [range2] aligned the subranges of [list1] and |
46 /// [list2], otherwise the whole lists are aligned. | 118 /// [list2], otherwise the whole lists are aligned. |
47 /// | 119 /// |
48 /// If provided, [match] determines the equality between members of [list1] and | 120 /// If provided, [match] determines the equality between members of [list1] and |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
169 List<List<CodeLine>> inputLines; | 241 List<List<CodeLine>> inputLines; |
170 | 242 |
171 List<int> nextInputLine = [0, 0]; | 243 List<int> nextInputLine = [0, 0]; |
172 | 244 |
173 List<DiffBlock> blocks = <DiffBlock>[]; | 245 List<DiffBlock> blocks = <DiffBlock>[]; |
174 | 246 |
175 DiffCreator(List<OutputStructure> structures, this.sourceFileManager) | 247 DiffCreator(List<OutputStructure> structures, this.sourceFileManager) |
176 : this.structures = structures, | 248 : this.structures = structures, |
177 this.inputLines = structures.map((s) => s.lines).toList(); | 249 this.inputLines = structures.map((s) => s.lines).toList(); |
178 | 250 |
179 CodeSource codeSourceFromEntities(Iterable<OutputEntity> entities) { | 251 /// Compute [CodeSource]s defined by [entities]. |
252 Iterable<CodeSource> codeSourceFromEntities(Iterable<OutputEntity> entities) { | |
253 Set<CodeSource> sources = new Set<CodeSource>(); | |
180 for (OutputEntity entity in entities) { | 254 for (OutputEntity entity in entities) { |
181 if (entity.codeSource != null) { | 255 if (entity.codeSource != null) { |
182 return entity.codeSource; | 256 sources.add(entity.codeSource); |
183 } | 257 } |
184 } | 258 } |
185 return null; | 259 return sources; |
260 } | |
261 | |
262 /// Create a block with the code from [codeSources]. The [CodeSource]s in | |
263 /// [mainSources] are tagged as original code sources, the rest as inlined | |
264 /// code sources. | |
265 DiffColumnBlock codeLinesFromCodeSources( | |
266 Iterable<CodeSource> mainSources, | |
267 Iterable<CodeSource> codeSources) { | |
268 List<HtmlPart> parts = <HtmlPart>[]; | |
269 for (CodeSource codeSource in codeSources) { | |
270 //parts.addAll(codeLinesFromCodeSource(codeSource)); | |
271 String className = | |
272 mainSources.contains(codeSource) | |
273 ? ClassNames.mainDart : ClassNames.inlinedDart; | |
274 parts.add( | |
275 new TagPart('div', | |
276 properties: {'class': className}, | |
277 content: codeLinesFromCodeSource(codeSource))); | |
278 } | |
279 return new PartsColumnBlock(parts); | |
280 } | |
281 | |
282 /// Adds all [CodeSource]s used in [dartCodeLines] to [codeSourceSet]. | |
283 void collectCodeSources(Set<CodeSource> codeSourceSet, | |
284 Map<CodeLine, List<CodeLine>> dartCodeLines) { | |
285 for (List<CodeLine> codeLines in dartCodeLines.values) { | |
286 for (CodeLine dartCodeLine in codeLines) { | |
287 if (dartCodeLine.lineAnnotation != null) { | |
288 codeSourceSet.add(dartCodeLine.lineAnnotation); | |
289 } | |
290 } | |
291 } | |
186 } | 292 } |
187 | 293 |
188 /// Checks that lines are added in sequence without gaps or duplicates. | 294 /// Checks that lines are added in sequence without gaps or duplicates. |
189 void checkLineInvariant(int index, Interval range) { | 295 void checkLineInvariant(int index, Interval range) { |
190 int expectedLineNo = nextInputLine[index]; | 296 int expectedLineNo = nextInputLine[index]; |
191 if (range.from != expectedLineNo) { | 297 if (range.from != expectedLineNo) { |
192 print('Expected line no $expectedLineNo, found ${range.from}'); | 298 print('Expected line no $expectedLineNo, found ${range.from}'); |
193 if (range.from < expectedLineNo) { | 299 if (range.from < expectedLineNo) { |
194 print('Duplicate lines:'); | 300 print('Duplicate lines:'); |
195 int i = range.from; | 301 int i = range.from; |
196 while (i <= expectedLineNo) { | 302 while (i <= expectedLineNo) { |
197 print(inputLines[index][i++].code); | 303 print(inputLines[index][i++].code); |
198 } | 304 } |
199 } else { | 305 } else { |
200 print('Missing lines:'); | 306 print('Missing lines:'); |
201 int i = expectedLineNo; | 307 int i = expectedLineNo; |
202 while (i <= range.from) { | 308 while (i <= range.from) { |
203 print(inputLines[index][i++].code); | 309 print(inputLines[index][i++].code); |
204 } | 310 } |
205 } | 311 } |
206 } | 312 } |
207 nextInputLine[index] = range.to; | 313 nextInputLine[index] = range.to; |
208 } | 314 } |
209 | 315 |
210 /// Creates a block containing the code lines in [range] from input number | 316 /// Creates a block containing the code lines in [range] from input number |
211 /// [index]. If [codeSource] is provided, the block will contain a | 317 /// [index]. If [codeSource] is provided, the block will contain a |
212 /// corresponding Dart code column. | 318 /// corresponding Dart code column. |
213 void handleSkew(int index, Interval range, [CodeSource codeSource]) { | 319 void handleSkew( |
320 int index, | |
321 Interval range, | |
322 [Iterable<CodeSource> mainCodeSources = const <CodeSource>[]]) { | |
323 if (range.isEmpty) return; | |
324 | |
325 Set<CodeSource> codeSources = new Set<CodeSource>(); | |
326 codeSources.addAll(mainCodeSources); | |
327 | |
214 DiffBlock block = new DiffBlock(DiffKind.UNMATCHED); | 328 DiffBlock block = new DiffBlock(DiffKind.UNMATCHED); |
215 checkLineInvariant(index, range); | 329 checkLineInvariant(index, range); |
216 block.addColumn(index, inputLines[index].sublist(range.from, range.to)); | 330 List<CodeLine> jsCodeLines = |
217 if (codeSource != null) { | 331 inputLines[index].sublist(range.from, range.to); |
218 block.addColumn(2, | 332 Map<CodeLine, List<CodeLine>> dartCodeLines = |
219 codeLinesFromCodeSource(sourceFileManager, codeSource)); | 333 dartCodeLinesFromJsCodeLines(jsCodeLines); |
334 block.addColumnBlock( | |
335 new DiffColumn('js', index), | |
336 new CodeLinesColumnBlock(jsCodeLines, dartCodeLines)); | |
337 collectCodeSources(codeSources, dartCodeLines); | |
338 | |
339 if (codeSources.isNotEmpty) { | |
340 block.addColumnBlock( | |
341 const DiffColumn('dart'), | |
342 codeLinesFromCodeSources(mainCodeSources, codeSources)); | |
220 } | 343 } |
221 blocks.add(block); | 344 blocks.add(block); |
222 } | 345 } |
223 | 346 |
224 /// Create a block containing the code lines in [ranges] from the | 347 /// Create a block containing the code lines in [ranges] from the |
225 /// corresponding JavaScript inputs. If [codeSource] is provided, the block | 348 /// corresponding JavaScript inputs. If [codeSource] is provided, the block |
226 /// will contain a corresponding Dart code column. | 349 /// will contain a corresponding Dart code column. |
227 void addLines(DiffKind kind, List<Interval> ranges, [CodeSource codeSource]) { | 350 void addLines( |
351 DiffKind kind, | |
352 List<Interval> ranges, | |
353 [Iterable<CodeSource> mainCodeSources = const <CodeSource>[]]) { | |
354 if (ranges.every((range) => range.isEmpty)) return; | |
355 | |
356 Set<CodeSource> codeSources = new Set<CodeSource>(); | |
357 codeSources.addAll(mainCodeSources); | |
358 | |
228 DiffBlock block = new DiffBlock(kind); | 359 DiffBlock block = new DiffBlock(kind); |
229 for (int i = 0; i < ranges.length; i++) { | 360 for (int i = 0; i < ranges.length; i++) { |
230 checkLineInvariant(i, ranges[i]); | 361 checkLineInvariant(i, ranges[i]); |
231 block.addColumn(i, inputLines[i].sublist(ranges[i].from, ranges[i].to)); | 362 List<CodeLine> jsCodeLines = |
363 inputLines[i].sublist(ranges[i].from, ranges[i].to); | |
364 Map<CodeLine, List<CodeLine>> dartCodeLines = | |
365 dartCodeLinesFromJsCodeLines(jsCodeLines); | |
366 block.addColumnBlock( | |
367 new DiffColumn('js', i), | |
368 new CodeLinesColumnBlock(jsCodeLines, dartCodeLines)); | |
369 collectCodeSources(codeSources, dartCodeLines); | |
232 } | 370 } |
233 if (codeSource != null) { | 371 if (codeSources.isNotEmpty) { |
234 block.addColumn(2, | 372 block.addColumnBlock(const DiffColumn('dart'), |
235 codeLinesFromCodeSource(sourceFileManager, codeSource)); | 373 codeLinesFromCodeSources(mainCodeSources, codeSources)); |
236 } | 374 } |
237 blocks.add(block); | 375 blocks.add(block); |
238 } | 376 } |
239 | 377 |
240 /// Merge the code lines in [range1] and [range2] of the corresponding input. | 378 /// Merge the code lines in [range1] and [range2] of the corresponding input. |
241 void addRaw(Interval range1, Interval range2) { | 379 void addRaw(Interval range1, Interval range2) { |
380 if (range1.isEmpty && range2.isEmpty) return; | |
381 | |
242 match(a, b) => a.code == b.code; | 382 match(a, b) => a.code == b.code; |
243 | 383 |
244 List<Interval> currentMatchedIntervals; | 384 List<Interval> currentMatchedIntervals; |
245 List<Interval> currentUnmatchedIntervals; | 385 List<Interval> currentUnmatchedIntervals; |
246 | 386 |
247 void flushMatching() { | 387 void flushMatching() { |
248 if (currentMatchedIntervals != null) { | 388 if (currentMatchedIntervals != null) { |
249 addLines(DiffKind.IDENTICAL, currentMatchedIntervals); | 389 addLines(DiffKind.IDENTICAL, currentMatchedIntervals); |
250 } | 390 } |
251 currentMatchedIntervals = null; | 391 currentMatchedIntervals = null; |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
406 structures[1].children, | 546 structures[1].children, |
407 match: (a, b) => a.name == b.name, | 547 match: (a, b) => a.name == b.name, |
408 handleSkew: addBlock, | 548 handleSkew: addBlock, |
409 handleMatched: addMatchingBlocks, | 549 handleMatched: addMatchingBlocks, |
410 handleUnmatched: addUnmatchedBlocks); | 550 handleUnmatched: addUnmatchedBlocks); |
411 | 551 |
412 addRaw(structures[0].footer, structures[1].footer); | 552 addRaw(structures[0].footer, structures[1].footer); |
413 | 553 |
414 return blocks; | 554 return blocks; |
415 } | 555 } |
416 } | 556 |
417 | 557 /// Creates html lines for code lines in [codeSource]. The [sourceFileManager] |
418 /// Creates html lines for code lines in [codeSource]. [sourceFileManager] is | 558 /// is used to read that text from the source URIs. |
419 /// used to read that text from the source URIs. | 559 List<HtmlPart> codeLinesFromCodeSource(CodeSource codeSource) { |
420 List<HtmlPart> codeLinesFromCodeSource( | 560 List<HtmlPart> lines = <HtmlPart>[]; |
421 SourceFileManager sourceFileManager, | 561 SourceFile sourceFile = sourceFileManager.getSourceFile(codeSource.uri); |
422 CodeSource codeSource) { | 562 String elementName = codeSource.name; |
423 List<HtmlPart> lines = <HtmlPart>[]; | 563 HtmlLine line = new HtmlLine(); |
424 SourceFile sourceFile = sourceFileManager.getSourceFile(codeSource.uri); | 564 line.htmlParts.add(new ConstHtmlPart('<span class="comment">')); |
425 String elementName = codeSource.name; | 565 line.htmlParts.add(new HtmlText( |
426 HtmlLine line = new HtmlLine(); | 566 '${elementName}: ${sourceFile.filename}')); |
427 line.htmlParts.add(new ConstHtmlPart('<span class="comment">')); | 567 line.htmlParts.add(new ConstHtmlPart('</span>')); |
428 line.htmlParts.add(new HtmlText( | 568 lines.add(line); |
429 '${elementName}: ${sourceFile.filename}')); | 569 if (codeSource.begin != null) { |
430 line.htmlParts.add(new ConstHtmlPart('</span>')); | 570 int startLine = sourceFile.getLine(codeSource.begin); |
431 lines.add(line); | 571 int endLine = sourceFile.getLine(codeSource.end) + 1; |
432 if (codeSource.begin != null) { | 572 for (CodeLine codeLine in convertAnnotatedCodeToCodeLines( |
433 int startLine = sourceFile.getLine(codeSource.begin); | 573 sourceFile.slowText(), |
434 int endLine = sourceFile.getLine(codeSource.end); | 574 const <Annotation>[], |
435 for (int lineNo = startLine; lineNo <= endLine; lineNo++) { | 575 startLine: startLine, |
436 String text = sourceFile.getLineText(lineNo); | 576 endLine: endLine)) { |
437 CodeLine codeLine = new CodeLine(lineNo, sourceFile.getOffset(lineNo, 0)); | 577 codeLine.lineAnnotation = codeSource; |
438 codeLine.codeBuffer.write(text); | 578 lines.add(codeLine); |
439 codeLine.htmlParts.add(new HtmlText(text)); | 579 } |
440 lines.add(codeLine); | 580 } |
441 } | 581 return lines; |
442 } | 582 } |
443 return lines; | 583 |
444 } | 584 /// Creates a map from JavaScript [CodeLine]s in [jsCodeLines] to the Dart |
585 /// [CodeLine]s references in the source information. | |
586 Map<CodeLine, List<CodeLine>> dartCodeLinesFromJsCodeLines( | |
587 List<CodeLine> jsCodeLines) { | |
588 Map<CodeLine, Interval> codeLineInterval = <CodeLine, Interval>{}; | |
589 Map<CodeLine, List<CodeLine>> jsToDartMap = <CodeLine, List<CodeLine>>{}; | |
590 List<Annotation> annotations = <Annotation>[]; | |
591 Uri currentUri; | |
592 Interval interval; | |
593 | |
594 Map<Uri, Set<CodeSource>> codeSourceMap = <Uri, Set<CodeSource>>{}; | |
595 | |
596 for (CodeLine jsCodeLine in jsCodeLines) { | |
597 for (Annotation annotation in jsCodeLine.annotations) { | |
598 CodeLineAnnotation codeLineAnnotation = annotation.data; | |
599 for (CodeSource codeSource in codeLineAnnotation.codeSources) { | |
600 codeSourceMap.putIfAbsent(codeSource.uri, | |
601 () => new Set<CodeSource>()).add(codeSource); | |
602 } | |
603 } | |
604 } | |
605 | |
606 void flush() { | |
607 if (currentUri == null) return; | |
608 | |
609 Set<CodeSource> codeSources = codeSourceMap[currentUri]; | |
610 SourceFile sourceFile = sourceFileManager.getSourceFile(currentUri); | |
611 List<CodeLine> annotatedDartCodeLines = | |
612 convertAnnotatedCodeToCodeLines( | |
613 sourceFile.slowText(), | |
614 annotations, | |
615 startLine: interval.from, | |
616 endLine: interval.to, | |
617 uri: currentUri); | |
618 if (codeSources != null) { | |
619 CodeSource currentCodeSource; | |
620 Interval currentLineInterval; | |
621 for (CodeLine dartCodeLine in annotatedDartCodeLines) { | |
622 if (currentCodeSource == null || | |
623 !currentLineInterval.contains(dartCodeLine.lineNo)) { | |
624 currentCodeSource = null; | |
625 for (CodeSource codeSource in codeSources) { | |
626 Interval interval = new Interval( | |
627 sourceFile.getLine(codeSource.begin), | |
628 sourceFile.getLine(codeSource.end) + 1); | |
629 if (interval.contains(dartCodeLine.lineNo)) { | |
630 currentCodeSource = codeSource; | |
631 currentLineInterval = interval; | |
632 break; | |
633 } | |
634 } | |
635 } | |
636 if (currentCodeSource != null) { | |
637 dartCodeLine.lineAnnotation = currentCodeSource; | |
638 } | |
639 } | |
640 } | |
641 | |
642 int index = 0; | |
643 for (CodeLine jsCodeLine in codeLineInterval.keys) { | |
644 List<CodeLine> dartCodeLines = | |
645 jsToDartMap.putIfAbsent(jsCodeLine, () => <CodeLine>[]); | |
646 if (dartCodeLines.isEmpty && index < annotatedDartCodeLines.length) { | |
647 dartCodeLines.add(annotatedDartCodeLines[index++]); | |
648 } | |
649 } | |
650 while (index < annotatedDartCodeLines.length) { | |
651 jsToDartMap[codeLineInterval.keys.last].add( | |
652 annotatedDartCodeLines[index++]); | |
653 } | |
654 | |
655 currentUri = null; | |
656 } | |
657 | |
658 void restart(CodeLine codeLine, CodeLocation codeLocation, int line) { | |
659 flush(); | |
660 | |
661 currentUri = codeLocation.uri; | |
662 interval = new Interval(line, line + 1); | |
663 annotations = <Annotation>[]; | |
664 codeLineInterval.clear(); | |
665 codeLineInterval[codeLine] = interval; | |
666 } | |
667 | |
668 for (CodeLine jsCodeLine in jsCodeLines) { | |
669 for (Annotation annotation in jsCodeLine.annotations) { | |
670 CodeLineAnnotation codeLineAnnotation = annotation.data; | |
671 | |
672 for (CodeLocation location in codeLineAnnotation.codeLocations) { | |
673 SourceFile sourceFile = sourceFileManager.getSourceFile(location.uri); | |
674 int line = sourceFile.getLine(location.offset); | |
675 if (currentUri != location.uri) { | |
676 restart(jsCodeLine, location, line); | |
677 } else if (interval.inWindow(line, windowSize: 2)) { | |
678 interval = interval.include(line); | |
679 codeLineInterval[jsCodeLine] = interval; | |
680 } else { | |
681 restart(jsCodeLine, location, line); | |
682 } | |
683 | |
684 annotations.add(new Annotation( | |
685 codeLineAnnotation.annotationType, | |
686 location.offset, | |
687 'id=${codeLineAnnotation.annotationId}', | |
688 data: codeLineAnnotation)); | |
689 } | |
690 } | |
691 } | |
692 flush(); | |
693 return jsToDartMap; | |
694 } | |
695 } | |
696 | |
697 const DiffColumn column_js0 = const DiffColumn('js', 0); | |
698 const DiffColumn column_js1 = const DiffColumn('js', 1); | |
699 const DiffColumn column_dart = const DiffColumn('dart'); | |
700 | |
701 class ClassNames { | |
702 static String column(DiffColumn column) => 'column_${column}'; | |
703 static String identical(bool alternate) => | |
704 'identical${alternate ? '1' : '2'}'; | |
705 static String corresponding(bool alternate) => | |
706 'corresponding${alternate ? '1' : '2'}'; | |
707 | |
708 static const String buttons = 'buttons'; | |
709 static const String comment = 'comment'; | |
710 static const String header = 'header'; | |
711 static const String headerTable = 'header_table'; | |
712 static const String headerColumn = 'header_column'; | |
713 static const String legend = 'legend'; | |
714 static const String table = 'table'; | |
715 | |
716 static const String cell = 'cell'; | |
717 static const String innerCell = 'inner_cell'; | |
718 | |
719 static const String mainDart = 'main_dart'; | |
Siggi Cherem (dart-lang)
2016/03/07 18:08:36
consider: mainDart => originalDart?
(mainDart sou
Johnni Winther
2016/03/08 09:15:18
Done.
I don't have other categories in mind, but
| |
720 static const String inlinedDart = 'inlined_dart'; | |
721 | |
722 static const String line = 'line'; | |
723 static const String lineNumber = 'line_number'; | |
724 static String colored(int index) => 'colored${index}'; | |
725 | |
726 static const String withSourceInfo = 'with_source_info'; | |
727 static const String withoutSourceInfo = 'without_source_info'; | |
728 static const String additionalSourceInfo = 'additional_source_info'; | |
729 static const String unusedSourceInfo = 'unused_source_info'; | |
730 | |
731 static const String sourceMapped = 'source_mapped'; | |
732 static const String sourceMapping = 'source_mapping'; | |
733 static String sourceMappingIndex(int index) => 'source_mapping${index}'; | |
734 | |
735 static const String markers = 'markers'; | |
736 static const String marker = 'marker'; | |
737 } | |
738 | |
739 class AnnotationType { | |
740 static const WITH_SOURCE_INFO = | |
741 const AnnotationType(0, ClassNames.withSourceInfo, true); | |
742 static const WITHOUT_SOURCE_INFO = | |
743 const AnnotationType(1, ClassNames.withoutSourceInfo, false); | |
744 static const ADDITIONAL_SOURCE_INFO = | |
745 const AnnotationType(2, ClassNames.additionalSourceInfo, true); | |
746 static const UNUSED_SOURCE_INFO = | |
747 const AnnotationType(3, ClassNames.unusedSourceInfo, false); | |
748 | |
749 final int index; | |
750 final String className; | |
751 final bool isSourceMapped; | |
752 | |
753 const AnnotationType(this.index, this.className, this.isSourceMapped); | |
754 | |
755 static const List<AnnotationType> values = const <AnnotationType>[ | |
756 WITH_SOURCE_INFO, | |
757 WITHOUT_SOURCE_INFO, | |
758 ADDITIONAL_SOURCE_INFO, | |
759 UNUSED_SOURCE_INFO]; | |
760 } | |
761 | |
762 class CodeLineAnnotation { | |
763 final int annotationId; | |
764 final AnnotationType annotationType; | |
765 final List<CodeLocation> codeLocations; | |
766 final List<CodeSource> codeSources; | |
767 final String stepInfo; | |
768 int sourceMappingIndex; | |
769 | |
770 CodeLineAnnotation( | |
771 {this.annotationId, | |
772 this.annotationType, | |
773 this.codeLocations, | |
774 this.codeSources, | |
775 this.stepInfo, | |
776 this.sourceMappingIndex}); | |
777 | |
778 Map toJson(JsonStrategy strategy) { | |
779 return { | |
780 'annotationId': annotationId, | |
781 'annotationType': annotationType.index, | |
782 'codeLocations': codeLocations.map((l) => l.toJson(strategy)).toList(), | |
783 'codeSources': codeSources.map((c) => c.toJson()).toList(), | |
784 'stepInfo': stepInfo, | |
785 'sourceMappingIndex': sourceMappingIndex, | |
786 }; | |
787 } | |
788 | |
789 static fromJson(Map json, JsonStrategy strategy) { | |
790 return new CodeLineAnnotation( | |
791 annotationId: json['id'], | |
792 annotationType: AnnotationType.values[json['annotationType']], | |
793 codeLocations: json['codeLocations'] | |
794 .map((j) => CodeLocation.fromJson(j, strategy)) | |
795 .toList(), | |
796 codeSources: json['codeSources'] | |
797 .map((j) => CodeSource.fromJson(j)) | |
798 .toList(), | |
799 stepInfo: json['stepInfo'], | |
800 sourceMappingIndex: json['sourceMappingIndex']); | |
801 } | |
802 } | |
OLD | NEW |