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

Unified Diff: tests/compiler/dart2js/sourcemaps/diff.dart

Issue 1752393002: Add source mappings and inlined Dart code to diff_view. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Updated cf. comments. Created 4 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tests/compiler/dart2js/sourcemaps/diff_view.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tests/compiler/dart2js/sourcemaps/diff.dart
diff --git a/tests/compiler/dart2js/sourcemaps/diff.dart b/tests/compiler/dart2js/sourcemaps/diff.dart
index 6fb4468bd59ea3d617e9b7980d5e58cffb2ab61f..4fd31c161094ca8bd09716b25017dcb3e5bcfa67 100644
--- a/tests/compiler/dart2js/sourcemaps/diff.dart
+++ b/tests/compiler/dart2js/sourcemaps/diff.dart
@@ -9,6 +9,7 @@ import 'package:compiler/src/io/source_file.dart';
import 'html_parts.dart';
import 'output_structure.dart';
import 'sourcemap_helper.dart';
+import 'sourcemap_html_helper.dart';
enum DiffKind {
UNMATCHED,
@@ -16,26 +17,97 @@ enum DiffKind {
IDENTICAL,
}
+/// Id for an output column.
+class DiffColumn {
+ final String type;
+ final int index;
+
+ const DiffColumn(this.type, [this.index]);
+
+ int get hashCode => type.hashCode * 19 + index.hashCode * 23;
+
+ bool operator ==(other) {
+ if (identical(this, other)) return true;
+ if (other is! DiffColumn) return false;
+ return type == other.type && index == other.index;
+ }
+
+ String toString() => '$type${index != null ? index : ''}';
+}
+
+/// A block of code in an output column.
+abstract class DiffColumnBlock {
+ void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context);
+}
+
+/// A block consisting of pure HTML parts.
+class PartsColumnBlock extends DiffColumnBlock {
+ final List<HtmlPart> parts;
+
+ PartsColumnBlock(this.parts);
+
+ void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) {
+ if (parts.isNotEmpty) {
+ for (HtmlPart part in parts) {
+ part.printHtmlOn(htmlBuffer, context);
+ }
+ }
+ }
+}
+
+/// A block consisting of line-per-line JavaScript and source mapped Dart code.
+class CodeLinesColumnBlock extends DiffColumnBlock {
+ final List<CodeLine> jsCodeLines;
+ final Map<CodeLine, List<CodeLine>> jsToDartMap;
+
+ CodeLinesColumnBlock(this.jsCodeLines, this.jsToDartMap);
+
+ void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) {
+ if (jsCodeLines.isNotEmpty) {
+ htmlBuffer.write('<table style="width:100%">');
+ for (CodeLine codeLine in jsCodeLines) {
+ htmlBuffer.write('<tr><td class="${ClassNames.innerCell}">');
+ codeLine.printHtmlOn(htmlBuffer, context);
+ htmlBuffer.write(
+ '</td><td '
+ 'class="${ClassNames.innerCell} ${ClassNames.sourceMapped}">');
+ List<CodeLine> lines = jsToDartMap[codeLine];
+ if (lines != null) {
+ for (CodeLine line in lines) {
+ line.printHtmlOn(htmlBuffer,
+ context.from(includeAnnotation: (a) {
+ CodeLineAnnotation annotation = a.data;
+ return annotation.annotationType.isSourceMapped;
+ }));
+ }
+ }
+ htmlBuffer.write('</td></tr>');
+ }
+ htmlBuffer.write('</table>');
+ }
+ }
+}
+
/// A list of columns that should align in output.
class DiffBlock {
final DiffKind kind;
- List<List<HtmlPart>> columns = <List<HtmlPart>>[];
+ Map<DiffColumn, DiffColumnBlock> _columns = <DiffColumn, DiffColumnBlock>{};
DiffBlock(this.kind);
- void addColumn(int index, List<HtmlPart> lines) {
- if (index >= columns.length) {
- columns.length = index + 1;
- }
- columns[index] = lines;
+ void addColumnBlock(DiffColumn column, DiffColumnBlock block) {
+ _columns[column] = block;
}
- List<HtmlPart> getColumn(int index) {
- List<HtmlPart> lines;
- if (index < columns.length) {
- lines = columns[index];
+ Iterable<DiffColumn> get columns => _columns.keys;
+
+ void printHtmlOn(DiffColumn column,
+ StringBuffer htmlBuffer,
+ HtmlPrintContext context) {
+ DiffColumnBlock block = _columns[column];
+ if (block != null) {
+ block.printHtmlOn(htmlBuffer, context);
}
- return lines != null ? lines : const <HtmlPart>[];
}
}
@@ -176,13 +248,47 @@ class DiffCreator {
: this.structures = structures,
this.inputLines = structures.map((s) => s.lines).toList();
- CodeSource codeSourceFromEntities(Iterable<OutputEntity> entities) {
+ /// Compute [CodeSource]s defined by [entities].
+ Iterable<CodeSource> codeSourceFromEntities(Iterable<OutputEntity> entities) {
+ Set<CodeSource> sources = new Set<CodeSource>();
for (OutputEntity entity in entities) {
if (entity.codeSource != null) {
- return entity.codeSource;
+ sources.add(entity.codeSource);
+ }
+ }
+ return sources;
+ }
+
+ /// Create a block with the code from [codeSources]. The [CodeSource]s in
+ /// [mainSources] are tagged as original code sources, the rest as inlined
+ /// code sources.
+ DiffColumnBlock codeLinesFromCodeSources(
+ Iterable<CodeSource> mainSources,
+ Iterable<CodeSource> codeSources) {
+ List<HtmlPart> parts = <HtmlPart>[];
+ for (CodeSource codeSource in codeSources) {
+ //parts.addAll(codeLinesFromCodeSource(codeSource));
+ String className =
+ mainSources.contains(codeSource)
+ ? ClassNames.originalDart : ClassNames.inlinedDart;
+ parts.add(
+ new TagPart('div',
+ properties: {'class': className},
+ content: codeLinesFromCodeSource(codeSource)));
+ }
+ return new PartsColumnBlock(parts);
+ }
+
+ /// Adds all [CodeSource]s used in [dartCodeLines] to [codeSourceSet].
+ void collectCodeSources(Set<CodeSource> codeSourceSet,
+ Map<CodeLine, List<CodeLine>> dartCodeLines) {
+ for (List<CodeLine> codeLines in dartCodeLines.values) {
+ for (CodeLine dartCodeLine in codeLines) {
+ if (dartCodeLine.lineAnnotation != null) {
+ codeSourceSet.add(dartCodeLine.lineAnnotation);
+ }
}
}
- return null;
}
/// Checks that lines are added in sequence without gaps or duplicates.
@@ -210,13 +316,30 @@ class DiffCreator {
/// Creates a block containing the code lines in [range] from input number
/// [index]. If [codeSource] is provided, the block will contain a
/// corresponding Dart code column.
- void handleSkew(int index, Interval range, [CodeSource codeSource]) {
+ void handleSkew(
+ int index,
+ Interval range,
+ [Iterable<CodeSource> mainCodeSources = const <CodeSource>[]]) {
+ if (range.isEmpty) return;
+
+ Set<CodeSource> codeSources = new Set<CodeSource>();
+ codeSources.addAll(mainCodeSources);
+
DiffBlock block = new DiffBlock(DiffKind.UNMATCHED);
checkLineInvariant(index, range);
- block.addColumn(index, inputLines[index].sublist(range.from, range.to));
- if (codeSource != null) {
- block.addColumn(2,
- codeLinesFromCodeSource(sourceFileManager, codeSource));
+ List<CodeLine> jsCodeLines =
+ inputLines[index].sublist(range.from, range.to);
+ Map<CodeLine, List<CodeLine>> dartCodeLines =
+ dartCodeLinesFromJsCodeLines(jsCodeLines);
+ block.addColumnBlock(
+ new DiffColumn('js', index),
+ new CodeLinesColumnBlock(jsCodeLines, dartCodeLines));
+ collectCodeSources(codeSources, dartCodeLines);
+
+ if (codeSources.isNotEmpty) {
+ block.addColumnBlock(
+ const DiffColumn('dart'),
+ codeLinesFromCodeSources(mainCodeSources, codeSources));
}
blocks.add(block);
}
@@ -224,21 +347,38 @@ class DiffCreator {
/// Create a block containing the code lines in [ranges] from the
/// corresponding JavaScript inputs. If [codeSource] is provided, the block
/// will contain a corresponding Dart code column.
- void addLines(DiffKind kind, List<Interval> ranges, [CodeSource codeSource]) {
+ void addLines(
+ DiffKind kind,
+ List<Interval> ranges,
+ [Iterable<CodeSource> mainCodeSources = const <CodeSource>[]]) {
+ if (ranges.every((range) => range.isEmpty)) return;
+
+ Set<CodeSource> codeSources = new Set<CodeSource>();
+ codeSources.addAll(mainCodeSources);
+
DiffBlock block = new DiffBlock(kind);
for (int i = 0; i < ranges.length; i++) {
checkLineInvariant(i, ranges[i]);
- block.addColumn(i, inputLines[i].sublist(ranges[i].from, ranges[i].to));
+ List<CodeLine> jsCodeLines =
+ inputLines[i].sublist(ranges[i].from, ranges[i].to);
+ Map<CodeLine, List<CodeLine>> dartCodeLines =
+ dartCodeLinesFromJsCodeLines(jsCodeLines);
+ block.addColumnBlock(
+ new DiffColumn('js', i),
+ new CodeLinesColumnBlock(jsCodeLines, dartCodeLines));
+ collectCodeSources(codeSources, dartCodeLines);
}
- if (codeSource != null) {
- block.addColumn(2,
- codeLinesFromCodeSource(sourceFileManager, codeSource));
+ if (codeSources.isNotEmpty) {
+ block.addColumnBlock(const DiffColumn('dart'),
+ codeLinesFromCodeSources(mainCodeSources, codeSources));
}
blocks.add(block);
}
/// Merge the code lines in [range1] and [range2] of the corresponding input.
void addRaw(Interval range1, Interval range2) {
+ if (range1.isEmpty && range2.isEmpty) return;
+
match(a, b) => a.code == b.code;
List<Interval> currentMatchedIntervals;
@@ -413,32 +553,250 @@ class DiffCreator {
return blocks;
}
-}
-/// Creates html lines for code lines in [codeSource]. [sourceFileManager] is
-/// used to read that text from the source URIs.
-List<HtmlPart> codeLinesFromCodeSource(
- SourceFileManager sourceFileManager,
- CodeSource codeSource) {
- List<HtmlPart> lines = <HtmlPart>[];
- SourceFile sourceFile = sourceFileManager.getSourceFile(codeSource.uri);
- String elementName = codeSource.name;
- HtmlLine line = new HtmlLine();
- line.htmlParts.add(new ConstHtmlPart('<span class="comment">'));
- line.htmlParts.add(new HtmlText(
- '${elementName}: ${sourceFile.filename}'));
- line.htmlParts.add(new ConstHtmlPart('</span>'));
- lines.add(line);
- if (codeSource.begin != null) {
- int startLine = sourceFile.getLine(codeSource.begin);
- int endLine = sourceFile.getLine(codeSource.end);
- for (int lineNo = startLine; lineNo <= endLine; lineNo++) {
- String text = sourceFile.getLineText(lineNo);
- CodeLine codeLine = new CodeLine(lineNo, sourceFile.getOffset(lineNo, 0));
- codeLine.codeBuffer.write(text);
- codeLine.htmlParts.add(new HtmlText(text));
- lines.add(codeLine);
+ /// Creates html lines for code lines in [codeSource]. The [sourceFileManager]
+ /// is used to read that text from the source URIs.
+ List<HtmlPart> codeLinesFromCodeSource(CodeSource codeSource) {
+ List<HtmlPart> lines = <HtmlPart>[];
+ SourceFile sourceFile = sourceFileManager.getSourceFile(codeSource.uri);
+ String elementName = codeSource.name;
+ HtmlLine line = new HtmlLine();
+ line.htmlParts.add(new ConstHtmlPart('<span class="comment">'));
+ line.htmlParts.add(new HtmlText(
+ '${elementName}: ${sourceFile.filename}'));
+ line.htmlParts.add(new ConstHtmlPart('</span>'));
+ lines.add(line);
+ if (codeSource.begin != null) {
+ int startLine = sourceFile.getLine(codeSource.begin);
+ int endLine = sourceFile.getLine(codeSource.end) + 1;
+ for (CodeLine codeLine in convertAnnotatedCodeToCodeLines(
+ sourceFile.slowText(),
+ const <Annotation>[],
+ startLine: startLine,
+ endLine: endLine)) {
+ codeLine.lineAnnotation = codeSource;
+ lines.add(codeLine);
+ }
+ }
+ return lines;
+ }
+
+ /// Creates a map from JavaScript [CodeLine]s in [jsCodeLines] to the Dart
+ /// [CodeLine]s references in the source information.
+ Map<CodeLine, List<CodeLine>> dartCodeLinesFromJsCodeLines(
+ List<CodeLine> jsCodeLines) {
+ Map<CodeLine, Interval> codeLineInterval = <CodeLine, Interval>{};
+ Map<CodeLine, List<CodeLine>> jsToDartMap = <CodeLine, List<CodeLine>>{};
+ List<Annotation> annotations = <Annotation>[];
+ Uri currentUri;
+ Interval interval;
+
+ Map<Uri, Set<CodeSource>> codeSourceMap = <Uri, Set<CodeSource>>{};
+
+ for (CodeLine jsCodeLine in jsCodeLines) {
+ for (Annotation annotation in jsCodeLine.annotations) {
+ CodeLineAnnotation codeLineAnnotation = annotation.data;
+ for (CodeSource codeSource in codeLineAnnotation.codeSources) {
+ codeSourceMap.putIfAbsent(codeSource.uri,
+ () => new Set<CodeSource>()).add(codeSource);
+ }
+ }
+ }
+
+ void flush() {
+ if (currentUri == null) return;
+
+ Set<CodeSource> codeSources = codeSourceMap[currentUri];
+ SourceFile sourceFile = sourceFileManager.getSourceFile(currentUri);
+ List<CodeLine> annotatedDartCodeLines =
+ convertAnnotatedCodeToCodeLines(
+ sourceFile.slowText(),
+ annotations,
+ startLine: interval.from,
+ endLine: interval.to,
+ uri: currentUri);
+ if (codeSources != null) {
+ CodeSource currentCodeSource;
+ Interval currentLineInterval;
+ for (CodeLine dartCodeLine in annotatedDartCodeLines) {
+ if (currentCodeSource == null ||
+ !currentLineInterval.contains(dartCodeLine.lineNo)) {
+ currentCodeSource = null;
+ for (CodeSource codeSource in codeSources) {
+ Interval interval = new Interval(
+ sourceFile.getLine(codeSource.begin),
+ sourceFile.getLine(codeSource.end) + 1);
+ if (interval.contains(dartCodeLine.lineNo)) {
+ currentCodeSource = codeSource;
+ currentLineInterval = interval;
+ break;
+ }
+ }
+ }
+ if (currentCodeSource != null) {
+ dartCodeLine.lineAnnotation = currentCodeSource;
+ }
+ }
+ }
+
+ int index = 0;
+ for (CodeLine jsCodeLine in codeLineInterval.keys) {
+ List<CodeLine> dartCodeLines =
+ jsToDartMap.putIfAbsent(jsCodeLine, () => <CodeLine>[]);
+ if (dartCodeLines.isEmpty && index < annotatedDartCodeLines.length) {
+ dartCodeLines.add(annotatedDartCodeLines[index++]);
+ }
+ }
+ while (index < annotatedDartCodeLines.length) {
+ jsToDartMap[codeLineInterval.keys.last].add(
+ annotatedDartCodeLines[index++]);
+ }
+
+ currentUri = null;
}
+
+ void restart(CodeLine codeLine, CodeLocation codeLocation, int line) {
+ flush();
+
+ currentUri = codeLocation.uri;
+ interval = new Interval(line, line + 1);
+ annotations = <Annotation>[];
+ codeLineInterval.clear();
+ codeLineInterval[codeLine] = interval;
+ }
+
+ for (CodeLine jsCodeLine in jsCodeLines) {
+ for (Annotation annotation in jsCodeLine.annotations) {
+ CodeLineAnnotation codeLineAnnotation = annotation.data;
+
+ for (CodeLocation location in codeLineAnnotation.codeLocations) {
+ SourceFile sourceFile = sourceFileManager.getSourceFile(location.uri);
+ int line = sourceFile.getLine(location.offset);
+ if (currentUri != location.uri) {
+ restart(jsCodeLine, location, line);
+ } else if (interval.inWindow(line, windowSize: 2)) {
+ interval = interval.include(line);
+ codeLineInterval[jsCodeLine] = interval;
+ } else {
+ restart(jsCodeLine, location, line);
+ }
+
+ annotations.add(new Annotation(
+ codeLineAnnotation.annotationType,
+ location.offset,
+ 'id=${codeLineAnnotation.annotationId}',
+ data: codeLineAnnotation));
+ }
+ }
+ }
+ flush();
+ return jsToDartMap;
+ }
+}
+
+const DiffColumn column_js0 = const DiffColumn('js', 0);
+const DiffColumn column_js1 = const DiffColumn('js', 1);
+const DiffColumn column_dart = const DiffColumn('dart');
+
+class ClassNames {
+ static String column(DiffColumn column) => 'column_${column}';
+ static String identical(bool alternate) =>
+ 'identical${alternate ? '1' : '2'}';
+ static String corresponding(bool alternate) =>
+ 'corresponding${alternate ? '1' : '2'}';
+
+ static const String buttons = 'buttons';
+ static const String comment = 'comment';
+ static const String header = 'header';
+ static const String headerTable = 'header_table';
+ static const String headerColumn = 'header_column';
+ static const String legend = 'legend';
+ static const String table = 'table';
+
+ static const String cell = 'cell';
+ static const String innerCell = 'inner_cell';
+
+ static const String originalDart = 'main_dart';
+ static const String inlinedDart = 'inlined_dart';
+
+ static const String line = 'line';
+ static const String lineNumber = 'line_number';
+ static String colored(int index) => 'colored${index}';
+
+ static const String withSourceInfo = 'with_source_info';
+ static const String withoutSourceInfo = 'without_source_info';
+ static const String additionalSourceInfo = 'additional_source_info';
+ static const String unusedSourceInfo = 'unused_source_info';
+
+ static const String sourceMapped = 'source_mapped';
+ static const String sourceMapping = 'source_mapping';
+ static String sourceMappingIndex(int index) => 'source_mapping${index}';
+
+ static const String markers = 'markers';
+ static const String marker = 'marker';
+}
+
+class AnnotationType {
+ static const WITH_SOURCE_INFO =
+ const AnnotationType(0, ClassNames.withSourceInfo, true);
+ static const WITHOUT_SOURCE_INFO =
+ const AnnotationType(1, ClassNames.withoutSourceInfo, false);
+ static const ADDITIONAL_SOURCE_INFO =
+ const AnnotationType(2, ClassNames.additionalSourceInfo, true);
+ static const UNUSED_SOURCE_INFO =
+ const AnnotationType(3, ClassNames.unusedSourceInfo, false);
+
+ final int index;
+ final String className;
+ final bool isSourceMapped;
+
+ const AnnotationType(this.index, this.className, this.isSourceMapped);
+
+ static const List<AnnotationType> values = const <AnnotationType>[
+ WITH_SOURCE_INFO,
+ WITHOUT_SOURCE_INFO,
+ ADDITIONAL_SOURCE_INFO,
+ UNUSED_SOURCE_INFO];
+}
+
+class CodeLineAnnotation {
+ final int annotationId;
+ final AnnotationType annotationType;
+ final List<CodeLocation> codeLocations;
+ final List<CodeSource> codeSources;
+ final String stepInfo;
+ int sourceMappingIndex;
+
+ CodeLineAnnotation(
+ {this.annotationId,
+ this.annotationType,
+ this.codeLocations,
+ this.codeSources,
+ this.stepInfo,
+ this.sourceMappingIndex});
+
+ Map toJson(JsonStrategy strategy) {
+ return {
+ 'annotationId': annotationId,
+ 'annotationType': annotationType.index,
+ 'codeLocations': codeLocations.map((l) => l.toJson(strategy)).toList(),
+ 'codeSources': codeSources.map((c) => c.toJson()).toList(),
+ 'stepInfo': stepInfo,
+ 'sourceMappingIndex': sourceMappingIndex,
+ };
+ }
+
+ static fromJson(Map json, JsonStrategy strategy) {
+ return new CodeLineAnnotation(
+ annotationId: json['id'],
+ annotationType: AnnotationType.values[json['annotationType']],
+ codeLocations: json['codeLocations']
+ .map((j) => CodeLocation.fromJson(j, strategy))
+ .toList(),
+ codeSources: json['codeSources']
+ .map((j) => CodeSource.fromJson(j))
+ .toList(),
+ stepInfo: json['stepInfo'],
+ sourceMappingIndex: json['sourceMappingIndex']);
}
- return lines;
}
« no previous file with comments | « no previous file | tests/compiler/dart2js/sourcemaps/diff_view.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698