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

Side by Side Diff: tests/compiler/dart2js/sourcemaps/output_structure.dart

Issue 1678043003: Add Dart code to diff_view (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Cleanup Created 4 years, 10 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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library sourcemap.output_structure;
6
7 import 'html_parts.dart' show
8 CodeLine;
9
10 // Constants used to identify the subsection of the JavaScript output. These
11 // are specifically for the unminified full_emitter output.
12 const String HEAD = ' var dart = [';
13 const String TAIL = ' }], ';
14 const String END = ' setupProgram(dart';
15
16 final RegExp TOP_LEVEL_VALUE = new RegExp(r'^ (".+?"):');
17 final RegExp TOP_LEVEL_FUNCTION =
18 new RegExp(r'^ ([a-zA-Z0-9_$]+): \[?function');
19 final RegExp TOP_LEVEL_CLASS = new RegExp(r'^ ([a-zA-Z0-9_$]+): \[?\{');
20
21 final RegExp STATICS = new RegExp(r'^ static:');
22 final RegExp MEMBER_VALUE = new RegExp(r'^ (".+?"):');
23 final RegExp MEMBER_FUNCTION =
24 new RegExp(r'^ ([a-zA-Z0-9_$]+): \[?function');
25 final RegExp MEMBER_OBJECT = new RegExp(r'^ ([a-zA-Z0-9_$]+): \[?\{');
26
27 final RegExp STATIC_FUNCTION =
28 new RegExp(r'^ ([a-zA-Z0-9_$]+): \[?function');
29
30 /// Subrange of the JavaScript output.
31 abstract class OutputEntity {
32 Interval get interval;
33 Interval get header;
34 Interval get footer;
35
36 bool get canHaveChildren => false;
37
38 List<OutputEntity> get children;
39
40 CodeSource codeSource;
41
42 Interval getChildInterval(Interval childIndex) {
43 return new Interval(
44 children[childIndex.from].interval.from,
45 children[childIndex.to - 1].interval.to);
46
47 }
48
49 OutputEntity getChild(int index) {
50 return children[index];
51 }
52
53 accept(OutputVisitor visitor, arg);
54
55 EntityKind get kind;
56
57 Map toJson();
58
59 OutputEntity getEntityForLine(int line);
60 }
61
62 enum EntityKind {
63 STRUCTURE,
64 LIBRARY,
65 CLASS,
66 TOP_LEVEL_FUNCTION,
67 TOP_LEVEL_VALUE,
68 MEMBER_FUNCTION,
69 MEMBER_OBJECT,
70 MEMBER_VALUE,
71 STATICS,
72 STATIC_FUNCTION,
73 }
74
75 abstract class OutputVisitor<R, A> {
76 R visitStructure(OutputStructure entity, A arg);
77 R visitLibrary(LibraryBlock entity, A arg);
78 R visitClass(LibraryClass entity, A arg);
79 R visitTopLevelFunction(TopLevelFunction entity, A arg);
80 R visitTopLevelValue(TopLevelValue entity, A arg);
81 R visitMemberObject(MemberObject entity, A arg);
82 R visitMemberFunction(MemberFunction entity, A arg);
83 R visitMemberValue(MemberValue entity, A arg);
84 R visitStatics(Statics entity, A arg);
85 R visitStaticFunction(StaticFunction entity, A arg);
86 }
87
88 abstract class BaseOutputVisitor<R, A> extends OutputVisitor<R, A> {
89 R visitEntity(OutputEntity entity, A arg) => null;
90
91 R visitStructure(OutputStructure entity, A arg) => visitEntity(entity, arg);
92 R visitLibrary(LibraryBlock entity, A arg) => visitEntity(entity, arg);
93 R visitClass(LibraryClass entity, A arg) => visitEntity(entity, arg);
94
95 R visitMember(BasicEntity entity, A arg) => visitEntity(entity, arg);
96
97 R visitTopLevelMember(BasicEntity entity, A arg) => visitMember(entity, arg);
98
99 R visitTopLevelFunction(TopLevelFunction entity, A arg) {
100 return visitTopLevelMember(entity, arg);
101 }
102
103 R visitTopLevelValue(TopLevelValue entity, A arg) {
104 return visitTopLevelMember(entity, arg);
105 }
106
107 R visitClassMember(BasicEntity entity, A arg) => visitMember(entity, arg);
108
109 R visitMemberObject(MemberObject entity, A arg) {
110 return visitClassMember(entity, arg);
111 }
112
113 R visitMemberFunction(MemberFunction entity, A arg) {
114 return visitClassMember(entity, arg);
115 }
116
117 R visitMemberValue(MemberValue entity, A arg) {
118 return visitClassMember(entity, arg);
119 }
120
121 R visitStatics(Statics entity, A arg) {
122 return visitClassMember(entity, arg);
123 }
124
125 R visitStaticFunction(StaticFunction entity, A arg) {
126 return visitClassMember(entity, arg);
127 }
128 }
129
130 /// The whole JavaScript output.
131 class OutputStructure extends OutputEntity {
132 final List<CodeLine> lines;
133 final int headerEnd;
134 final int footerStart;
135 final List<LibraryBlock> children;
136
137 OutputStructure(
138 this.lines,
139 this.headerEnd,
140 this.footerStart,
141 this.children);
142
143 @override
144 EntityKind get kind => EntityKind.STRUCTURE;
145
146 Interval get interval => new Interval(0, lines.length);
147
148 Interval get header => new Interval(0, headerEnd);
149
150 Interval get footer => new Interval(footerStart, lines.length);
151
152 bool get canHaveChildren => true;
153
154 OutputEntity getEntityForLine(int line) {
155 if (line < headerEnd || line >= footerStart) {
156 return this;
157 }
158 for (LibraryBlock library in children) {
159 if (library.interval.contains(line)) {
160 return library.getEntityForLine(line);
161 }
162 }
163 return null;
164 }
165
166 /// Compute the structure of the JavaScript [lines].
167 static OutputStructure parse(List<CodeLine> lines) {
168
169 int findHeaderStart(List<CodeLine> lines) {
170 int index = 0;
171 for (CodeLine line in lines) {
172 if (line.code.startsWith(HEAD)) {
173 return index;
174 }
175 index++;
176 }
177 return lines.length;
178 }
179
180 int findHeaderEnd(int start, List<CodeLine> lines) {
181 int index = start;
182 for (CodeLine line in lines.skip(start)) {
183 if (line.code.startsWith(END)) {
184 return index;
185 }
186 index++;
187 }
188 return lines.length;
189 }
190
191 String readHeader(CodeLine line) {
192 String code = line.code;
193 String ssaLineHeader;
194 if (code.startsWith(HEAD)) {
195 return code.substring(HEAD.length);
196 } else if (code.startsWith(TAIL)) {
197 return code.substring(TAIL.length);
198 }
199 return null;
200 }
201
202 List<LibraryBlock> computeHeaderMap(
203 List<CodeLine> lines, int start, int end) {
204 List<LibraryBlock> libraryBlocks = <LibraryBlock>[];
205 LibraryBlock current;
206 for (int index = start; index < end; index++) {
207 String header = readHeader(lines[index]);
208 if (header != null) {
209 if (current != null) {
210 current.to = index;
211 }
212 libraryBlocks.add(current = new LibraryBlock(header, index));
213 }
214 }
215 if (current != null) {
216 current.to = end;
217 }
218 return libraryBlocks;
219 }
220
221 int headerEnd = findHeaderStart(lines);
222 int footerStart = findHeaderEnd(headerEnd, lines);
223 List<LibraryBlock> libraryBlocks =
224 computeHeaderMap(lines, headerEnd, footerStart);
225 for (LibraryBlock block in libraryBlocks) {
226 block.preprocess(lines);
227 }
228
229 return new OutputStructure(
230 lines, headerEnd, footerStart, libraryBlocks);
231 }
232
233 accept(OutputVisitor visitor, arg) => visitor.visitStructure(this, arg);
234
235 @override
236 Map toJson() {
237 return {
238 'lines': lines.map((line) => line.toJson()).toList(),
239 'headerEnd': headerEnd,
240 'footerStart': footerStart,
241 'children': children.map((child) => child.toJson()).toList(),
242 };
243 }
244
245 static OutputStructure fromJson(Map json) {
246 List<CodeLine> lines = json['lines'].map(CodeLine.fromJson).toList();
247 int headerEnd = json['headerEnd'];
248 int footerStart = json['footerStart'];
249 List<LibraryBlock> children =
250 json['children'].map(AbstractEntity.fromJson).toList();
251 return new OutputStructure(lines, headerEnd, footerStart, children);
252 }
253 }
254
255 abstract class AbstractEntity extends OutputEntity {
256 final String name;
257 final int from;
258 int to;
259
260 AbstractEntity(this.name, this.from);
261
262 Interval get interval => new Interval(from, to);
263
264 @override
265 Map toJson() {
266 return {
267 'kind': kind.index,
268 'name': name,
269 'from': from,
270 'to': to,
271 'children': children.map((child) => child.toJson()).toList(),
272 'codeSource': codeSource != null ? codeSource.toJson() : null,
273 };
274 }
275
276 static AbstractEntity fromJson(Map json) {
277 EntityKind kind = EntityKind.values[json['kind']];
278 String name = json['name'];
279 int from = json['from'];
280 int to = json['to'];
281 CodeSource codeSource = CodeSource.fromJson(json['codeSource']);
282
283 switch (kind) {
284 case EntityKind.STRUCTURE:
285 throw new StateError('Unexpected entity kind $kind');
286 case EntityKind.LIBRARY:
287 LibraryBlock lib = new LibraryBlock(name, from)
288 ..to = to
289 ..codeSource = codeSource;
290 json['children'].forEach((child) => lib.children.add(fromJson(child)));
291 return lib;
292 case EntityKind.CLASS:
293 LibraryClass cls = new LibraryClass(name, from)
294 ..to = to
295 ..codeSource = codeSource;
296 json['children'].forEach((child) => cls.children.add(fromJson(child)));
297 return cls;
298 case EntityKind.TOP_LEVEL_FUNCTION:
299 return new TopLevelFunction(name, from)
300 ..to = to
301 ..codeSource = codeSource;
302 case EntityKind.TOP_LEVEL_VALUE:
303 return new TopLevelValue(name, from)
304 ..to = to
305 ..codeSource = codeSource;
306 case EntityKind.MEMBER_FUNCTION:
307 return new MemberFunction(name, from)
308 ..to = to
309 ..codeSource = codeSource;
310 case EntityKind.MEMBER_OBJECT:
311 return new MemberObject(name, from)
312 ..to = to
313 ..codeSource = codeSource;
314 case EntityKind.MEMBER_VALUE:
315 return new MemberValue(name, from)
316 ..to = to
317 ..codeSource = codeSource;
318 case EntityKind.STATICS:
319 Statics statics = new Statics(from)
320 ..to = to
321 ..codeSource = codeSource;
322 json['children'].forEach(
323 (child) => statics.children.add(fromJson(child)));
324 return statics;
325 case EntityKind.STATIC_FUNCTION:
326 return new StaticFunction(name, from)
327 ..to = to
328 ..codeSource = codeSource;
329 }
330 }
331 }
332
333 /// A block defining the content of a Dart library.
334 class LibraryBlock extends AbstractEntity {
335 List<BasicEntity> children = <BasicEntity>[];
336 int get headerEnd => from + 2;
337 int get footerStart => to - 1;
338
339 LibraryBlock(String name, int from) : super(name, from);
340
341 @override
342 EntityKind get kind => EntityKind.LIBRARY;
343
344 Interval get header => new Interval(from, headerEnd);
345
346 Interval get footer => new Interval(footerStart, to);
347
348 bool get canHaveChildren => true;
349
350 void preprocess(List<CodeLine> lines) {
351 int index = headerEnd;
352 BasicEntity current;
353 while (index < footerStart) {
354 String line = lines[index].code;
355 BasicEntity next;
356 Match matchFunction = TOP_LEVEL_FUNCTION.firstMatch(line);
357 if (matchFunction != null) {
358 next = new TopLevelFunction(matchFunction.group(1), index);
359 } else {
360 Match matchClass = TOP_LEVEL_CLASS.firstMatch(line);
361 if (matchClass != null) {
362 next = new LibraryClass(matchClass.group(1), index);
363 } else {
364 Match matchValue = TOP_LEVEL_VALUE.firstMatch(line);
365 if (matchValue != null) {
366 next = new TopLevelValue(matchValue.group(1), index);
367 }
368 }
369 }
370 if (next != null) {
371 if (current != null) {
372 current.to = index;
373 }
374 children.add(current = next);
375 } else if (index == headerEnd) {
376 throw 'Failed to match first library block line:\n$line';
377 }
378
379 index++;
380 }
381 if (current != null) {
382 current.to = footerStart;
383 }
384
385 for (BasicEntity entity in children) {
386 entity.preprocess(lines);
387 }
388 }
389
390 accept(OutputVisitor visitor, arg) => visitor.visitLibrary(this, arg);
391
392 OutputEntity getEntityForLine(int line) {
393 if (line < headerEnd || line >= footerStart) {
394 return this;
395 }
396 for (BasicEntity child in children) {
397 if (child.interval.contains(line)) {
398 return child.getEntityForLine(line);
399 }
400 }
401 return null;
402 }
403 }
404
405 /// A simple member of a library or class.
406 abstract class BasicEntity extends AbstractEntity {
407 BasicEntity(String name, int from) : super(name, from);
408
409 Interval get header => new Interval(from, to);
410
411 Interval get footer => new Interval(to, to);
412
413 List<OutputEntity> get children => const <OutputEntity>[];
414
415 void preprocess(List<CodeLine> lines) {}
416
417 @override
418 OutputEntity getEntityForLine(int line) {
419 if (interval.contains(line)) {
420 return this;
421 }
422 return null;
423 }
424 }
425
426 class TopLevelFunction extends BasicEntity {
427 TopLevelFunction(String name, int from) : super(name, from);
428
429 @override
430 EntityKind get kind => EntityKind.TOP_LEVEL_FUNCTION;
431
432 accept(OutputVisitor visitor, arg) {
433 return visitor.visitTopLevelFunction(this, arg);
434 }
435 }
436
437 class TopLevelValue extends BasicEntity {
438 TopLevelValue(String name, int from) : super(name, from);
439
440 @override
441 EntityKind get kind => EntityKind.TOP_LEVEL_VALUE;
442
443 accept(OutputVisitor visitor, arg) {
444 return visitor.visitTopLevelValue(this, arg);
445 }
446 }
447
448 /// A block defining a Dart class.
449 class LibraryClass extends BasicEntity {
450 List<BasicEntity> children = <BasicEntity>[];
451 int get headerEnd => from + 1;
452 int get footerStart => to - 1;
453
454 LibraryClass(String name, int from) : super(name, from);
455
456 @override
457 EntityKind get kind => EntityKind.CLASS;
458
459 Interval get header => new Interval(from, headerEnd);
460
461 Interval get footer => new Interval(footerStart, to);
462
463 bool get canHaveChildren => true;
464
465 void preprocess(List<CodeLine> lines) {
466 int index = headerEnd;
467 BasicEntity current;
468 while (index < footerStart) {
469 String line = lines[index].code;
470 BasicEntity next;
471 Match match = MEMBER_FUNCTION.firstMatch(line);
472 if (match != null) {
473 next = new MemberFunction(match.group(1), index);
474 } else {
475 match = STATICS.firstMatch(line);
476 if (match != null) {
477 next = new Statics(index);
478 } else {
479 match = MEMBER_OBJECT.firstMatch(line);
480 if (match != null) {
481 next = new MemberObject(match.group(1), index);
482 } else {
483 match = MEMBER_VALUE.firstMatch(line);
484 if (match != null) {
485 next = new MemberValue(match.group(1), index);
486 }
487 }
488 }
489 }
490 if (next != null) {
491 if (current != null) {
492 current.to = index;
493 }
494 children.add(current = next);
495 } else if (index == headerEnd) {
496 throw 'Failed to match first library block line:\n$line';
497 }
498
499 index++;
500 }
501 if (current != null) {
502 current.to = footerStart;
503 }
504
505 for (BasicEntity entity in children) {
506 entity.preprocess(lines);
507 }
508 }
509
510 accept(OutputVisitor visitor, arg) => visitor.visitClass(this, arg);
511
512 OutputEntity getEntityForLine(int line) {
513 if (line < headerEnd || line >= footerStart) {
514 return this;
515 }
516 for (BasicEntity child in children) {
517 if (child.interval.contains(line)) {
518 return child.getEntityForLine(line);
519 }
520 }
521 return null;
522 }
523 }
524
525 /// A block defining static members of a Dart class.
526 class Statics extends BasicEntity {
527 List<BasicEntity> children = <BasicEntity>[];
528 int get headerEnd => from + 1;
529 int get footerStart => to - 1;
530
531 Statics(int from) : super('statics', from);
532
533 @override
534 EntityKind get kind => EntityKind.STATICS;
535
536 Interval get header => new Interval(from, headerEnd);
537
538 Interval get footer => new Interval(footerStart, to);
539
540 bool get canHaveChildren => true;
541
542 void preprocess(List<CodeLine> lines) {
543 int index = headerEnd;
544 BasicEntity current;
545 while (index < footerStart) {
546 String line = lines[index].code;
547 BasicEntity next;
548 Match matchFunction = STATIC_FUNCTION.firstMatch(line);
549 if (matchFunction != null) {
550 next = new MemberFunction(matchFunction.group(1), index);
551 }
552 if (next != null) {
553 if (current != null) {
554 current.to = index;
555 }
556 children.add(current = next);
557 } else if (index == headerEnd) {
558 throw 'Failed to match first statics line:\n$line';
559 }
560
561 index++;
562 }
563 if (current != null) {
564 current.to = footerStart;
565 }
566 }
567
568 accept(OutputVisitor visitor, arg) => visitor.visitStatics(this, arg);
569
570 OutputEntity getEntityForLine(int line) {
571 if (line < headerEnd || line >= footerStart) {
572 return this;
573 }
574 for (BasicEntity child in children) {
575 if (child.interval.contains(line)) {
576 return child.getEntityForLine(line);
577 }
578 }
579 return null;
580 }
581 }
582
583 class MemberFunction extends BasicEntity {
584 MemberFunction(String name, int from) : super(name, from);
585
586 @override
587 EntityKind get kind => EntityKind.MEMBER_FUNCTION;
588
589 accept(OutputVisitor visitor, arg) => visitor.visitMemberFunction(this, arg);
590 }
591
592 class MemberObject extends BasicEntity {
593 MemberObject(String name, int from) : super(name, from);
594
595 @override
596 EntityKind get kind => EntityKind.MEMBER_OBJECT;
597
598 accept(OutputVisitor visitor, arg) => visitor.visitMemberObject(this, arg);
599 }
600
601 class MemberValue extends BasicEntity {
602 MemberValue(String name, int from) : super(name, from);
603
604 @override
605 EntityKind get kind => EntityKind.MEMBER_VALUE;
606
607 accept(OutputVisitor visitor, arg) => visitor.visitMemberValue(this, arg);
608 }
609
610 class StaticFunction extends BasicEntity {
611 StaticFunction(String name, int from) : super(name, from);
612
613 @override
614 EntityKind get kind => EntityKind.STATIC_FUNCTION;
615
616 accept(OutputVisitor visitor, arg) => visitor.visitStaticFunction(this, arg);
617 }
618
619 class Interval {
620 final int from;
621 final int to;
622
623 const Interval(this.from, this.to);
624
625 int get length => to - from;
626
627 bool contains(int value) {
628 return from <= value && value < to;
629 }
630 }
631
632 enum CodeKind {
633 LIBRARY,
634 CLASS,
635 MEMBER,
636 }
637
638 class CodeSource {
639 final CodeKind kind;
640 final Uri uri;
641 final String name;
642 final int begin;
643 final int end;
644
645 CodeSource(this.kind, this.uri, this.name, this.begin, this.end);
646
647 String toString() => '${toJson()}';
648
649 Map toJson() {
650 return {
651 'kind': kind.index,
652 'uri': uri.toString(),
653 'name': name,
654 'begin': begin,
655 'end': end,
656 };
657 }
658
659 static CodeSource fromJson(Map json) {
660 if (json == null) return null;
661 return new CodeSource(
662 CodeKind.values[json['kind']],
663 Uri.parse(json['uri']),
664 json['name'],
665 json['begin'],
666 json['end']);
667 }
668 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698