OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library sourcemap.output_structure; | 5 library sourcemap.output_structure; |
6 | 6 |
| 7 import 'dart:math' as Math; |
7 import 'html_parts.dart' show | 8 import 'html_parts.dart' show |
8 CodeLine; | 9 Annotation, |
| 10 CodeLine, |
| 11 JsonStrategy; |
9 | 12 |
10 // Constants used to identify the subsection of the JavaScript output. These | 13 // Constants used to identify the subsection of the JavaScript output. These |
11 // are specifically for the unminified full_emitter output. | 14 // are specifically for the unminified full_emitter output. |
12 const String HEAD = ' var dart = ['; | 15 const String HEAD = ' var dart = ['; |
13 const String TAIL = ' }], '; | 16 const String TAIL = ' }], '; |
14 const String END = ' setupProgram(dart'; | 17 const String END = ' setupProgram(dart'; |
15 | 18 |
16 final RegExp TOP_LEVEL_VALUE = new RegExp(r'^ (".+?"):'); | 19 final RegExp TOP_LEVEL_VALUE = new RegExp(r'^ (".+?"):'); |
17 final RegExp TOP_LEVEL_FUNCTION = | 20 final RegExp TOP_LEVEL_FUNCTION = |
18 new RegExp(r'^ ([a-zA-Z0-9_$]+): \[?function'); | 21 new RegExp(r'^ ([a-zA-Z0-9_$]+): \[?function'); |
(...skipping 28 matching lines...) Expand all Loading... |
47 } | 50 } |
48 | 51 |
49 OutputEntity getChild(int index) { | 52 OutputEntity getChild(int index) { |
50 return children[index]; | 53 return children[index]; |
51 } | 54 } |
52 | 55 |
53 accept(OutputVisitor visitor, arg); | 56 accept(OutputVisitor visitor, arg); |
54 | 57 |
55 EntityKind get kind; | 58 EntityKind get kind; |
56 | 59 |
57 Map toJson(); | 60 Map toJson(JsonStrategy strategy); |
58 | 61 |
59 OutputEntity getEntityForLine(int line); | 62 OutputEntity getEntityForLine(int line); |
60 } | 63 } |
61 | 64 |
62 enum EntityKind { | 65 enum EntityKind { |
63 STRUCTURE, | 66 STRUCTURE, |
64 LIBRARY, | 67 LIBRARY, |
65 CLASS, | 68 CLASS, |
66 TOP_LEVEL_FUNCTION, | 69 TOP_LEVEL_FUNCTION, |
67 TOP_LEVEL_VALUE, | 70 TOP_LEVEL_VALUE, |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 block.preprocess(lines); | 229 block.preprocess(lines); |
227 } | 230 } |
228 | 231 |
229 return new OutputStructure( | 232 return new OutputStructure( |
230 lines, headerEnd, footerStart, libraryBlocks); | 233 lines, headerEnd, footerStart, libraryBlocks); |
231 } | 234 } |
232 | 235 |
233 accept(OutputVisitor visitor, arg) => visitor.visitStructure(this, arg); | 236 accept(OutputVisitor visitor, arg) => visitor.visitStructure(this, arg); |
234 | 237 |
235 @override | 238 @override |
236 Map toJson() { | 239 Map toJson(JsonStrategy strategy) { |
237 return { | 240 return { |
238 'lines': lines.map((line) => line.toJson()).toList(), | 241 'lines': lines.map((line) => line.toJson(strategy)).toList(), |
239 'headerEnd': headerEnd, | 242 'headerEnd': headerEnd, |
240 'footerStart': footerStart, | 243 'footerStart': footerStart, |
241 'children': children.map((child) => child.toJson()).toList(), | 244 'children': children.map((child) => child.toJson(strategy)).toList(), |
242 }; | 245 }; |
243 } | 246 } |
244 | 247 |
245 static OutputStructure fromJson(Map json) { | 248 static OutputStructure fromJson(Map json, JsonStrategy strategy) { |
246 List<CodeLine> lines = json['lines'].map(CodeLine.fromJson).toList(); | 249 List<CodeLine> lines = |
| 250 json['lines'].map((l) => CodeLine.fromJson(l, strategy)).toList(); |
247 int headerEnd = json['headerEnd']; | 251 int headerEnd = json['headerEnd']; |
248 int footerStart = json['footerStart']; | 252 int footerStart = json['footerStart']; |
249 List<LibraryBlock> children = | 253 List<LibraryBlock> children = |
250 json['children'].map(AbstractEntity.fromJson).toList(); | 254 json['children'] |
| 255 .map((j) => AbstractEntity.fromJson(j, strategy)) |
| 256 .toList(); |
251 return new OutputStructure(lines, headerEnd, footerStart, children); | 257 return new OutputStructure(lines, headerEnd, footerStart, children); |
252 } | 258 } |
253 } | 259 } |
254 | 260 |
255 abstract class AbstractEntity extends OutputEntity { | 261 abstract class AbstractEntity extends OutputEntity { |
256 final String name; | 262 final String name; |
257 final int from; | 263 final int from; |
258 int to; | 264 int to; |
259 | 265 |
260 AbstractEntity(this.name, this.from); | 266 AbstractEntity(this.name, this.from); |
261 | 267 |
262 Interval get interval => new Interval(from, to); | 268 Interval get interval => new Interval(from, to); |
263 | 269 |
264 @override | 270 @override |
265 Map toJson() { | 271 Map toJson(JsonStrategy strategy) { |
266 return { | 272 return { |
267 'kind': kind.index, | 273 'kind': kind.index, |
268 'name': name, | 274 'name': name, |
269 'from': from, | 275 'from': from, |
270 'to': to, | 276 'to': to, |
271 'children': children.map((child) => child.toJson()).toList(), | 277 'children': children.map((child) => child.toJson(strategy)).toList(), |
272 'codeSource': codeSource != null ? codeSource.toJson() : null, | 278 'codeSource': codeSource != null ? codeSource.toJson() : null, |
273 }; | 279 }; |
274 } | 280 } |
275 | 281 |
276 static AbstractEntity fromJson(Map json) { | 282 static AbstractEntity fromJson(Map json, JsonStrategy strategy) { |
277 EntityKind kind = EntityKind.values[json['kind']]; | 283 EntityKind kind = EntityKind.values[json['kind']]; |
278 String name = json['name']; | 284 String name = json['name']; |
279 int from = json['from']; | 285 int from = json['from']; |
280 int to = json['to']; | 286 int to = json['to']; |
281 CodeSource codeSource = CodeSource.fromJson(json['codeSource']); | 287 CodeSource codeSource = CodeSource.fromJson(json['codeSource']); |
282 | 288 |
283 switch (kind) { | 289 switch (kind) { |
284 case EntityKind.STRUCTURE: | 290 case EntityKind.STRUCTURE: |
285 throw new StateError('Unexpected entity kind $kind'); | 291 throw new StateError('Unexpected entity kind $kind'); |
286 case EntityKind.LIBRARY: | 292 case EntityKind.LIBRARY: |
287 LibraryBlock lib = new LibraryBlock(name, from) | 293 LibraryBlock lib = new LibraryBlock(name, from) |
288 ..to = to | 294 ..to = to |
289 ..codeSource = codeSource; | 295 ..codeSource = codeSource; |
290 json['children'].forEach((child) => lib.children.add(fromJson(child))); | 296 json['children'] |
| 297 .forEach((child) => lib.children.add(fromJson(child, strategy))); |
291 return lib; | 298 return lib; |
292 case EntityKind.CLASS: | 299 case EntityKind.CLASS: |
293 LibraryClass cls = new LibraryClass(name, from) | 300 LibraryClass cls = new LibraryClass(name, from) |
294 ..to = to | 301 ..to = to |
295 ..codeSource = codeSource; | 302 ..codeSource = codeSource; |
296 json['children'].forEach((child) => cls.children.add(fromJson(child))); | 303 json['children'] |
| 304 .forEach((child) => cls.children.add(fromJson(child, strategy))); |
297 return cls; | 305 return cls; |
298 case EntityKind.TOP_LEVEL_FUNCTION: | 306 case EntityKind.TOP_LEVEL_FUNCTION: |
299 return new TopLevelFunction(name, from) | 307 return new TopLevelFunction(name, from) |
300 ..to = to | 308 ..to = to |
301 ..codeSource = codeSource; | 309 ..codeSource = codeSource; |
302 case EntityKind.TOP_LEVEL_VALUE: | 310 case EntityKind.TOP_LEVEL_VALUE: |
303 return new TopLevelValue(name, from) | 311 return new TopLevelValue(name, from) |
304 ..to = to | 312 ..to = to |
305 ..codeSource = codeSource; | 313 ..codeSource = codeSource; |
306 case EntityKind.MEMBER_FUNCTION: | 314 case EntityKind.MEMBER_FUNCTION: |
307 return new MemberFunction(name, from) | 315 return new MemberFunction(name, from) |
308 ..to = to | 316 ..to = to |
309 ..codeSource = codeSource; | 317 ..codeSource = codeSource; |
310 case EntityKind.MEMBER_OBJECT: | 318 case EntityKind.MEMBER_OBJECT: |
311 return new MemberObject(name, from) | 319 return new MemberObject(name, from) |
312 ..to = to | 320 ..to = to |
313 ..codeSource = codeSource; | 321 ..codeSource = codeSource; |
314 case EntityKind.MEMBER_VALUE: | 322 case EntityKind.MEMBER_VALUE: |
315 return new MemberValue(name, from) | 323 return new MemberValue(name, from) |
316 ..to = to | 324 ..to = to |
317 ..codeSource = codeSource; | 325 ..codeSource = codeSource; |
318 case EntityKind.STATICS: | 326 case EntityKind.STATICS: |
319 Statics statics = new Statics(from) | 327 Statics statics = new Statics(from) |
320 ..to = to | 328 ..to = to |
321 ..codeSource = codeSource; | 329 ..codeSource = codeSource; |
322 json['children'].forEach( | 330 json['children'].forEach( |
323 (child) => statics.children.add(fromJson(child))); | 331 (child) => statics.children.add(fromJson(child, strategy))); |
324 return statics; | 332 return statics; |
325 case EntityKind.STATIC_FUNCTION: | 333 case EntityKind.STATIC_FUNCTION: |
326 return new StaticFunction(name, from) | 334 return new StaticFunction(name, from) |
327 ..to = to | 335 ..to = to |
328 ..codeSource = codeSource; | 336 ..codeSource = codeSource; |
329 } | 337 } |
330 } | 338 } |
331 } | 339 } |
332 | 340 |
333 /// A block defining the content of a Dart library. | 341 /// A block defining the content of a Dart library. |
334 class LibraryBlock extends AbstractEntity { | 342 class LibraryBlock extends AbstractEntity { |
335 List<BasicEntity> children = <BasicEntity>[]; | 343 List<BasicEntity> children = <BasicEntity>[]; |
336 int get headerEnd => from + 2; | 344 int get headerEnd => from + 2; |
337 int get footerStart => to - 1; | 345 int get footerStart => to/* - 1*/; |
338 | 346 |
339 LibraryBlock(String name, int from) : super(name, from); | 347 LibraryBlock(String name, int from) : super(name, from); |
340 | 348 |
341 @override | 349 @override |
342 EntityKind get kind => EntityKind.LIBRARY; | 350 EntityKind get kind => EntityKind.LIBRARY; |
343 | 351 |
344 Interval get header => new Interval(from, headerEnd); | 352 Interval get header => new Interval(from, headerEnd); |
345 | 353 |
346 Interval get footer => new Interval(footerStart, to); | 354 Interval get footer => new Interval(footerStart, to); |
347 | 355 |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 } | 625 } |
618 | 626 |
619 class Interval { | 627 class Interval { |
620 final int from; | 628 final int from; |
621 final int to; | 629 final int to; |
622 | 630 |
623 const Interval(this.from, this.to); | 631 const Interval(this.from, this.to); |
624 | 632 |
625 int get length => to - from; | 633 int get length => to - from; |
626 | 634 |
| 635 bool get isEmpty => from == to; |
| 636 |
627 bool contains(int value) { | 637 bool contains(int value) { |
628 return from <= value && value < to; | 638 return from <= value && value < to; |
629 } | 639 } |
| 640 |
| 641 Interval include(int index) { |
| 642 return new Interval(Math.min(from, index), Math.max(to, index + 1)); |
| 643 } |
| 644 |
| 645 bool inWindow(int index, {int windowSize: 0}) { |
| 646 return from - windowSize <= index && index < to + windowSize; |
| 647 } |
| 648 |
| 649 String toString() => '[$from,$to['; |
630 } | 650 } |
631 | 651 |
632 enum CodeKind { | 652 enum CodeKind { |
633 LIBRARY, | 653 LIBRARY, |
634 CLASS, | 654 CLASS, |
635 MEMBER, | 655 MEMBER, |
636 } | 656 } |
637 | 657 |
| 658 class CodeLocation { |
| 659 final Uri uri; |
| 660 final String name; |
| 661 final int offset; |
| 662 |
| 663 CodeLocation(this.uri, this.name, this.offset); |
| 664 |
| 665 String toString() => '$uri:$name:$offset'; |
| 666 |
| 667 Map toJson(JsonStrategy strategy) { |
| 668 return { |
| 669 'uri': uri.toString(), |
| 670 'name': name, |
| 671 'offset': offset, |
| 672 }; |
| 673 } |
| 674 |
| 675 static CodeLocation fromJson(Map json, JsonStrategy strategy) { |
| 676 if (json == null) return null; |
| 677 return new CodeLocation( |
| 678 Uri.parse(json['uri']), |
| 679 json['name'], |
| 680 json['offset']); |
| 681 } |
| 682 } |
| 683 |
| 684 /// A named entity in source code. This is used to serialize [Element] |
| 685 /// references without serializing the [Element] itself. |
638 class CodeSource { | 686 class CodeSource { |
639 final CodeKind kind; | 687 final CodeKind kind; |
640 final Uri uri; | 688 final Uri uri; |
641 final String name; | 689 final String name; |
642 final int begin; | 690 final int begin; |
643 final int end; | 691 final int end; |
| 692 final List<CodeSource> members = <CodeSource>[]; |
644 | 693 |
645 CodeSource(this.kind, this.uri, this.name, this.begin, this.end); | 694 CodeSource(this.kind, this.uri, this.name, this.begin, this.end); |
646 | 695 |
| 696 int get hashCode { |
| 697 return |
| 698 kind.hashCode * 13 + |
| 699 uri.hashCode * 17 + |
| 700 name.hashCode * 19 + |
| 701 begin.hashCode * 23; |
| 702 } |
| 703 |
| 704 bool operator ==(other) { |
| 705 if (identical(this, other)) return true; |
| 706 if (other is! CodeSource) return false; |
| 707 return |
| 708 kind == other.kind && |
| 709 uri == other.uri && |
| 710 name == other.name && |
| 711 begin == other.begin; |
| 712 |
| 713 } |
| 714 |
647 String toString() => '${toJson()}'; | 715 String toString() => '${toJson()}'; |
648 | 716 |
649 Map toJson() { | 717 Map toJson() { |
650 return { | 718 return { |
651 'kind': kind.index, | 719 'kind': kind.index, |
652 'uri': uri.toString(), | 720 'uri': uri.toString(), |
653 'name': name, | 721 'name': name, |
654 'begin': begin, | 722 'begin': begin, |
655 'end': end, | 723 'end': end, |
| 724 'members': members.map((c) => c.toJson()).toList(), |
656 }; | 725 }; |
657 } | 726 } |
658 | 727 |
659 static CodeSource fromJson(Map json) { | 728 static CodeSource fromJson(Map json) { |
660 if (json == null) return null; | 729 if (json == null) return null; |
661 return new CodeSource( | 730 CodeSource codeSource = new CodeSource( |
662 CodeKind.values[json['kind']], | 731 CodeKind.values[json['kind']], |
663 Uri.parse(json['uri']), | 732 Uri.parse(json['uri']), |
664 json['name'], | 733 json['name'], |
665 json['begin'], | 734 json['begin'], |
666 json['end']); | 735 json['end']); |
| 736 json['members'].forEach((m) => codeSource.members.add(fromJson(m))); |
| 737 return codeSource; |
667 } | 738 } |
668 } | 739 } |
OLD | NEW |