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

Side by Side Diff: tests/compiler/dart2js/sourcemaps/html_parts.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 unified diff | Download patch
OLDNEW
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.html_parts; 5 library sourcemap.html_parts;
6 6
7 import 'sourcemap_html_helper.dart'; 7 import 'sourcemap_html_helper.dart';
8 8
9 class Annotation {
10 final id;
11 final int codeOffset;
12 final String title;
13 final data;
14
15 Annotation(this.id, this.codeOffset, this.title, {this.data});
16 }
17
18 typedef bool AnnotationFilter(Annotation annotation);
19 typedef AnnotationData AnnotationDataFunction(
20 Iterable<Annotation> annotations,
21 {bool forSpan});
22 typedef LineData LineDataFunction(lineAnnotation);
23
24 bool includeAllAnnotation(Annotation annotation) => true;
25
26 class LineData {
27 final String lineClass;
28 final String lineNumberClass;
29
30 const LineData({
31 this.lineClass: 'line',
32 this.lineNumberClass: 'lineNumber'});
33 }
34
35 class AnnotationData {
36 final String tag;
37 final Map<String, String> properties;
38
39 const AnnotationData({
40 this.tag: 'a',
41 this.properties: const <String, String>{}});
42
43 int get hashCode => tag.hashCode * 13 + properties.hashCode * 19;
44
45 bool operator ==(other) {
46 if (identical(this, other)) return true;
47 if (other is! AnnotationData) return false;
48 return tag == other.tag &&
49 properties.length == other.properties.length &&
50 properties.keys.every((k) => properties[k] == other.properties[k]);
51 }
52 }
53
54 AnnotationDataFunction createAnnotationDataFunction(
55 {CssColorScheme colorScheme: const SingleColorScheme(),
56 ElementScheme elementScheme: const ElementScheme()}) {
57 return (Iterable<Annotation> annotations, {bool forSpan}) {
58 return getAnnotationDataFromSchemes(
59 annotations,
60 forSpan: forSpan,
61 colorScheme: colorScheme,
62 elementScheme: elementScheme);
63 };
64 }
65
66 LineData getDefaultLineData(data) => const LineData();
67
68 AnnotationData getAnnotationDataFromSchemes(
69 Iterable<Annotation> annotations,
70 {bool forSpan,
71 CssColorScheme colorScheme: const SingleColorScheme(),
72 ElementScheme elementScheme: const ElementScheme()}) {
73 if (colorScheme.showLocationAsSpan != forSpan) return null;
74 Map<String, String> data = <String, String>{};
75 var id;
76 if (annotations.length == 1) {
77 Annotation annotation = annotations.single;
78 if (annotation != null) {
79 id = annotation.id;
80 data['style'] = colorScheme.singleLocationToCssColor(id);
81 data['title'] = annotation.title;
82 }
83 } else {
84 id = annotations.first.id;
85 List ids = [];
86 for (Annotation annotation in annotations) {
87 ids.add(annotation.id);
88 }
89 data['style'] = colorScheme.multiLocationToCssColor(ids);
90 data['title'] = annotations.map((l) => l.title).join(',');
91 }
92 if (id != null) {
93 Set ids = annotations.map((l) => l.id).toSet();
94 data['tag'] = 'a';
95 data['name'] = elementScheme.getName(id, ids);
96 data['href'] = elementScheme.getHref(id, ids);
97 data['onclick'] = elementScheme.onClick(id, ids);
98 data['onmouseover'] = elementScheme.onMouseOver(id, ids);
99 data['onmouseout'] = elementScheme.onMouseOut(id, ids);
100 return new AnnotationData(
101 properties: data);
102 }
103 return null;
104 }
105
9 class HtmlPrintContext { 106 class HtmlPrintContext {
10 final int lineNoWidth; 107 final int lineNoWidth;
11 final bool usePre; 108 final bool usePre;
109 final AnnotationFilter includeAnnotation;
110 final AnnotationDataFunction getAnnotationData;
111 final LineDataFunction getLineData;
12 112
13 HtmlPrintContext({ 113 HtmlPrintContext({
14 this.lineNoWidth, 114 this.lineNoWidth,
15 this.usePre: true}); 115 this.usePre: true,
116 this.includeAnnotation: includeAllAnnotation,
117 this.getAnnotationData: getAnnotationDataFromSchemes,
118 this.getLineData: getDefaultLineData});
119
120 HtmlPrintContext from({
121 int lineNoWidth,
122 bool usePre,
123 AnnotationFilter includeAnnotation,
124 AnnotationDataFunction getAnnotationData,
125 LineDataFunction getLineData}) {
126 return new HtmlPrintContext(
127 lineNoWidth: lineNoWidth ?? this.lineNoWidth,
128 usePre: usePre ?? this.usePre,
129 includeAnnotation: includeAnnotation ?? this.includeAnnotation,
130 getAnnotationData: getAnnotationData ?? this.getAnnotationData,
131 getLineData: getLineData ?? this.getLineData);
132 }
16 } 133 }
17 134
18 enum HtmlPartKind { 135 enum HtmlPartKind {
19 CODE, 136 CODE,
20 LINE, 137 LINE,
21 CONST, 138 CONST,
22 NEWLINE, 139 NEWLINE,
23 TEXT, 140 TEXT,
24 ANCHOR, 141 TAG,
142 LINE_NUMBER,
25 } 143 }
26 144
27 abstract class HtmlPart { 145 abstract class HtmlPart {
28 void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {} 146 void printHtmlOn(StringBuffer buffer, HtmlPrintContext context);
29 147
30 toJson(); 148 HtmlPartKind get kind;
31 149
32 static HtmlPart fromJson(json) { 150 toJson(JsonStrategy strategy);
151
152 static HtmlPart fromJson(json, JsonStrategy strategy) {
33 if (json is String) { 153 if (json is String) {
34 return new ConstHtmlPart(json); 154 return new ConstHtmlPart(json);
35 } else { 155 } else {
36 switch (HtmlPartKind.values[json['kind']]) { 156 switch (HtmlPartKind.values[json['kind']]) {
37 case HtmlPartKind.LINE: 157 case HtmlPartKind.LINE:
38 return HtmlLine.fromJson(json); 158 return HtmlLine.fromJson(json, strategy);
39 case HtmlPartKind.CODE: 159 case HtmlPartKind.CODE:
40 return CodeLine.fromJson(json); 160 return CodeLine.fromJson(json, strategy);
41 case HtmlPartKind.CONST: 161 case HtmlPartKind.CONST:
42 return ConstHtmlPart.fromJson(json); 162 return ConstHtmlPart.fromJson(json, strategy);
43 case HtmlPartKind.NEWLINE: 163 case HtmlPartKind.NEWLINE:
44 return const NewLine(); 164 return const NewLine();
45 case HtmlPartKind.TEXT: 165 case HtmlPartKind.TEXT:
46 return HtmlText.fromJson(json); 166 return HtmlText.fromJson(json, strategy);
47 case HtmlPartKind.ANCHOR: 167 case HtmlPartKind.TAG:
48 return AnchorHtmlPart.fromJson(json); 168 return TagPart.fromJson(json, strategy);
169 case HtmlPartKind.LINE_NUMBER:
170 return LineNumber.fromJson(json, strategy);
49 } 171 }
50 } 172 }
51 } 173 }
52 } 174 }
53 175
54 class ConstHtmlPart implements HtmlPart { 176 class ConstHtmlPart implements HtmlPart {
55 final String html; 177 final String html;
56 178
57 const ConstHtmlPart(this.html); 179 const ConstHtmlPart(this.html);
58 180
181 HtmlPartKind get kind => HtmlPartKind.CONST;
182
59 @override 183 @override
60 void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) { 184 void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
61 buffer.write(html); 185 buffer.write(html);
62 } 186 }
63 187
64 toJson() { 188 toJson(JsonStrategy strategy) {
65 return {'kind': HtmlPartKind.CONST.index, 'html': html}; 189 return {'kind': kind.index, 'html': html};
66 } 190 }
67 191
68 static ConstHtmlPart fromJson(Map json) { 192 static ConstHtmlPart fromJson(Map json, JsonStrategy strategy) {
69 return new ConstHtmlPart(json['html']); 193 return new ConstHtmlPart(json['html']);
70 } 194 }
71 } 195 }
72 196
73 class NewLine implements HtmlPart { 197 class NewLine implements HtmlPart {
74 const NewLine(); 198 const NewLine();
75 199
200 HtmlPartKind get kind => HtmlPartKind.NEWLINE;
201
76 void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) { 202 void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
77 if (context.usePre) { 203 if (context.usePre) {
78 buffer.write('\n'); 204 buffer.write('\n');
79 } else { 205 } else {
80 buffer.write('<br/>'); 206 buffer.write('<br/>');
81 } 207 }
82 } 208 }
83 209
84 toJson() { 210 toJson(JsonStrategy strategy) {
85 return {'kind': HtmlPartKind.NEWLINE.index}; 211 return {'kind': kind.index};
86 } 212 }
87 } 213 }
88 214
89 class HtmlText implements HtmlPart { 215 class HtmlText implements HtmlPart {
90 final String text; 216 final String text;
91 217
92 const HtmlText(this.text); 218 const HtmlText(this.text);
93 219
220 HtmlPartKind get kind => HtmlPartKind.TEXT;
221
94 void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) { 222 void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
95 String escaped = escape(text); 223 String escaped = escape(text);
96 buffer.write(escaped); 224 buffer.write(escaped);
97 } 225 }
98 226
99 toJson() { 227 toJson(JsonStrategy strategy) {
100 return {'kind': HtmlPartKind.TEXT.index, 'text': text}; 228 return {'kind': kind.index, 'text': text};
101 } 229 }
102 230
103 static HtmlText fromJson(Map json) { 231 static HtmlText fromJson(Map json, JsonStrategy strategy) {
104 return new HtmlText(json['text']); 232 return new HtmlText(json['text']);
105 } 233 }
106 } 234 }
107 235
108 class AnchorHtmlPart implements HtmlPart { 236 class TagPart implements HtmlPart {
109 final String color; 237 final String tag;
110 final String name; 238 final Map<String, String> properties;
111 final String href; 239 final List<HtmlPart> content;
112 final String title;
113 final String onclick;
114 final String onmouseover;
115 final String onmouseout;
116 240
117 AnchorHtmlPart({ 241 TagPart(
118 this.color, 242 this.tag,
119 this.name, 243 {this.properties: const <String, String>{},
120 this.href, 244 this.content: const <HtmlPart>[]});
121 this.title, 245
122 this.onclick, 246 HtmlPartKind get kind => HtmlPartKind.TAG;
123 this.onmouseover,
124 this.onmouseout});
125 247
126 @override 248 @override
127 void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) { 249 void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
128 buffer.write('<a'); 250 buffer.write('<$tag');
129 if (href != null) { 251 properties.forEach((String key, String value) {
130 buffer.write(' href="${href}"'); 252 if (value != null) {
253 buffer.write(' $key="${value}"');
254 }
255 });
256 buffer.write('>');
257 for (HtmlPart child in content) {
258 child.printHtmlOn(buffer, context);
131 } 259 }
132 if (name != null) { 260 buffer.write('</$tag>');
133 buffer.write(' name="${name}"');
134 }
135 if (title != null) {
136 buffer.write(' title="${escape(title)}"');
137 }
138 buffer.write(' style="${color}"');
139 if (onclick != null) {
140 buffer.write(' onclick="${onclick}"');
141 }
142 if (onmouseover != null) {
143 buffer.write(' onmouseover="${onmouseover}"');
144 }
145 if (onmouseout != null) {
146 buffer.write(' onmouseout="${onmouseout}"');
147 }
148 buffer.write('>');
149 } 261 }
150 262
151 toJson() { 263 toJson(JsonStrategy strategy) {
152 return { 264 return {
153 'kind': HtmlPartKind.ANCHOR.index, 265 'kind': kind.index,
154 'color': color, 266 'tag': tag,
155 'name': name, 267 'properties': properties,
156 'href': href, 268 'content': content.map((p) => p.toJson(strategy)).toList()};
157 'title': title,
158 'onclick': onclick,
159 'onmouseover': onmouseover,
160 'onmouseout': onmouseout};
161 } 269 }
162 270
163 static AnchorHtmlPart fromJson(Map json) { 271 static TagPart fromJson(Map json, JsonStrategy strategy) {
164 return new AnchorHtmlPart( 272 return new TagPart(
165 color: json['color'], 273 json['tag'],
166 name: json['name'], 274 properties: json['properties'],
167 href: json['href'], 275 content: json['content'].map(HtmlPart.fromJson).toList());
168 title: json['title'],
169 onclick: json['onclick'],
170 onmouseover: json['onmouseover'],
171 onmouseout: json['onmouseout']);
172 } 276 }
173 } 277 }
174 278
175 class HtmlLine implements HtmlPart { 279 class HtmlLine implements HtmlPart {
176 final List<HtmlPart> htmlParts = <HtmlPart>[]; 280 final List<HtmlPart> htmlParts = <HtmlPart>[];
177 281
282 HtmlPartKind get kind => HtmlPartKind.LINE;
283
178 @override 284 @override
179 void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) { 285 void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) {
180 for (HtmlPart part in htmlParts) { 286 for (HtmlPart part in htmlParts) {
181 part.printHtmlOn(htmlBuffer, context); 287 part.printHtmlOn(htmlBuffer, context);
182 } 288 }
183 } 289 }
184 290
185 Map toJson() { 291 Map toJson(JsonStrategy strategy) {
186 return { 292 return {
187 'kind': HtmlPartKind.LINE.index, 293 'kind': kind.index,
188 'html': htmlParts.map((p) => p.toJson()).toList(), 294 'html': htmlParts.map((p) => p.toJson(strategy)).toList(),
189 }; 295 };
190 } 296 }
191 297
192 static CodeLine fromJson(Map json) { 298 static HtmlLine fromJson(Map json, JsonStrategy strategy) {
193 HtmlLine line = new HtmlLine(); 299 HtmlLine line = new HtmlLine();
194 json['html'].forEach((part) => line.htmlParts.add(HtmlPart.fromJson(part))); 300 json['html']
301 .forEach((part) => line.htmlParts
302 .add(HtmlPart.fromJson(part, strategy)));
195 return line; 303 return line;
196 } 304 }
197 } 305 }
198 306
199 class CodeLine extends HtmlLine { 307 class CodePart {
308 final List<Annotation> annotations;
309 final String subsequentCode;
310
311 CodePart(this.annotations, this.subsequentCode);
312
313 void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
314 Iterable<Annotation> included =
315 annotations.where(context.includeAnnotation);
316
317 List<HtmlPart> htmlParts = <HtmlPart>[];
318 if (included.isNotEmpty) {
319 AnnotationData annotationData =
320 context.getAnnotationData(included, forSpan: false);
321 AnnotationData annotationDataForSpan =
322 context.getAnnotationData(included, forSpan: true);
323
324 String head = subsequentCode;
325 String tail = '';
326 if (subsequentCode.length > 1) {
327 head = subsequentCode.substring(0, 1);
328 tail = subsequentCode.substring(1);
329 }
330
331 void addForSpan(AnnotationData data) {
332 htmlParts.add(new TagPart(
333 data.tag,
334 properties: data.properties,
335 content: [new HtmlText(subsequentCode)]));
336 }
337
338 if (annotationData != null &&
339 annotationDataForSpan != null) {
340 htmlParts.add(new TagPart(
341 annotationDataForSpan.tag,
342 properties: annotationDataForSpan.properties,
343 content: [
344 new TagPart(
345 annotationData.tag,
346 properties: annotationData.properties,
347 content: [new HtmlText(head)]),
348 new HtmlText(tail)]));
349 } else if (annotationDataForSpan != null) {
350 htmlParts.add(new TagPart(
351 annotationDataForSpan.tag,
352 properties: annotationDataForSpan.properties,
353 content: [new HtmlText(subsequentCode)]));
354 } else if (annotationData != null) {
355 htmlParts.add(new TagPart(
356 annotationData.tag,
357 properties: annotationData.properties,
358 content: [new HtmlText(head)]));
359 htmlParts.add(new HtmlText(tail));
360 } else {
361 htmlParts.add(new HtmlText(subsequentCode));
362 }
363 } else {
364 htmlParts.add(new HtmlText(subsequentCode));
365 }
366
367 for (HtmlPart part in htmlParts) {
368 part.printHtmlOn(buffer, context);
369 }
370 }
371
372 Map toJson(JsonStrategy strategy) {
373 return {
374 'annotations':
375 annotations.map((a) => strategy.encodeAnnotation(a)).toList(),
376 'subsequentCode': subsequentCode,
377 };
378 }
379
380 static CodePart fromJson(Map json, JsonStrategy strategy) {
381 return new CodePart(
382 json['annotations'].map((j) => strategy.decodeAnnotation(j)).toList(),
383 json['subsequentCode']);
384 }
385 }
386
387 class LineNumber extends HtmlPart {
388 final int lineNo;
389 final lineAnnotation;
390
391 LineNumber(this.lineNo, this.lineAnnotation);
392
393 HtmlPartKind get kind => HtmlPartKind.LINE_NUMBER;
394
395 @override
396 toJson(JsonStrategy strategy) {
397 return {
398 'kind': kind.index,
399 'lineNo': lineNo,
400 'lineAnnotation': strategy.encodeLineAnnotation(lineAnnotation),
401 };
402 }
403
404 static LineNumber fromJson(Map json, JsonStrategy strategy) {
405 return new LineNumber(
406 json['lineNo'],
407 strategy.decodeLineAnnotation(json['lineAnnotation']));
408 }
409
410 @override
411 void printHtmlOn(StringBuffer buffer, HtmlPrintContext context) {
412 buffer.write(lineNumber(
413 lineNo,
414 width: context.lineNoWidth,
415 useNbsp: !context.usePre,
416 className: context.getLineData(lineAnnotation).lineNumberClass));
417 }
418 }
419
420 class CodeLine extends HtmlPart {
421 final Uri uri;
200 final int lineNo; 422 final int lineNo;
201 final int offset; 423 final int offset;
202 final StringBuffer codeBuffer = new StringBuffer(); 424 final StringBuffer codeBuffer = new StringBuffer();
203 final List<HtmlPart> htmlParts = <HtmlPart>[]; 425 final List<CodePart> codeParts = <CodePart>[];
204 // TODO(johnniwinther): Make annotations serializable.
205 final List<Annotation> annotations = <Annotation>[]; 426 final List<Annotation> annotations = <Annotation>[];
427 var lineAnnotation;
206 String _code; 428 String _code;
207 429
208 CodeLine(this.lineNo, this.offset); 430 CodeLine(this.lineNo, this.offset, {this.uri});
431
432 HtmlPartKind get kind => HtmlPartKind.CODE;
209 433
210 String get code { 434 String get code {
211 if (_code == null) { 435 if (_code == null) {
212 _code = codeBuffer.toString(); 436 _code = codeBuffer.toString();
213 } 437 }
214 return _code; 438 return _code;
215 } 439 }
216 440
217 @override 441 @override
218 void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) { 442 void printHtmlOn(StringBuffer htmlBuffer, HtmlPrintContext context) {
219 htmlBuffer.write(lineNumber( 443 if (context.usePre) {
220 lineNo, width: context.lineNoWidth, useNbsp: !context.usePre)); 444 LineData lineData = context.getLineData(lineAnnotation);
221 for (HtmlPart part in htmlParts) { 445 htmlBuffer.write('<p class="${lineData.lineClass}">');
446 }
447 new LineNumber(lineNo, lineAnnotation).printHtmlOn(htmlBuffer, context);
448 for (CodePart part in codeParts) {
222 part.printHtmlOn(htmlBuffer, context); 449 part.printHtmlOn(htmlBuffer, context);
223 } 450 }
451 const NewLine().printHtmlOn(htmlBuffer, context);
452 if (context.usePre) {
453 htmlBuffer.write('</p>');
454 }
224 } 455 }
225 456
226 Map toJson() { 457 Map toJson(JsonStrategy strategy) {
227 return { 458 return {
228 'kind': HtmlPartKind.CODE.index, 459 'kind': kind.index,
229 'lineNo': lineNo, 460 'lineNo': lineNo,
230 'offset': offset, 461 'offset': offset,
231 'code': code, 462 'code': code,
232 'html': htmlParts.map((p) => p.toJson()).toList(), 463 'parts': codeParts.map((p) => p.toJson(strategy)).toList(),
464 'annotations':
465 annotations.map((a) => strategy.encodeAnnotation(a)).toList(),
466 'lineAnnotation': lineAnnotation != null
467 ? strategy.encodeLineAnnotation(lineAnnotation) : null,
233 }; 468 };
234 } 469 }
235 470
236 static CodeLine fromJson(Map json) { 471 static CodeLine fromJson(Map json, JsonStrategy strategy) {
237 CodeLine line = new CodeLine(json['lineNo'], json['offset']); 472 CodeLine line = new CodeLine(
473 json['lineNo'],
474 json['offset'],
475 uri: json['uri'] != null ? Uri.parse(json['uri']) : null);
238 line.codeBuffer.write(json['code']); 476 line.codeBuffer.write(json['code']);
239 json['html'].forEach((part) => line.htmlParts.add(HtmlPart.fromJson(part))); 477 json['parts']
478 .forEach((part) => line.codeParts
479 .add(CodePart.fromJson(part, strategy)));
480 json['annotations']
481 .forEach((a) => line.annotations
482 .add(strategy.decodeAnnotation(a)));
483 line.lineAnnotation = json['lineAnnotation'] != null
484 ? strategy.decodeLineAnnotation(json['lineAnnotation']) : null;
240 return line; 485 return line;
241 } 486 }
242 } 487 }
243 488
489 class JsonStrategy {
490 const JsonStrategy();
491
492 Map encodeAnnotation(Annotation annotation) {
493 return {
494 'id': annotation.id,
495 'codeOffset': annotation.codeOffset,
496 'title': annotation.title,
497 'data': annotation.data,
498 };
499 }
500
501 Annotation decodeAnnotation(Map json) {
502 return new Annotation(
503 json['id'],
504 json['codeOffset'],
505 json['title'],
506 data: json['data']);
507 }
508
509
510 encodeLineAnnotation(lineAnnotation) => lineAnnotation;
511
512 decodeLineAnnotation(json) => json;
513 }
OLDNEW
« no previous file with comments | « tests/compiler/dart2js/sourcemaps/diff_view.dart ('k') | tests/compiler/dart2js/sourcemaps/output_structure.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698