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

Side by Side Diff: pkg/compiler/lib/src/io/position_information.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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
« no previous file with comments | « pkg/compiler/lib/src/io/code_output.dart ('k') | pkg/compiler/lib/src/io/source_file.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 /// Source information system mapping that attempts a semantic mapping between 5 /// Source information system mapping that attempts a semantic mapping between
6 /// offsets of JavaScript code points to offsets of Dart code points. 6 /// offsets of JavaScript code points to offsets of Dart code points.
7 7
8 library dart2js.source_information.position; 8 library dart2js.source_information.position;
9 9
10 import '../common.dart'; 10 import '../common.dart';
11 import '../elements/elements.dart' show 11 import '../elements/elements.dart' show AstElement, FieldElement, LocalElement;
12 AstElement,
13 FieldElement,
14 LocalElement;
15 import '../js/js.dart' as js; 12 import '../js/js.dart' as js;
16 import '../js/js_source_mapping.dart'; 13 import '../js/js_source_mapping.dart';
17 import '../js/js_debug.dart'; 14 import '../js/js_debug.dart';
18 import '../tree/tree.dart' show 15 import '../tree/tree.dart' show FunctionExpression, Node, Send;
19 FunctionExpression,
20 Node,
21 Send;
22 16
23 import 'code_output.dart' show 17 import 'code_output.dart' show CodeBuffer;
24 CodeBuffer;
25 import 'source_file.dart'; 18 import 'source_file.dart';
26 import 'source_information.dart'; 19 import 'source_information.dart';
27 20
28 /// [SourceInformation] that consists of an offset position into the source 21 /// [SourceInformation] that consists of an offset position into the source
29 /// code. 22 /// code.
30 class PositionSourceInformation extends SourceInformation { 23 class PositionSourceInformation extends SourceInformation {
31 @override 24 @override
32 final SourceLocation startPosition; 25 final SourceLocation startPosition;
33 26
34 @override 27 @override
35 final SourceLocation closingPosition; 28 final SourceLocation closingPosition;
36 29
37 PositionSourceInformation(this.startPosition, 30 PositionSourceInformation(this.startPosition, [this.closingPosition]);
38 [this.closingPosition]);
39 31
40 @override 32 @override
41 List<SourceLocation> get sourceLocations { 33 List<SourceLocation> get sourceLocations {
42 List<SourceLocation> list = <SourceLocation>[]; 34 List<SourceLocation> list = <SourceLocation>[];
43 if (startPosition != null) { 35 if (startPosition != null) {
44 list.add(startPosition); 36 list.add(startPosition);
45 } 37 }
46 if (closingPosition != null) { 38 if (closingPosition != null) {
47 list.add(closingPosition); 39 list.add(closingPosition);
48 } 40 }
49 return list; 41 return list;
50 } 42 }
51 43
52 @override 44 @override
53 SourceSpan get sourceSpan { 45 SourceSpan get sourceSpan {
54 SourceLocation location = 46 SourceLocation location =
55 startPosition != null ? startPosition : closingPosition; 47 startPosition != null ? startPosition : closingPosition;
56 Uri uri = location.sourceUri; 48 Uri uri = location.sourceUri;
57 int offset = location.offset; 49 int offset = location.offset;
58 return new SourceSpan(uri, offset, offset); 50 return new SourceSpan(uri, offset, offset);
59 } 51 }
60 52
61 int get hashCode { 53 int get hashCode {
62 return 0x7FFFFFFF & 54 return 0x7FFFFFFF &
63 (startPosition.hashCode * 17 + closingPosition.hashCode * 19); 55 (startPosition.hashCode * 17 + closingPosition.hashCode * 19);
64 } 56 }
65 57
66 bool operator ==(other) { 58 bool operator ==(other) {
67 if (identical(this, other)) return true; 59 if (identical(this, other)) return true;
68 if (other is! PositionSourceInformation) return false; 60 if (other is! PositionSourceInformation) return false;
69 return startPosition == other.startPosition && 61 return startPosition == other.startPosition &&
70 closingPosition == other.closingPosition; 62 closingPosition == other.closingPosition;
71 } 63 }
72 64
73 /// Create a textual representation of the source information using [uriText] 65 /// Create a textual representation of the source information using [uriText]
74 /// as the Uri representation. 66 /// as the Uri representation.
75 String _computeText(String uriText) { 67 String _computeText(String uriText) {
76 StringBuffer sb = new StringBuffer(); 68 StringBuffer sb = new StringBuffer();
77 sb.write('$uriText:'); 69 sb.write('$uriText:');
78 // Use 1-based line/column info to match usual dart tool output. 70 // Use 1-based line/column info to match usual dart tool output.
79 if (startPosition != null) { 71 if (startPosition != null) {
80 sb.write('[${startPosition.line + 1},' 72 sb.write('[${startPosition.line + 1},'
81 '${startPosition.column + 1}]'); 73 '${startPosition.column + 1}]');
82 } 74 }
83 if (closingPosition != null) { 75 if (closingPosition != null) {
84 sb.write('-[${closingPosition.line + 1},' 76 sb.write('-[${closingPosition.line + 1},'
85 '${closingPosition.column + 1}]'); 77 '${closingPosition.column + 1}]');
86 } 78 }
87 return sb.toString(); 79 return sb.toString();
88 } 80 }
89 81
90 String get shortText { 82 String get shortText {
91 if (startPosition != null) { 83 if (startPosition != null) {
92 return _computeText(startPosition.sourceUri.pathSegments.last); 84 return _computeText(startPosition.sourceUri.pathSegments.last);
93 } else { 85 } else {
94 return _computeText(closingPosition.sourceUri.pathSegments.last); 86 return _computeText(closingPosition.sourceUri.pathSegments.last);
95 } 87 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 final String name; 143 final String name;
152 final AstElement element; 144 final AstElement element;
153 145
154 PositionSourceInformationBuilder(AstElement element) 146 PositionSourceInformationBuilder(AstElement element)
155 : this.element = element, 147 : this.element = element,
156 sourceFile = element.implementation.compilationUnit.script.file, 148 sourceFile = element.implementation.compilationUnit.script.file,
157 name = computeElementNameForSourceMaps(element); 149 name = computeElementNameForSourceMaps(element);
158 150
159 SourceInformation buildDeclaration(AstElement element) { 151 SourceInformation buildDeclaration(AstElement element) {
160 if (element.isSynthesized) { 152 if (element.isSynthesized) {
161 return new PositionSourceInformation( 153 return new PositionSourceInformation(new OffsetSourceLocation(
162 new OffsetSourceLocation( 154 sourceFile, element.position.charOffset, name));
163 sourceFile, element.position.charOffset, name));
164 } else { 155 } else {
165 return new PositionSourceInformation( 156 return new PositionSourceInformation(
166 new OffsetSourceLocation(sourceFile, 157 new OffsetSourceLocation(sourceFile,
167 element.resolvedAst.node.getBeginToken().charOffset, name), 158 element.resolvedAst.node.getBeginToken().charOffset, name),
168 new OffsetSourceLocation(sourceFile, 159 new OffsetSourceLocation(sourceFile,
169 element.resolvedAst.node.getEndToken().charOffset, name)); 160 element.resolvedAst.node.getEndToken().charOffset, name));
170 } 161 }
171 } 162 }
172 163
173 /// Builds a source information object pointing the start position of [node]. 164 /// Builds a source information object pointing the start position of [node].
174 SourceInformation buildBegin(Node node) { 165 SourceInformation buildBegin(Node node) {
175 return new PositionSourceInformation(new OffsetSourceLocation( 166 return new PositionSourceInformation(new OffsetSourceLocation(
176 sourceFile, node.getBeginToken().charOffset, name)); 167 sourceFile, node.getBeginToken().charOffset, name));
177 } 168 }
178 169
179 @override 170 @override
180 SourceInformation buildGeneric(Node node) => buildBegin(node); 171 SourceInformation buildGeneric(Node node) => buildBegin(node);
181 172
182 @override 173 @override
183 SourceInformation buildCreate(Node node) => buildBegin(node); 174 SourceInformation buildCreate(Node node) => buildBegin(node);
184 175
185 @override 176 @override
186 SourceInformation buildReturn(Node node) => buildBegin(node); 177 SourceInformation buildReturn(Node node) => buildBegin(node);
187 178
188 @override 179 @override
189 SourceInformation buildImplicitReturn(AstElement element) { 180 SourceInformation buildImplicitReturn(AstElement element) {
190 if (element.isSynthesized) { 181 if (element.isSynthesized) {
191 return new PositionSourceInformation( 182 return new PositionSourceInformation(new OffsetSourceLocation(
192 new OffsetSourceLocation( 183 sourceFile, element.position.charOffset, name));
193 sourceFile, element.position.charOffset, name));
194 } else { 184 } else {
195 return new PositionSourceInformation( 185 return new PositionSourceInformation(new OffsetSourceLocation(
196 new OffsetSourceLocation(sourceFile, 186 sourceFile, element.resolvedAst.node.getEndToken().charOffset, name));
197 element.resolvedAst.node.getEndToken().charOffset, name));
198 } 187 }
199 } 188 }
200
201 189
202 @override 190 @override
203 SourceInformation buildLoop(Node node) => buildBegin(node); 191 SourceInformation buildLoop(Node node) => buildBegin(node);
204 192
205 @override 193 @override
206 SourceInformation buildGet(Node node) { 194 SourceInformation buildGet(Node node) {
207 Node left = node; 195 Node left = node;
208 Node right = node; 196 Node right = node;
209 Send send = node.asSend(); 197 Send send = node.asSend();
210 if (send != null) { 198 if (send != null) {
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 return startPosition; 314 return startPosition;
327 case CodePositionKind.END: 315 case CodePositionKind.END:
328 return endPosition; 316 return endPosition;
329 case CodePositionKind.CLOSING: 317 case CodePositionKind.CLOSING:
330 return closingPosition; 318 return closingPosition;
331 } 319 }
332 } 320 }
333 321
334 String toString() { 322 String toString() {
335 return 'CodePosition(start=$startPosition,' 323 return 'CodePosition(start=$startPosition,'
336 'end=$endPosition,closing=$closingPosition)'; 324 'end=$endPosition,closing=$closingPosition)';
337 } 325 }
338 } 326 }
339 327
340 /// A map from a [js.Node] to its [CodePosition]. 328 /// A map from a [js.Node] to its [CodePosition].
341 abstract class CodePositionMap { 329 abstract class CodePositionMap {
342 CodePosition operator [](js.Node node); 330 CodePosition operator [](js.Node node);
343 } 331 }
344 332
345 /// Registry for mapping [js.Node]s to their [CodePosition]. 333 /// Registry for mapping [js.Node]s to their [CodePosition].
346 class CodePositionRecorder implements CodePositionMap { 334 class CodePositionRecorder implements CodePositionMap {
347 Map<js.Node, CodePosition> _codePositionMap = 335 Map<js.Node, CodePosition> _codePositionMap =
348 new Map<js.Node, CodePosition>.identity(); 336 new Map<js.Node, CodePosition>.identity();
349 337
350 void registerPositions(js.Node node, 338 void registerPositions(
351 int startPosition, 339 js.Node node, int startPosition, int endPosition, int closingPosition) {
352 int endPosition, 340 registerCodePosition(
353 int closingPosition) { 341 node, new CodePosition(startPosition, endPosition, closingPosition));
354 registerCodePosition(node,
355 new CodePosition(startPosition, endPosition, closingPosition));
356 } 342 }
357 343
358 void registerCodePosition(js.Node node, CodePosition codePosition) { 344 void registerCodePosition(js.Node node, CodePosition codePosition) {
359 _codePositionMap[node] = codePosition; 345 _codePositionMap[node] = codePosition;
360 } 346 }
361 347
362 CodePosition operator [](js.Node node) => _codePositionMap[node]; 348 CodePosition operator [](js.Node node) => _codePositionMap[node];
363 } 349 }
364 350
365 /// Enum values for the part of a Dart node used for the source location offset. 351 /// Enum values for the part of a Dart node used for the source location offset.
(...skipping 23 matching lines...) Expand all
389 /// For function expressions the inner position is the closing brace or the 375 /// For function expressions the inner position is the closing brace or the
390 /// arrow: 376 /// arrow:
391 /// 377 ///
392 /// foo() => () {} 378 /// foo() => () {}
393 /// ^ // the inner position of the 'foo' function 379 /// ^ // the inner position of the 'foo' function
394 /// ^ // the inner position of the closure 380 /// ^ // the inner position of the closure
395 /// 381 ///
396 INNER, 382 INNER,
397 } 383 }
398 384
399 SourceLocation getSourceLocation( 385 SourceLocation getSourceLocation(SourceInformation sourceInformation,
400 SourceInformation sourceInformation,
401 [SourcePositionKind sourcePositionKind = SourcePositionKind.START]) { 386 [SourcePositionKind sourcePositionKind = SourcePositionKind.START]) {
402 if (sourceInformation == null) return null; 387 if (sourceInformation == null) return null;
403 switch (sourcePositionKind) { 388 switch (sourcePositionKind) {
404 case SourcePositionKind.START: 389 case SourcePositionKind.START:
405 return sourceInformation.startPosition; 390 return sourceInformation.startPosition;
406 case SourcePositionKind.INNER: 391 case SourcePositionKind.INNER:
407 return sourceInformation.closingPosition; 392 return sourceInformation.closingPosition;
408 } 393 }
409 } 394 }
410 395
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 END, 427 END,
443 } 428 }
444 429
445 /// Processor that associates [SourceLocation]s from [SourceInformation] on 430 /// Processor that associates [SourceLocation]s from [SourceInformation] on
446 /// [js.Node]s with the target offsets in a [SourceMapper]. 431 /// [js.Node]s with the target offsets in a [SourceMapper].
447 class PositionSourceInformationProcessor implements SourceInformationProcessor { 432 class PositionSourceInformationProcessor implements SourceInformationProcessor {
448 final CodePositionRecorder codePositionRecorder = new CodePositionRecorder(); 433 final CodePositionRecorder codePositionRecorder = new CodePositionRecorder();
449 CodePositionMap codePositionMap; 434 CodePositionMap codePositionMap;
450 List<TraceListener> traceListeners; 435 List<TraceListener> traceListeners;
451 436
452 PositionSourceInformationProcessor( 437 PositionSourceInformationProcessor(SourceMapper sourceMapper,
453 SourceMapper sourceMapper,
454 [Coverage coverage]) { 438 [Coverage coverage]) {
455 codePositionMap = coverage != null 439 codePositionMap = coverage != null
456 ? new CodePositionCoverage(codePositionRecorder, coverage) 440 ? new CodePositionCoverage(codePositionRecorder, coverage)
457 : codePositionRecorder; 441 : codePositionRecorder;
458 traceListeners = [new PositionTraceListener(sourceMapper)]; 442 traceListeners = [new PositionTraceListener(sourceMapper)];
459 if (coverage != null) { 443 if (coverage != null) {
460 traceListeners.add(new CoverageListener(coverage)); 444 traceListeners.add(new CoverageListener(coverage));
461 } 445 }
462 } 446 }
463 447
464 void process(js.Node node, CodeBuffer codeBuffer) { 448 void process(js.Node node, CodeBuffer codeBuffer) {
465 new JavaScriptTracer(codePositionMap, traceListeners).apply(node); 449 new JavaScriptTracer(codePositionMap, traceListeners).apply(node);
466 } 450 }
467 451
468 @override 452 @override
469 void onPositions(js.Node node, 453 void onPositions(
470 int startPosition, 454 js.Node node, int startPosition, int endPosition, int closingPosition) {
471 int endPosition,
472 int closingPosition) {
473 codePositionRecorder.registerPositions( 455 codePositionRecorder.registerPositions(
474 node, startPosition, endPosition, closingPosition); 456 node, startPosition, endPosition, closingPosition);
475 } 457 }
476 } 458 }
477 459
478 /// Visitor that computes [SourceInformation] for a [js.Node] using information 460 /// Visitor that computes [SourceInformation] for a [js.Node] using information
479 /// attached to the node itself or alternatively from child nodes. 461 /// attached to the node itself or alternatively from child nodes.
480 class NodeSourceInformation extends js.BaseVisitor<SourceInformation> { 462 class NodeSourceInformation extends js.BaseVisitor<SourceInformation> {
481 const NodeSourceInformation(); 463 const NodeSourceInformation();
482 464
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 return visit(node.value); 499 return visit(node.value);
518 } 500 }
519 501
520 @override 502 @override
521 SourceInformation visitAssignment(js.Assignment node) { 503 SourceInformation visitAssignment(js.Assignment node) {
522 if (node.sourceInformation != null) { 504 if (node.sourceInformation != null) {
523 return node.sourceInformation; 505 return node.sourceInformation;
524 } 506 }
525 return visit(node.value); 507 return visit(node.value);
526 } 508 }
527
528 } 509 }
529 510
530 /// Mixin that add support for computing [SourceInformation] for a [js.Node]. 511 /// Mixin that add support for computing [SourceInformation] for a [js.Node].
531 class NodeToSourceInformationMixin { 512 class NodeToSourceInformationMixin {
532 SourceInformation computeSourceInformation(js.Node node) { 513 SourceInformation computeSourceInformation(js.Node node) {
533 return const NodeSourceInformation().visit(node); 514 return const NodeSourceInformation().visit(node);
534 } 515 }
535 } 516 }
536 517
537 /// [TraceListener] that register [SourceLocation]s with a [SourceMapper]. 518 /// [TraceListener] that register [SourceLocation]s with a [SourceMapper].
538 class PositionTraceListener extends TraceListener with 519 class PositionTraceListener extends TraceListener
539 NodeToSourceInformationMixin { 520 with NodeToSourceInformationMixin {
540 final SourceMapper sourceMapper; 521 final SourceMapper sourceMapper;
541 522
542 PositionTraceListener(this.sourceMapper); 523 PositionTraceListener(this.sourceMapper);
543 524
544 @override 525 @override
545 void onStep(js.Node node, Offset offset, StepKind kind) { 526 void onStep(js.Node node, Offset offset, StepKind kind) {
546 SourceInformation sourceInformation = computeSourceInformation(node); 527 SourceInformation sourceInformation = computeSourceInformation(node);
547 if (sourceInformation == null) return; 528 if (sourceInformation == null) return;
548 int codeLocation = offset.subexpressionOffset; 529 int codeLocation = offset.subexpressionOffset;
549 if (codeLocation == null) return; 530 if (codeLocation == null) return;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 pureAccess = true; 591 pureAccess = true;
611 break; 592 break;
612 } else { 593 } else {
613 target = targetAccess.receiver; 594 target = targetAccess.receiver;
614 } 595 }
615 } 596 }
616 if (pureAccess) { 597 if (pureAccess) {
617 // a.m() this.m() a.b.c.d.m() 598 // a.m() this.m() a.b.c.d.m()
618 // ^ ^ ^ 599 // ^ ^ ^
619 return new CallPosition( 600 return new CallPosition(
620 node, 601 node, CodePositionKind.START, SourcePositionKind.START);
621 CodePositionKind.START,
622 SourcePositionKind.START);
623 } else { 602 } else {
624 // *.m() *.a.b.c.d.m() 603 // *.m() *.a.b.c.d.m()
625 // ^ ^ 604 // ^ ^
626 return new CallPosition( 605 return new CallPosition(
627 access.selector, 606 access.selector, CodePositionKind.START, SourcePositionKind.INNER);
628 CodePositionKind.START,
629 SourcePositionKind.INNER);
630 } 607 }
631 } else if (node.target is js.VariableUse) { 608 } else if (node.target is js.VariableUse) {
632 // m() 609 // m()
633 // ^ 610 // ^
634 return new CallPosition( 611 return new CallPosition(
635 node, 612 node, CodePositionKind.START, SourcePositionKind.START);
636 CodePositionKind.START,
637 SourcePositionKind.START);
638 } else if (node.target is js.Fun || node.target is js.New) { 613 } else if (node.target is js.Fun || node.target is js.New) {
639 // function(){}() new Function("...")() 614 // function(){}() new Function("...")()
640 // ^ ^ 615 // ^ ^
641 return new CallPosition( 616 return new CallPosition(
642 node.target, 617 node.target, CodePositionKind.END, SourcePositionKind.INNER);
643 CodePositionKind.END,
644 SourcePositionKind.INNER);
645 } else if (node.target is js.Binary || node.target is js.Call) { 618 } else if (node.target is js.Binary || node.target is js.Call) {
646 // (0,a)() m()() 619 // (0,a)() m()()
647 // ^ ^ 620 // ^ ^
648 return new CallPosition( 621 return new CallPosition(
649 node.target, 622 node.target, CodePositionKind.END, SourcePositionKind.INNER);
650 CodePositionKind.END,
651 SourcePositionKind.INNER);
652 } else { 623 } else {
653 assert(invariant(NO_LOCATION_SPANNABLE, false, 624 assert(invariant(NO_LOCATION_SPANNABLE, false,
654 message: "Unexpected property access ${nodeToString(node)}:\n" 625 message: "Unexpected property access ${nodeToString(node)}:\n"
655 "${DebugPrinter.prettyPrint(node)}")); 626 "${DebugPrinter.prettyPrint(node)}"));
656 // Don't know.... 627 // Don't know....
657 return new CallPosition( 628 return new CallPosition(
658 node, 629 node, CodePositionKind.START, SourcePositionKind.START);
659 CodePositionKind.START,
660 SourcePositionKind.START);
661 } 630 }
662 } 631 }
663 } 632 }
664 633
665 class Offset { 634 class Offset {
666 /// The offset of the enclosing statement relative to the beginning of the 635 /// The offset of the enclosing statement relative to the beginning of the
667 /// file. 636 /// file.
668 /// 637 ///
669 /// For instance: 638 /// For instance:
670 /// 639 ///
(...skipping 30 matching lines...) Expand all
701 /// foo().bar(baz()); 670 /// foo().bar(baz());
702 /// ^ // the left-to-right offset of the `foo()` call 671 /// ^ // the left-to-right offset of the `foo()` call
703 /// ^ // the left-to-right offset of the `*.bar()` call 672 /// ^ // the left-to-right offset of the `*.bar()` call
704 /// ^ // the left-to-right offset of the `baz()` call 673 /// ^ // the left-to-right offset of the `baz()` call
705 /// 674 ///
706 /// Here, `baz()` is executed before `foo()` so we need to use 'f' as its best 675 /// Here, `baz()` is executed before `foo()` so we need to use 'f' as its best
707 /// position under the restriction. 676 /// position under the restriction.
708 /// 677 ///
709 final int leftToRightOffset; 678 final int leftToRightOffset;
710 679
711 Offset(this.statementOffset, this.leftToRightOffset, this.subexpressionOffset) ; 680 Offset(
681 this.statementOffset, this.leftToRightOffset, this.subexpressionOffset);
712 682
713 String toString() { 683 String toString() {
714 return 'Offset[statementOffset=$statementOffset,' 684 return 'Offset[statementOffset=$statementOffset,'
715 'leftToRightOffset=$leftToRightOffset,' 685 'leftToRightOffset=$leftToRightOffset,'
716 'subexpressionOffset=$subexpressionOffset]'; 686 'subexpressionOffset=$subexpressionOffset]';
717 } 687 }
718 } 688 }
719 689
720 enum BranchKind { 690 enum BranchKind { CONDITION, LOOP, CATCH, FINALLY, CASE, }
721 CONDITION,
722 LOOP,
723 CATCH,
724 FINALLY,
725 CASE,
726 }
727 691
728 enum StepKind { 692 enum StepKind {
729 FUN_ENTRY, 693 FUN_ENTRY,
730 FUN_EXIT, 694 FUN_EXIT,
731 CALL, 695 CALL,
732 NEW, 696 NEW,
733 RETURN, 697 RETURN,
734 BREAK, 698 BREAK,
735 CONTINUE, 699 CONTINUE,
736 THROW, 700 THROW,
(...skipping 23 matching lines...) Expand all
760 /// Called when the current branch ends. 724 /// Called when the current branch ends.
761 void popBranch() {} 725 void popBranch() {}
762 726
763 /// Called when [node] defines a step of the given [kind] at the given 727 /// Called when [node] defines a step of the given [kind] at the given
764 /// [offset] when the generated JavaScript code. 728 /// [offset] when the generated JavaScript code.
765 void onStep(js.Node node, Offset offset, StepKind kind) {} 729 void onStep(js.Node node, Offset offset, StepKind kind) {}
766 } 730 }
767 731
768 /// Visitor that computes the [js.Node]s the are part of the JavaScript 732 /// Visitor that computes the [js.Node]s the are part of the JavaScript
769 /// steppable execution and thus needs source mapping locations. 733 /// steppable execution and thus needs source mapping locations.
770 class JavaScriptTracer extends js.BaseVisitor { 734 class JavaScriptTracer extends js.BaseVisitor {
771 final CodePositionMap codePositions; 735 final CodePositionMap codePositions;
772 final List<TraceListener> listeners; 736 final List<TraceListener> listeners;
773 737
774 /// The steps added by subexpressions. 738 /// The steps added by subexpressions.
775 List steps = []; 739 List steps = [];
776 740
777 /// The offset of the current statement. 741 /// The offset of the current statement.
778 int statementOffset; 742 int statementOffset;
779 743
780 /// The current offset in left-to-right progression. 744 /// The current offset in left-to-right progression.
781 int leftToRightOffset; 745 int leftToRightOffset;
782 746
783 /// The offset of the surrounding statement, used for the first subexpression. 747 /// The offset of the surrounding statement, used for the first subexpression.
784 int offsetPosition; 748 int offsetPosition;
785 749
786 bool active; 750 bool active;
787 751
788 JavaScriptTracer(this.codePositions, 752 JavaScriptTracer(this.codePositions, this.listeners, {this.active: false});
789 this.listeners,
790 {this.active: false});
791 753
792 void notifyStart(js.Node node) { 754 void notifyStart(js.Node node) {
793 listeners.forEach((listener) => listener.onStart(node)); 755 listeners.forEach((listener) => listener.onStart(node));
794 } 756 }
795 757
796 void notifyEnd(js.Node node) { 758 void notifyEnd(js.Node node) {
797 listeners.forEach((listener) => listener.onEnd(node)); 759 listeners.forEach((listener) => listener.onEnd(node));
798 } 760 }
799 761
800 void notifyPushBranch(BranchKind kind, [value]) { 762 void notifyPushBranch(BranchKind kind, [value]) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 } 807 }
846 } 808 }
847 } 809 }
848 810
849 @override 811 @override
850 visitFun(js.Fun node) { 812 visitFun(js.Fun node) {
851 bool activeBefore = active; 813 bool activeBefore = active;
852 if (!active) { 814 if (!active) {
853 active = node.sourceInformation != null; 815 active = node.sourceInformation != null;
854 } 816 }
855 leftToRightOffset = statementOffset = 817 leftToRightOffset =
856 getSyntaxOffset(node, kind: CodePositionKind.START); 818 statementOffset = getSyntaxOffset(node, kind: CodePositionKind.START);
857 Offset entryOffset = getOffsetForNode(node, statementOffset); 819 Offset entryOffset = getOffsetForNode(node, statementOffset);
858 notifyStep(node, entryOffset, StepKind.FUN_ENTRY); 820 notifyStep(node, entryOffset, StepKind.FUN_ENTRY);
859 821
860 visit(node.body); 822 visit(node.body);
861 823
862 leftToRightOffset = statementOffset = 824 leftToRightOffset =
863 getSyntaxOffset(node, kind: CodePositionKind.CLOSING); 825 statementOffset = getSyntaxOffset(node, kind: CodePositionKind.CLOSING);
864 Offset exitOffset = getOffsetForNode(node, statementOffset); 826 Offset exitOffset = getOffsetForNode(node, statementOffset);
865 notifyStep(node, exitOffset, StepKind.FUN_EXIT); 827 notifyStep(node, exitOffset, StepKind.FUN_EXIT);
866 active = activeBefore; 828 active = activeBefore;
867 } 829 }
868 830
869 @override 831 @override
870 visitBlock(js.Block node) { 832 visitBlock(js.Block node) {
871 for (js.Statement statement in node.statements) { 833 for (js.Statement statement in node.statements) {
872 visit(statement); 834 visit(statement);
873 } 835 }
874 } 836 }
875 837
876 int getSyntaxOffset(js.Node node, 838 int getSyntaxOffset(js.Node node,
877 {CodePositionKind kind: CodePositionKind.START}) { 839 {CodePositionKind kind: CodePositionKind.START}) {
878 CodePosition codePosition = codePositions[node]; 840 CodePosition codePosition = codePositions[node];
879 if (codePosition != null) { 841 if (codePosition != null) {
880 return codePosition.getPosition(kind); 842 return codePosition.getPosition(kind);
881 } 843 }
882 return null; 844 return null;
883 } 845 }
884 846
885 visitSubexpression(js.Node parent, 847 visitSubexpression(
886 js.Expression child, 848 js.Node parent, js.Expression child, int codeOffset, StepKind kind) {
887 int codeOffset,
888 StepKind kind) {
889 var oldSteps = steps; 849 var oldSteps = steps;
890 steps = []; 850 steps = [];
891 offsetPosition = codeOffset; 851 offsetPosition = codeOffset;
892 visit(child); 852 visit(child);
893 if (steps.isEmpty) { 853 if (steps.isEmpty) {
894 notifyStep(parent, 854 notifyStep(parent, getOffsetForNode(parent, offsetPosition), kind);
895 getOffsetForNode(parent, offsetPosition),
896 kind);
897 // The [offsetPosition] should only be used by the first subexpression. 855 // The [offsetPosition] should only be used by the first subexpression.
898 offsetPosition = null; 856 offsetPosition = null;
899 } 857 }
900 steps = oldSteps; 858 steps = oldSteps;
901 } 859 }
902 860
903 @override 861 @override
904 visitExpressionStatement(js.ExpressionStatement node) { 862 visitExpressionStatement(js.ExpressionStatement node) {
905 statementOffset = getSyntaxOffset(node); 863 statementOffset = getSyntaxOffset(node);
906 visitSubexpression( 864 visitSubexpression(
907 node, node.expression, statementOffset, 865 node, node.expression, statementOffset, StepKind.EXPRESSION_STATEMENT);
908 StepKind.EXPRESSION_STATEMENT);
909 statementOffset = null; 866 statementOffset = null;
910 leftToRightOffset = null; 867 leftToRightOffset = null;
911 } 868 }
912 869
913 @override 870 @override
914 visitEmptyStatement(js.EmptyStatement node) {} 871 visitEmptyStatement(js.EmptyStatement node) {}
915 872
916 @override 873 @override
917 visitCall(js.Call node) { 874 visitCall(js.Call node) {
918 visit(node.target); 875 visit(node.target);
919 int oldPosition = offsetPosition; 876 int oldPosition = offsetPosition;
920 offsetPosition = null; 877 offsetPosition = null;
921 visitList(node.arguments); 878 visitList(node.arguments);
922 offsetPosition = oldPosition; 879 offsetPosition = oldPosition;
923 CallPosition callPosition = 880 CallPosition callPosition = CallPosition.getSemanticPositionForCall(node);
924 CallPosition.getSemanticPositionForCall(node);
925 js.Node positionNode = callPosition.node; 881 js.Node positionNode = callPosition.node;
926 int callOffset = getSyntaxOffset( 882 int callOffset =
927 positionNode, kind: callPosition.codePositionKind); 883 getSyntaxOffset(positionNode, kind: callPosition.codePositionKind);
928 if (offsetPosition == null) { 884 if (offsetPosition == null) {
929 // Use the call offset if this is not the first subexpression. 885 // Use the call offset if this is not the first subexpression.
930 offsetPosition = callOffset; 886 offsetPosition = callOffset;
931 } 887 }
932 Offset offset = getOffsetForNode(positionNode, offsetPosition); 888 Offset offset = getOffsetForNode(positionNode, offsetPosition);
933 notifyStep(node, offset, StepKind.CALL); 889 notifyStep(node, offset, StepKind.CALL);
934 steps.add(node); 890 steps.add(node);
935 offsetPosition = null; 891 offsetPosition = null;
936 } 892 }
937 893
938 @override 894 @override
939 visitNew(js.New node) { 895 visitNew(js.New node) {
940 visit(node.target); 896 visit(node.target);
941 visitList(node.arguments); 897 visitList(node.arguments);
942 if (offsetPosition == null) { 898 if (offsetPosition == null) {
943 // Use the syntax offset if this is not the first subexpression. 899 // Use the syntax offset if this is not the first subexpression.
944 offsetPosition = getSyntaxOffset(node); 900 offsetPosition = getSyntaxOffset(node);
945 } 901 }
946 notifyStep( 902 notifyStep(node, getOffsetForNode(node, offsetPosition), StepKind.NEW);
947 node, getOffsetForNode(node, offsetPosition), StepKind.NEW);
948 steps.add(node); 903 steps.add(node);
949 offsetPosition = null; 904 offsetPosition = null;
950 } 905 }
951 906
952 @override 907 @override
953 visitAccess(js.PropertyAccess node) { 908 visitAccess(js.PropertyAccess node) {
954 visit(node.receiver); 909 visit(node.receiver);
955 visit(node.selector); 910 visit(node.selector);
956 } 911 }
957 912
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
989 944
990 @override 945 @override
991 visitAssignment(js.Assignment node) { 946 visitAssignment(js.Assignment node) {
992 visit(node.leftHandSide); 947 visit(node.leftHandSide);
993 visit(node.value); 948 visit(node.value);
994 } 949 }
995 950
996 @override 951 @override
997 visitIf(js.If node) { 952 visitIf(js.If node) {
998 statementOffset = getSyntaxOffset(node); 953 statementOffset = getSyntaxOffset(node);
999 visitSubexpression(node, node.condition, statementOffset, 954 visitSubexpression(
1000 StepKind.IF_CONDITION); 955 node, node.condition, statementOffset, StepKind.IF_CONDITION);
1001 statementOffset = null; 956 statementOffset = null;
1002 visit(node.then, BranchKind.CONDITION, true); 957 visit(node.then, BranchKind.CONDITION, true);
1003 visit(node.otherwise, BranchKind.CONDITION, false); 958 visit(node.otherwise, BranchKind.CONDITION, false);
1004 } 959 }
1005 960
1006 @override 961 @override
1007 visitFor(js.For node) { 962 visitFor(js.For node) {
1008 int offset = statementOffset = getSyntaxOffset(node); 963 int offset = statementOffset = getSyntaxOffset(node);
1009 statementOffset = offset; 964 statementOffset = offset;
1010 leftToRightOffset = null; 965 leftToRightOffset = null;
1011 if (node.init != null) { 966 if (node.init != null) {
1012 visitSubexpression(node, node.init, getSyntaxOffset(node), 967 visitSubexpression(
1013 StepKind.FOR_INITIALIZER); 968 node, node.init, getSyntaxOffset(node), StepKind.FOR_INITIALIZER);
1014 } 969 }
1015 970
1016 if (node.condition != null) { 971 if (node.condition != null) {
1017 visitSubexpression(node, node.condition, getSyntaxOffset(node.condition), 972 visitSubexpression(node, node.condition, getSyntaxOffset(node.condition),
1018 StepKind.FOR_CONDITION); 973 StepKind.FOR_CONDITION);
1019 } 974 }
1020 975
1021 notifyPushBranch(BranchKind.LOOP); 976 notifyPushBranch(BranchKind.LOOP);
1022 visit(node.body); 977 visit(node.body);
1023 978
1024 statementOffset = offset; 979 statementOffset = offset;
1025 if (node.update != null) { 980 if (node.update != null) {
1026 visitSubexpression(node, node.update, getSyntaxOffset(node.update), 981 visitSubexpression(
1027 StepKind.FOR_UPDATE); 982 node, node.update, getSyntaxOffset(node.update), StepKind.FOR_UPDATE);
1028 } 983 }
1029 984
1030 notifyPopBranch(); 985 notifyPopBranch();
1031 } 986 }
1032 987
1033 @override 988 @override
1034 visitWhile(js.While node) { 989 visitWhile(js.While node) {
1035 statementOffset = getSyntaxOffset(node); 990 statementOffset = getSyntaxOffset(node);
1036 if (node.condition != null) { 991 if (node.condition != null) {
1037 visitSubexpression(node, node.condition, getSyntaxOffset(node), 992 visitSubexpression(node, node.condition, getSyntaxOffset(node),
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1143 visit(node.name); 1098 visit(node.name);
1144 visit(node.value); 1099 visit(node.value);
1145 } 1100 }
1146 1101
1147 @override 1102 @override
1148 visitRegExpLiteral(js.RegExpLiteral node) {} 1103 visitRegExpLiteral(js.RegExpLiteral node) {}
1149 1104
1150 @override 1105 @override
1151 visitSwitch(js.Switch node) { 1106 visitSwitch(js.Switch node) {
1152 statementOffset = getSyntaxOffset(node); 1107 statementOffset = getSyntaxOffset(node);
1153 visitSubexpression(node, node.key, getSyntaxOffset(node), 1108 visitSubexpression(
1154 StepKind.SWITCH_EXPRESSION); 1109 node, node.key, getSyntaxOffset(node), StepKind.SWITCH_EXPRESSION);
1155 statementOffset = null; 1110 statementOffset = null;
1156 leftToRightOffset = null; 1111 leftToRightOffset = null;
1157 for (int i = 0; i < node.cases.length; i++) { 1112 for (int i = 0; i < node.cases.length; i++) {
1158 visit(node.cases[i], BranchKind.CASE, i); 1113 visit(node.cases[i], BranchKind.CASE, i);
1159 } 1114 }
1160 } 1115 }
1161 1116
1162 @override 1117 @override
1163 visitCase(js.Case node) { 1118 visitCase(js.Case node) {
1164 visit(node.expression); 1119 visit(node.expression);
(...skipping 30 matching lines...) Expand all
1195 if (leftToRightOffset != null && leftToRightOffset < codeOffset) { 1150 if (leftToRightOffset != null && leftToRightOffset < codeOffset) {
1196 leftToRightOffset = codeOffset; 1151 leftToRightOffset = codeOffset;
1197 } 1152 }
1198 if (leftToRightOffset == null) { 1153 if (leftToRightOffset == null) {
1199 leftToRightOffset = statementOffset; 1154 leftToRightOffset = statementOffset;
1200 } 1155 }
1201 return new Offset(statementOffset, leftToRightOffset, codeOffset); 1156 return new Offset(statementOffset, leftToRightOffset, codeOffset);
1202 } 1157 }
1203 } 1158 }
1204 1159
1205
1206 class Coverage { 1160 class Coverage {
1207 Set<js.Node> _nodesWithInfo = new Set<js.Node>(); 1161 Set<js.Node> _nodesWithInfo = new Set<js.Node>();
1208 int _nodesWithInfoCount = 0; 1162 int _nodesWithInfoCount = 0;
1209 Set<js.Node> _nodesWithoutInfo = new Set<js.Node>(); 1163 Set<js.Node> _nodesWithoutInfo = new Set<js.Node>();
1210 int _nodesWithoutInfoCount = 0; 1164 int _nodesWithoutInfoCount = 0;
1211 Map<Type, int> _nodesWithoutInfoCountByType = <Type, int>{}; 1165 Map<Type, int> _nodesWithoutInfoCountByType = <Type, int>{};
1212 Set<js.Node> _nodesWithoutOffset = new Set<js.Node>(); 1166 Set<js.Node> _nodesWithoutOffset = new Set<js.Node>();
1213 int _nodesWithoutOffsetCount = 0; 1167 int _nodesWithoutOffsetCount = 0;
1214 1168
1215 void registerNodeWithInfo(js.Node node) { 1169 void registerNodeWithInfo(js.Node node) {
(...skipping 14 matching lines...) Expand all
1230 _nodesWithoutOffsetCount += _nodesWithoutOffset.length; 1184 _nodesWithoutOffsetCount += _nodesWithoutOffset.length;
1231 _nodesWithoutOffset.clear(); 1185 _nodesWithoutOffset.clear();
1232 1186
1233 _nodesWithoutInfoCount += _nodesWithoutInfo.length; 1187 _nodesWithoutInfoCount += _nodesWithoutInfo.length;
1234 for (js.Node node in _nodesWithoutInfo) { 1188 for (js.Node node in _nodesWithoutInfo) {
1235 if (node is js.ExpressionStatement) { 1189 if (node is js.ExpressionStatement) {
1236 _nodesWithoutInfoCountByType.putIfAbsent( 1190 _nodesWithoutInfoCountByType.putIfAbsent(
1237 node.expression.runtimeType, () => 0); 1191 node.expression.runtimeType, () => 0);
1238 _nodesWithoutInfoCountByType[node.expression.runtimeType]++; 1192 _nodesWithoutInfoCountByType[node.expression.runtimeType]++;
1239 } else { 1193 } else {
1240 _nodesWithoutInfoCountByType.putIfAbsent( 1194 _nodesWithoutInfoCountByType.putIfAbsent(node.runtimeType, () => 0);
1241 node.runtimeType, () => 0);
1242 _nodesWithoutInfoCountByType[node.runtimeType]++; 1195 _nodesWithoutInfoCountByType[node.runtimeType]++;
1243 } 1196 }
1244 } 1197 }
1245 _nodesWithoutInfo.clear(); 1198 _nodesWithoutInfo.clear();
1246 } 1199 }
1247 1200
1248 String getCoverageReport() { 1201 String getCoverageReport() {
1249 collapse(); 1202 collapse();
1250 StringBuffer sb = new StringBuffer(); 1203 StringBuffer sb = new StringBuffer();
1251 int total = _nodesWithInfoCount + _nodesWithoutInfoCount; 1204 int total = _nodesWithInfoCount + _nodesWithoutInfoCount;
(...skipping 15 matching lines...) Expand all
1267 sb.write('s'); 1220 sb.write('s');
1268 } 1221 }
1269 sb.write(' without offset.'); 1222 sb.write(' without offset.');
1270 } 1223 }
1271 if (_nodesWithoutInfoCount > 0) { 1224 if (_nodesWithoutInfoCount > 0) {
1272 sb.write('\nNodes without info ('); 1225 sb.write('\nNodes without info (');
1273 sb.write(_nodesWithoutInfoCount); 1226 sb.write(_nodesWithoutInfoCount);
1274 sb.write(') by runtime type:'); 1227 sb.write(') by runtime type:');
1275 List<Type> types = _nodesWithoutInfoCountByType.keys.toList(); 1228 List<Type> types = _nodesWithoutInfoCountByType.keys.toList();
1276 types.sort((a, b) { 1229 types.sort((a, b) {
1277 return -_nodesWithoutInfoCountByType[a].compareTo( 1230 return -_nodesWithoutInfoCountByType[a]
1278 _nodesWithoutInfoCountByType[b]); 1231 .compareTo(_nodesWithoutInfoCountByType[b]);
1279 }); 1232 });
1280 1233
1281 types.forEach((Type type) { 1234 types.forEach((Type type) {
1282 int count = _nodesWithoutInfoCountByType[type]; 1235 int count = _nodesWithoutInfoCountByType[type];
1283 sb.write('\n '); 1236 sb.write('\n ');
1284 sb.write(count); 1237 sb.write(count);
1285 sb.write(' '); 1238 sb.write(' ');
1286 sb.write(type); 1239 sb.write(type);
1287 sb.write(' node'); 1240 sb.write(' node');
1288 if (count > 1) { 1241 if (count > 1) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1324 final CodePositionMap codePositions; 1277 final CodePositionMap codePositions;
1325 final Coverage coverage; 1278 final Coverage coverage;
1326 1279
1327 CodePositionCoverage(this.codePositions, this.coverage); 1280 CodePositionCoverage(this.codePositions, this.coverage);
1328 1281
1329 @override 1282 @override
1330 CodePosition operator [](js.Node node) { 1283 CodePosition operator [](js.Node node) {
1331 CodePosition codePosition = codePositions[node]; 1284 CodePosition codePosition = codePositions[node];
1332 if (codePosition == null) { 1285 if (codePosition == null) {
1333 coverage.registerNodesWithoutOffset(node); 1286 coverage.registerNodesWithoutOffset(node);
1334 } 1287 }
1335 return codePosition; 1288 return codePosition;
1336 } 1289 }
1337 } 1290 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/io/code_output.dart ('k') | pkg/compiler/lib/src/io/source_file.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698