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...) Expand all 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand all 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 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 return { | 656 return { |
669 'uri': uri.toString(), | 657 'uri': uri.toString(), |
670 'name': name, | 658 'name': name, |
671 'offset': offset, | 659 'offset': offset, |
672 }; | 660 }; |
673 } | 661 } |
674 | 662 |
675 static CodeLocation fromJson(Map json, JsonStrategy strategy) { | 663 static CodeLocation fromJson(Map json, JsonStrategy strategy) { |
676 if (json == null) return null; | 664 if (json == null) return null; |
677 return new CodeLocation( | 665 return new CodeLocation( |
678 Uri.parse(json['uri']), | 666 Uri.parse(json['uri']), json['name'], json['offset']); |
679 json['name'], | |
680 json['offset']); | |
681 } | 667 } |
682 } | 668 } |
683 | 669 |
684 /// A named entity in source code. This is used to serialize [Element] | 670 /// A named entity in source code. This is used to serialize [Element] |
685 /// references without serializing the [Element] itself. | 671 /// references without serializing the [Element] itself. |
686 class CodeSource { | 672 class CodeSource { |
687 final CodeKind kind; | 673 final CodeKind kind; |
688 final Uri uri; | 674 final Uri uri; |
689 final String name; | 675 final String name; |
690 final int begin; | 676 final int begin; |
691 final int end; | 677 final int end; |
692 final List<CodeSource> members = <CodeSource>[]; | 678 final List<CodeSource> members = <CodeSource>[]; |
693 | 679 |
694 CodeSource(this.kind, this.uri, this.name, this.begin, this.end); | 680 CodeSource(this.kind, this.uri, this.name, this.begin, this.end); |
695 | 681 |
696 int get hashCode { | 682 int get hashCode { |
697 return | 683 return kind.hashCode * 13 + |
698 kind.hashCode * 13 + | |
699 uri.hashCode * 17 + | 684 uri.hashCode * 17 + |
700 name.hashCode * 19 + | 685 name.hashCode * 19 + |
701 begin.hashCode * 23; | 686 begin.hashCode * 23; |
702 } | 687 } |
703 | 688 |
704 bool operator ==(other) { | 689 bool operator ==(other) { |
705 if (identical(this, other)) return true; | 690 if (identical(this, other)) return true; |
706 if (other is! CodeSource) return false; | 691 if (other is! CodeSource) return false; |
707 return | 692 return kind == other.kind && |
708 kind == other.kind && | |
709 uri == other.uri && | 693 uri == other.uri && |
710 name == other.name && | 694 name == other.name && |
711 begin == other.begin; | 695 begin == other.begin; |
712 | |
713 } | 696 } |
714 | 697 |
715 String toString() => '${toJson()}'; | 698 String toString() => '${toJson()}'; |
716 | 699 |
717 Map toJson() { | 700 Map toJson() { |
718 return { | 701 return { |
719 'kind': kind.index, | 702 'kind': kind.index, |
720 'uri': uri.toString(), | 703 'uri': uri.toString(), |
721 'name': name, | 704 'name': name, |
722 'begin': begin, | 705 'begin': begin, |
723 'end': end, | 706 'end': end, |
724 'members': members.map((c) => c.toJson()).toList(), | 707 'members': members.map((c) => c.toJson()).toList(), |
725 }; | 708 }; |
726 } | 709 } |
727 | 710 |
728 static CodeSource fromJson(Map json) { | 711 static CodeSource fromJson(Map json) { |
729 if (json == null) return null; | 712 if (json == null) return null; |
730 CodeSource codeSource = new CodeSource( | 713 CodeSource codeSource = new CodeSource(CodeKind.values[json['kind']], |
731 CodeKind.values[json['kind']], | 714 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))); | 715 json['members'].forEach((m) => codeSource.members.add(fromJson(m))); |
737 return codeSource; | 716 return codeSource; |
738 } | 717 } |
739 } | 718 } |
OLD | NEW |