| 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 |