| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 source_map_builder; | 5 library source_map_builder; |
| 6 | 6 |
| 7 import 'util/util.dart'; | 7 import 'util/util.dart'; |
| 8 import 'scanner/scannerlib.dart' show Token; | 8 import 'scanner/scannerlib.dart' show Token; |
| 9 import 'source_file.dart'; | 9 import 'source_file.dart'; |
| 10 import 'util/uri_extras.dart' show relativize; | 10 import 'util/uri_extras.dart' show relativize; |
| 11 | 11 |
| 12 class SourceMapBuilder { | 12 class SourceMapBuilder { |
| 13 static const int VLQ_BASE_SHIFT = 5; | 13 static const int VLQ_BASE_SHIFT = 5; |
| 14 static const int VLQ_BASE_MASK = (1 << 5) - 1; | 14 static const int VLQ_BASE_MASK = (1 << 5) - 1; |
| 15 static const int VLQ_CONTINUATION_BIT = 1 << 5; | 15 static const int VLQ_CONTINUATION_BIT = 1 << 5; |
| 16 static const int VLQ_CONTINUATION_MASK = 1 << 5; | 16 static const int VLQ_CONTINUATION_MASK = 1 << 5; |
| 17 static const String BASE64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn' | 17 static const String BASE64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn' |
| 18 'opqrstuvwxyz0123456789+/'; | 18 'opqrstuvwxyz0123456789+/'; |
| 19 | 19 |
| 20 final Uri uri; | 20 final Uri uri; |
| 21 final Uri fileUri; | 21 final Uri fileUri; |
| 22 | 22 |
| 23 SourceFile targetFile; |
| 23 List<SourceMapEntry> entries; | 24 List<SourceMapEntry> entries; |
| 24 | 25 |
| 25 Map<String, int> sourceUrlMap; | 26 Map<String, int> sourceUrlMap; |
| 26 List<String> sourceUrlList; | 27 List<String> sourceUrlList; |
| 27 Map<String, int> sourceNameMap; | 28 Map<String, int> sourceNameMap; |
| 28 List<String> sourceNameList; | 29 List<String> sourceNameList; |
| 29 | 30 |
| 30 int previousTargetLine; | 31 int previousTargetLine; |
| 31 int previousTargetColumn; | 32 int previousTargetColumn; |
| 32 int previousSourceUrlIndex; | 33 int previousSourceUrlIndex; |
| 33 int previousSourceLine; | 34 int previousSourceLine; |
| 34 int previousSourceColumn; | 35 int previousSourceColumn; |
| 35 int previousSourceNameIndex; | 36 int previousSourceNameIndex; |
| 36 bool firstEntryInLine; | 37 bool firstEntryInLine; |
| 37 | 38 |
| 38 SourceMapBuilder(this.uri, this.fileUri) { | 39 SourceMapBuilder(this.uri, this.fileUri, this.targetFile) { |
| 39 entries = new List<SourceMapEntry>(); | 40 entries = new List<SourceMapEntry>(); |
| 40 | 41 |
| 41 sourceUrlMap = new Map<String, int>(); | 42 sourceUrlMap = new Map<String, int>(); |
| 42 sourceUrlList = new List<String>(); | 43 sourceUrlList = new List<String>(); |
| 43 sourceNameMap = new Map<String, int>(); | 44 sourceNameMap = new Map<String, int>(); |
| 44 sourceNameList = new List<String>(); | 45 sourceNameList = new List<String>(); |
| 45 | 46 |
| 46 previousTargetLine = 0; | 47 previousTargetLine = 0; |
| 47 previousTargetColumn = 0; | 48 previousTargetColumn = 0; |
| 48 previousSourceUrlIndex = 0; | 49 previousSourceUrlIndex = 0; |
| 49 previousSourceLine = 0; | 50 previousSourceLine = 0; |
| 50 previousSourceColumn = 0; | 51 previousSourceColumn = 0; |
| 51 previousSourceNameIndex = 0; | 52 previousSourceNameIndex = 0; |
| 52 firstEntryInLine = true; | 53 firstEntryInLine = true; |
| 53 } | 54 } |
| 54 | 55 |
| 56 resetPreviousSourceLocation() { |
| 57 previousSourceUrlIndex = 0; |
| 58 previousSourceLine = 0; |
| 59 previousSourceColumn = 0; |
| 60 previousSourceNameIndex = 0; |
| 61 } |
| 62 |
| 63 updatePreviousSourceLocation(SourceFileLocation sourceLocation) { |
| 64 previousSourceLine = sourceLocation.getLine(); |
| 65 previousSourceColumn = sourceLocation.getColumn(); |
| 66 String sourceUrl = sourceLocation.getSourceUrl(); |
| 67 previousSourceUrlIndex = indexOf(sourceUrlList, sourceUrl, sourceUrlMap); |
| 68 String sourceName = sourceLocation.getSourceName(); |
| 69 if (sourceName != null) { |
| 70 previousSourceNameIndex = |
| 71 indexOf(sourceNameList, sourceName, sourceNameMap); |
| 72 } |
| 73 } |
| 74 |
| 75 bool sameAsPreviousLocation(SourceFileLocation sourceLocation) { |
| 76 if (sourceLocation == null) { |
| 77 return true; |
| 78 } |
| 79 int sourceUrlIndex = |
| 80 indexOf(sourceUrlList, sourceLocation.getSourceUrl(), sourceUrlMap); |
| 81 return |
| 82 sourceUrlIndex == previousSourceUrlIndex && |
| 83 sourceLocation.getLine() == previousSourceLine && |
| 84 sourceLocation.getColumn() == previousSourceColumn; |
| 85 } |
| 86 |
| 55 void addMapping(int targetOffset, SourceFileLocation sourceLocation) { | 87 void addMapping(int targetOffset, SourceFileLocation sourceLocation) { |
| 88 |
| 89 bool sameLine(int position, otherPosition) { |
| 90 return targetFile.getLine(position) == targetFile.getLine(otherPosition); |
| 91 } |
| 92 |
| 93 if (!entries.isEmpty && sameLine(targetOffset, entries.last.targetOffset)) { |
| 94 if (sameAsPreviousLocation(sourceLocation)) { |
| 95 // The entry points to the same source location as the previous entry in |
| 96 // the same line, hence it is not needed for the source map. |
| 97 // |
| 98 // TODO(zarah): Remove this check and make sure that [addMapping] is not |
| 99 // called for this position. Instead, when consecutive lines in the |
| 100 // generated code point to the same source location, record this and use |
| 101 // it to generate the entries of the source map. |
| 102 return; |
| 103 } |
| 104 } |
| 105 |
| 106 if (sourceLocation != null) { |
| 107 updatePreviousSourceLocation(sourceLocation); |
| 108 } |
| 56 entries.add(new SourceMapEntry(sourceLocation, targetOffset)); | 109 entries.add(new SourceMapEntry(sourceLocation, targetOffset)); |
| 57 } | 110 } |
| 58 | 111 |
| 59 void printStringListOn(List<String> strings, StringBuffer buffer) { | 112 void printStringListOn(List<String> strings, StringBuffer buffer) { |
| 60 bool first = true; | 113 bool first = true; |
| 61 buffer.write('['); | 114 buffer.write('['); |
| 62 for (String string in strings) { | 115 for (String string in strings) { |
| 63 if (!first) buffer.write(','); | 116 if (!first) buffer.write(','); |
| 64 buffer.write('"'); | 117 buffer.write('"'); |
| 65 writeJsonEscapedCharsOn(string, buffer); | 118 writeJsonEscapedCharsOn(string, buffer); |
| 66 buffer.write('"'); | 119 buffer.write('"'); |
| 67 first = false; | 120 first = false; |
| 68 } | 121 } |
| 69 buffer.write(']'); | 122 buffer.write(']'); |
| 70 } | 123 } |
| 71 | 124 |
| 72 String build(SourceFile targetFile) { | 125 String build() { |
| 126 resetPreviousSourceLocation(); |
| 73 StringBuffer mappingsBuffer = new StringBuffer(); | 127 StringBuffer mappingsBuffer = new StringBuffer(); |
| 74 entries.forEach((SourceMapEntry entry) => writeEntry(entry, targetFile, | 128 entries.forEach((SourceMapEntry entry) => writeEntry(entry, targetFile, |
| 75 mappingsBuffer)); | 129 mappingsBuffer)); |
| 76 StringBuffer buffer = new StringBuffer(); | 130 StringBuffer buffer = new StringBuffer(); |
| 77 buffer.write('{\n'); | 131 buffer.write('{\n'); |
| 78 buffer.write(' "version": 3,\n'); | 132 buffer.write(' "version": 3,\n'); |
| 79 if (uri != null && fileUri != null) { | 133 if (uri != null && fileUri != null) { |
| 80 buffer.write(' "file": "${relativize(uri, fileUri, false)}",\n'); | 134 buffer.write(' "file": "${relativize(uri, fileUri, false)}",\n'); |
| 81 } | 135 } |
| 82 buffer.write(' "sourceRoot": "",\n'); | 136 buffer.write(' "sourceRoot": "",\n'); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 | 174 |
| 121 if (entry.sourceLocation == null) return; | 175 if (entry.sourceLocation == null) return; |
| 122 | 176 |
| 123 String sourceUrl = entry.sourceLocation.getSourceUrl(); | 177 String sourceUrl = entry.sourceLocation.getSourceUrl(); |
| 124 int sourceLine = entry.sourceLocation.getLine(); | 178 int sourceLine = entry.sourceLocation.getLine(); |
| 125 int sourceColumn = entry.sourceLocation.getColumn(); | 179 int sourceColumn = entry.sourceLocation.getColumn(); |
| 126 String sourceName = entry.sourceLocation.getSourceName(); | 180 String sourceName = entry.sourceLocation.getSourceName(); |
| 127 | 181 |
| 128 int sourceUrlIndex = indexOf(sourceUrlList, sourceUrl, sourceUrlMap); | 182 int sourceUrlIndex = indexOf(sourceUrlList, sourceUrl, sourceUrlMap); |
| 129 encodeVLQ(output, sourceUrlIndex - previousSourceUrlIndex); | 183 encodeVLQ(output, sourceUrlIndex - previousSourceUrlIndex); |
| 130 previousSourceUrlIndex = sourceUrlIndex; | |
| 131 | |
| 132 encodeVLQ(output, sourceLine - previousSourceLine); | 184 encodeVLQ(output, sourceLine - previousSourceLine); |
| 133 previousSourceLine = sourceLine; | |
| 134 encodeVLQ(output, sourceColumn - previousSourceColumn); | 185 encodeVLQ(output, sourceColumn - previousSourceColumn); |
| 135 previousSourceColumn = sourceColumn; | 186 updatePreviousSourceLocation(entry.sourceLocation); |
| 136 | 187 |
| 137 if (sourceName == null) { | 188 if (sourceName == null) { |
| 138 return; | 189 return; |
| 139 } | 190 } |
| 140 | 191 |
| 141 int sourceNameIndex = indexOf(sourceNameList, sourceName, sourceNameMap); | 192 int sourceNameIndex = indexOf(sourceNameList, sourceName, sourceNameMap); |
| 142 encodeVLQ(output, sourceNameIndex - previousSourceNameIndex); | 193 encodeVLQ(output, sourceNameIndex - previousSourceNameIndex); |
| 143 previousSourceNameIndex = sourceNameIndex; | 194 |
| 144 } | 195 } |
| 145 | 196 |
| 146 int indexOf(List<String> list, String value, Map<String, int> map) { | 197 int indexOf(List<String> list, String value, Map<String, int> map) { |
| 147 return map.putIfAbsent(value, () { | 198 return map.putIfAbsent(value, () { |
| 148 int index = list.length; | 199 int index = list.length; |
| 149 list.add(value); | 200 list.add(value); |
| 150 return index; | 201 return index; |
| 151 }); | 202 }); |
| 152 } | 203 } |
| 153 | 204 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 TokenSourceFileLocation(SourceFile sourceFile, this.token) | 258 TokenSourceFileLocation(SourceFile sourceFile, this.token) |
| 208 : super(sourceFile); | 259 : super(sourceFile); |
| 209 | 260 |
| 210 int get offset => token.charOffset; | 261 int get offset => token.charOffset; |
| 211 | 262 |
| 212 String getSourceName() { | 263 String getSourceName() { |
| 213 if (token.isIdentifier()) return token.value; | 264 if (token.isIdentifier()) return token.value; |
| 214 return null; | 265 return null; |
| 215 } | 266 } |
| 216 } | 267 } |
| OLD | NEW |