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 'dart:math' as Math; |
8 import 'html_parts.dart' show | 8 import 'html_parts.dart' show Annotation, CodeLine, JsonStrategy; |
9 Annotation, | |
10 CodeLine, | |
11 JsonStrategy; | |
12 | 9 |
13 // Constants used to identify the subsection of the JavaScript output. These | 10 // Constants used to identify the subsection of the JavaScript output. These |
14 // are specifically for the unminified full_emitter output. | 11 // are specifically for the unminified full_emitter output. |
15 const String HEAD = ' var dart = ['; | 12 const String HEAD = ' var dart = ['; |
16 const String TAIL = ' }], '; | 13 const String TAIL = ' }], '; |
17 const String END = ' setupProgram(dart'; | 14 const String END = ' setupProgram(dart'; |
18 | 15 |
19 final RegExp TOP_LEVEL_VALUE = new RegExp(r'^ (".+?"):'); | 16 final RegExp TOP_LEVEL_VALUE = new RegExp(r'^ (".+?"):'); |
20 final RegExp TOP_LEVEL_FUNCTION = | 17 final RegExp TOP_LEVEL_FUNCTION = |
21 new RegExp(r'^ ([a-zA-Z0-9_$]+): \[?function'); | 18 new RegExp(r'^ ([a-zA-Z0-9_$]+): \[?function'); |
(...skipping 14 matching lines...) Loading... |
36 Interval get header; | 33 Interval get header; |
37 Interval get footer; | 34 Interval get footer; |
38 | 35 |
39 bool get canHaveChildren => false; | 36 bool get canHaveChildren => false; |
40 | 37 |
41 List<OutputEntity> get children; | 38 List<OutputEntity> get children; |
42 | 39 |
43 CodeSource codeSource; | 40 CodeSource codeSource; |
44 | 41 |
45 Interval getChildInterval(Interval childIndex) { | 42 Interval getChildInterval(Interval childIndex) { |
46 return new Interval( | 43 return new Interval(children[childIndex.from].interval.from, |
47 children[childIndex.from].interval.from, | |
48 children[childIndex.to - 1].interval.to); | 44 children[childIndex.to - 1].interval.to); |
49 | |
50 } | 45 } |
51 | 46 |
52 OutputEntity getChild(int index) { | 47 OutputEntity getChild(int index) { |
53 return children[index]; | 48 return children[index]; |
54 } | 49 } |
55 | 50 |
56 accept(OutputVisitor visitor, arg); | 51 accept(OutputVisitor visitor, arg); |
57 | 52 |
58 EntityKind get kind; | 53 EntityKind get kind; |
59 | 54 |
(...skipping 70 matching lines...) Loading... |
130 } | 125 } |
131 } | 126 } |
132 | 127 |
133 /// The whole JavaScript output. | 128 /// The whole JavaScript output. |
134 class OutputStructure extends OutputEntity { | 129 class OutputStructure extends OutputEntity { |
135 final List<CodeLine> lines; | 130 final List<CodeLine> lines; |
136 final int headerEnd; | 131 final int headerEnd; |
137 final int footerStart; | 132 final int footerStart; |
138 final List<LibraryBlock> children; | 133 final List<LibraryBlock> children; |
139 | 134 |
140 OutputStructure( | 135 OutputStructure(this.lines, this.headerEnd, this.footerStart, this.children); |
141 this.lines, | |
142 this.headerEnd, | |
143 this.footerStart, | |
144 this.children); | |
145 | 136 |
146 @override | 137 @override |
147 EntityKind get kind => EntityKind.STRUCTURE; | 138 EntityKind get kind => EntityKind.STRUCTURE; |
148 | 139 |
149 Interval get interval => new Interval(0, lines.length); | 140 Interval get interval => new Interval(0, lines.length); |
150 | 141 |
151 Interval get header => new Interval(0, headerEnd); | 142 Interval get header => new Interval(0, headerEnd); |
152 | 143 |
153 Interval get footer => new Interval(footerStart, lines.length); | 144 Interval get footer => new Interval(footerStart, lines.length); |
154 | 145 |
155 bool get canHaveChildren => true; | 146 bool get canHaveChildren => true; |
156 | 147 |
157 OutputEntity getEntityForLine(int line) { | 148 OutputEntity getEntityForLine(int line) { |
158 if (line < headerEnd || line >= footerStart) { | 149 if (line < headerEnd || line >= footerStart) { |
159 return this; | 150 return this; |
160 } | 151 } |
161 for (LibraryBlock library in children) { | 152 for (LibraryBlock library in children) { |
162 if (library.interval.contains(line)) { | 153 if (library.interval.contains(line)) { |
163 return library.getEntityForLine(line); | 154 return library.getEntityForLine(line); |
164 } | 155 } |
165 } | 156 } |
166 return null; | 157 return null; |
167 } | 158 } |
168 | 159 |
169 /// Compute the structure of the JavaScript [lines]. | 160 /// Compute the structure of the JavaScript [lines]. |
170 static OutputStructure parse(List<CodeLine> lines) { | 161 static OutputStructure parse(List<CodeLine> lines) { |
171 | |
172 int findHeaderStart(List<CodeLine> lines) { | 162 int findHeaderStart(List<CodeLine> lines) { |
173 int index = 0; | 163 int index = 0; |
174 for (CodeLine line in lines) { | 164 for (CodeLine line in lines) { |
175 if (line.code.startsWith(HEAD)) { | 165 if (line.code.startsWith(HEAD)) { |
176 return index; | 166 return index; |
177 } | 167 } |
178 index++; | 168 index++; |
179 } | 169 } |
180 return lines.length; | 170 return lines.length; |
181 } | 171 } |
(...skipping 40 matching lines...) Loading... |
222 } | 212 } |
223 | 213 |
224 int headerEnd = findHeaderStart(lines); | 214 int headerEnd = findHeaderStart(lines); |
225 int footerStart = findHeaderEnd(headerEnd, lines); | 215 int footerStart = findHeaderEnd(headerEnd, lines); |
226 List<LibraryBlock> libraryBlocks = | 216 List<LibraryBlock> libraryBlocks = |
227 computeHeaderMap(lines, headerEnd, footerStart); | 217 computeHeaderMap(lines, headerEnd, footerStart); |
228 for (LibraryBlock block in libraryBlocks) { | 218 for (LibraryBlock block in libraryBlocks) { |
229 block.preprocess(lines); | 219 block.preprocess(lines); |
230 } | 220 } |
231 | 221 |
232 return new OutputStructure( | 222 return new OutputStructure(lines, headerEnd, footerStart, libraryBlocks); |
233 lines, headerEnd, footerStart, libraryBlocks); | |
234 } | 223 } |
235 | 224 |
236 accept(OutputVisitor visitor, arg) => visitor.visitStructure(this, arg); | 225 accept(OutputVisitor visitor, arg) => visitor.visitStructure(this, arg); |
237 | 226 |
238 @override | 227 @override |
239 Map toJson(JsonStrategy strategy) { | 228 Map toJson(JsonStrategy strategy) { |
240 return { | 229 return { |
241 'lines': lines.map((line) => line.toJson(strategy)).toList(), | 230 'lines': lines.map((line) => line.toJson(strategy)).toList(), |
242 'headerEnd': headerEnd, | 231 'headerEnd': headerEnd, |
243 'footerStart': footerStart, | 232 'footerStart': footerStart, |
244 'children': children.map((child) => child.toJson(strategy)).toList(), | 233 'children': children.map((child) => child.toJson(strategy)).toList(), |
245 }; | 234 }; |
246 } | 235 } |
247 | 236 |
248 static OutputStructure fromJson(Map json, JsonStrategy strategy) { | 237 static OutputStructure fromJson(Map json, JsonStrategy strategy) { |
249 List<CodeLine> lines = | 238 List<CodeLine> lines = |
250 json['lines'].map((l) => CodeLine.fromJson(l, strategy)).toList(); | 239 json['lines'].map((l) => CodeLine.fromJson(l, strategy)).toList(); |
251 int headerEnd = json['headerEnd']; | 240 int headerEnd = json['headerEnd']; |
252 int footerStart = json['footerStart']; | 241 int footerStart = json['footerStart']; |
253 List<LibraryBlock> children = | 242 List<LibraryBlock> children = json['children'] |
254 json['children'] | 243 .map((j) => AbstractEntity.fromJson(j, strategy)) |
255 .map((j) => AbstractEntity.fromJson(j, strategy)) | 244 .toList(); |
256 .toList(); | |
257 return new OutputStructure(lines, headerEnd, footerStart, children); | 245 return new OutputStructure(lines, headerEnd, footerStart, children); |
258 } | 246 } |
259 } | 247 } |
260 | 248 |
261 abstract class AbstractEntity extends OutputEntity { | 249 abstract class AbstractEntity extends OutputEntity { |
262 final String name; | 250 final String name; |
263 final int from; | 251 final int from; |
264 int to; | 252 int to; |
265 | 253 |
266 AbstractEntity(this.name, this.from); | 254 AbstractEntity(this.name, this.from); |
(...skipping 24 matching lines...) Loading... |
291 throw new StateError('Unexpected entity kind $kind'); | 279 throw new StateError('Unexpected entity kind $kind'); |
292 case EntityKind.LIBRARY: | 280 case EntityKind.LIBRARY: |
293 LibraryBlock lib = new LibraryBlock(name, from) | 281 LibraryBlock lib = new LibraryBlock(name, from) |
294 ..to = to | 282 ..to = to |
295 ..codeSource = codeSource; | 283 ..codeSource = codeSource; |
296 json['children'] | 284 json['children'] |
297 .forEach((child) => lib.children.add(fromJson(child, strategy))); | 285 .forEach((child) => lib.children.add(fromJson(child, strategy))); |
298 return lib; | 286 return lib; |
299 case EntityKind.CLASS: | 287 case EntityKind.CLASS: |
300 LibraryClass cls = new LibraryClass(name, from) | 288 LibraryClass cls = new LibraryClass(name, from) |
301 ..to = to | 289 ..to = to |
302 ..codeSource = codeSource; | 290 ..codeSource = codeSource; |
303 json['children'] | 291 json['children'] |
304 .forEach((child) => cls.children.add(fromJson(child, strategy))); | 292 .forEach((child) => cls.children.add(fromJson(child, strategy))); |
305 return cls; | 293 return cls; |
306 case EntityKind.TOP_LEVEL_FUNCTION: | 294 case EntityKind.TOP_LEVEL_FUNCTION: |
307 return new TopLevelFunction(name, from) | 295 return new TopLevelFunction(name, from) |
308 ..to = to | 296 ..to = to |
309 ..codeSource = codeSource; | 297 ..codeSource = codeSource; |
310 case EntityKind.TOP_LEVEL_VALUE: | 298 case EntityKind.TOP_LEVEL_VALUE: |
311 return new TopLevelValue(name, from) | 299 return new TopLevelValue(name, from) |
312 ..to = to | 300 ..to = to |
313 ..codeSource = codeSource; | 301 ..codeSource = codeSource; |
314 case EntityKind.MEMBER_FUNCTION: | 302 case EntityKind.MEMBER_FUNCTION: |
315 return new MemberFunction(name, from) | 303 return new MemberFunction(name, from) |
316 ..to = to | 304 ..to = to |
317 ..codeSource = codeSource; | 305 ..codeSource = codeSource; |
318 case EntityKind.MEMBER_OBJECT: | 306 case EntityKind.MEMBER_OBJECT: |
319 return new MemberObject(name, from) | 307 return new MemberObject(name, from) |
320 ..to = to | 308 ..to = to |
321 ..codeSource = codeSource; | 309 ..codeSource = codeSource; |
322 case EntityKind.MEMBER_VALUE: | 310 case EntityKind.MEMBER_VALUE: |
323 return new MemberValue(name, from) | 311 return new MemberValue(name, from) |
324 ..to = to | 312 ..to = to |
325 ..codeSource = codeSource; | 313 ..codeSource = codeSource; |
326 case EntityKind.STATICS: | 314 case EntityKind.STATICS: |
327 Statics statics = new Statics(from) | 315 Statics statics = new Statics(from) |
328 ..to = to | 316 ..to = to |
329 ..codeSource = codeSource; | 317 ..codeSource = codeSource; |
330 json['children'].forEach( | 318 json['children'].forEach( |
331 (child) => statics.children.add(fromJson(child, strategy))); | 319 (child) => statics.children.add(fromJson(child, strategy))); |
332 return statics; | 320 return statics; |
333 case EntityKind.STATIC_FUNCTION: | 321 case EntityKind.STATIC_FUNCTION: |
334 return new StaticFunction(name, from) | 322 return new StaticFunction(name, from) |
335 ..to = to | 323 ..to = to |
336 ..codeSource = codeSource; | 324 ..codeSource = codeSource; |
337 } | 325 } |
338 } | 326 } |
339 } | 327 } |
340 | 328 |
341 /// A block defining the content of a Dart library. | 329 /// A block defining the content of a Dart library. |
342 class LibraryBlock extends AbstractEntity { | 330 class LibraryBlock extends AbstractEntity { |
343 List<BasicEntity> children = <BasicEntity>[]; | 331 List<BasicEntity> children = <BasicEntity>[]; |
344 int get headerEnd => from + 2; | 332 int get headerEnd => from + 2; |
345 int get footerStart => to/* - 1*/; | 333 int get footerStart => to /* - 1*/; |
346 | 334 |
347 LibraryBlock(String name, int from) : super(name, from); | 335 LibraryBlock(String name, int from) : super(name, from); |
348 | 336 |
349 @override | 337 @override |
350 EntityKind get kind => EntityKind.LIBRARY; | 338 EntityKind get kind => EntityKind.LIBRARY; |
351 | 339 |
352 Interval get header => new Interval(from, headerEnd); | 340 Interval get header => new Interval(from, headerEnd); |
353 | 341 |
354 Interval get footer => new Interval(footerStart, to); | 342 Interval get footer => new Interval(footerStart, to); |
355 | 343 |
(...skipping 286 matching lines...) Loading... |
642 return new Interval(Math.min(from, index), Math.max(to, index + 1)); | 630 return new Interval(Math.min(from, index), Math.max(to, index + 1)); |
643 } | 631 } |
644 | 632 |
645 bool inWindow(int index, {int windowSize: 0}) { | 633 bool inWindow(int index, {int windowSize: 0}) { |
646 return from - windowSize <= index && index < to + windowSize; | 634 return from - windowSize <= index && index < to + windowSize; |
647 } | 635 } |
648 | 636 |
649 String toString() => '[$from,$to['; | 637 String toString() => '[$from,$to['; |
650 } | 638 } |
651 | 639 |
652 enum CodeKind { | 640 enum CodeKind { LIBRARY, CLASS, MEMBER, } |
653 LIBRARY, | |
654 CLASS, | |
655 MEMBER, | |
656 } | |
657 | 641 |
658 class CodeLocation { | 642 class CodeLocation { |
659 final Uri uri; | 643 final Uri uri; |
660 final String name; | 644 final String name; |
661 final int offset; | 645 final int offset; |
662 | 646 |
663 CodeLocation(this.uri, this.name, this.offset); | 647 CodeLocation(this.uri, this.name, this.offset); |
664 | 648 |
665 String toString() => '$uri:$name:$offset'; | 649 String toString() => '$uri:$name:$offset'; |
666 | 650 |
667 Map toJson(JsonStrategy strategy) { | 651 Map toJson(JsonStrategy strategy) { |
668 return { | 652 return {'uri': uri.toString(), 'name': name, 'offset': offset,}; |
669 'uri': uri.toString(), | |
670 'name': name, | |
671 'offset': offset, | |
672 }; | |
673 } | 653 } |
674 | 654 |
675 static CodeLocation fromJson(Map json, JsonStrategy strategy) { | 655 static CodeLocation fromJson(Map json, JsonStrategy strategy) { |
676 if (json == null) return null; | 656 if (json == null) return null; |
677 return new CodeLocation( | 657 return new CodeLocation( |
678 Uri.parse(json['uri']), | 658 Uri.parse(json['uri']), json['name'], json['offset']); |
679 json['name'], | |
680 json['offset']); | |
681 } | 659 } |
682 } | 660 } |
683 | 661 |
684 /// A named entity in source code. This is used to serialize [Element] | 662 /// A named entity in source code. This is used to serialize [Element] |
685 /// references without serializing the [Element] itself. | 663 /// references without serializing the [Element] itself. |
686 class CodeSource { | 664 class CodeSource { |
687 final CodeKind kind; | 665 final CodeKind kind; |
688 final Uri uri; | 666 final Uri uri; |
689 final String name; | 667 final String name; |
690 final int begin; | 668 final int begin; |
691 final int end; | 669 final int end; |
692 final List<CodeSource> members = <CodeSource>[]; | 670 final List<CodeSource> members = <CodeSource>[]; |
693 | 671 |
694 CodeSource(this.kind, this.uri, this.name, this.begin, this.end); | 672 CodeSource(this.kind, this.uri, this.name, this.begin, this.end); |
695 | 673 |
696 int get hashCode { | 674 int get hashCode { |
697 return | 675 return kind.hashCode * 13 + |
698 kind.hashCode * 13 + | |
699 uri.hashCode * 17 + | 676 uri.hashCode * 17 + |
700 name.hashCode * 19 + | 677 name.hashCode * 19 + |
701 begin.hashCode * 23; | 678 begin.hashCode * 23; |
702 } | 679 } |
703 | 680 |
704 bool operator ==(other) { | 681 bool operator ==(other) { |
705 if (identical(this, other)) return true; | 682 if (identical(this, other)) return true; |
706 if (other is! CodeSource) return false; | 683 if (other is! CodeSource) return false; |
707 return | 684 return kind == other.kind && |
708 kind == other.kind && | |
709 uri == other.uri && | 685 uri == other.uri && |
710 name == other.name && | 686 name == other.name && |
711 begin == other.begin; | 687 begin == other.begin; |
712 | |
713 } | 688 } |
714 | 689 |
715 String toString() => '${toJson()}'; | 690 String toString() => '${toJson()}'; |
716 | 691 |
717 Map toJson() { | 692 Map toJson() { |
718 return { | 693 return { |
719 'kind': kind.index, | 694 'kind': kind.index, |
720 'uri': uri.toString(), | 695 'uri': uri.toString(), |
721 'name': name, | 696 'name': name, |
722 'begin': begin, | 697 'begin': begin, |
723 'end': end, | 698 'end': end, |
724 'members': members.map((c) => c.toJson()).toList(), | 699 'members': members.map((c) => c.toJson()).toList(), |
725 }; | 700 }; |
726 } | 701 } |
727 | 702 |
728 static CodeSource fromJson(Map json) { | 703 static CodeSource fromJson(Map json) { |
729 if (json == null) return null; | 704 if (json == null) return null; |
730 CodeSource codeSource = new CodeSource( | 705 CodeSource codeSource = new CodeSource(CodeKind.values[json['kind']], |
731 CodeKind.values[json['kind']], | 706 Uri.parse(json['uri']), json['name'], json['begin'], json['end']); |
732 Uri.parse(json['uri']), | |
733 json['name'], | |
734 json['begin'], | |
735 json['end']); | |
736 json['members'].forEach((m) => codeSource.members.add(fromJson(m))); | 707 json['members'].forEach((m) => codeSource.members.add(fromJson(m))); |
737 return codeSource; | 708 return codeSource; |
738 } | 709 } |
739 } | 710 } |
OLD | NEW |