Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(367)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/source_map_builder.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library source_map_builder;
6
7 import 'util/util.dart';
8 import 'scanner/scannerlib.dart' show Token;
9 import 'source_file.dart';
10 import 'util/uri_extras.dart' show relativize;
11
12 class SourceMapBuilder {
13 static const int VLQ_BASE_SHIFT = 5;
14 static const int VLQ_BASE_MASK = (1 << 5) - 1;
15 static const int VLQ_CONTINUATION_BIT = 1 << 5;
16 static const int VLQ_CONTINUATION_MASK = 1 << 5;
17 static const String BASE64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn'
18 'opqrstuvwxyz0123456789+/';
19
20 final Uri uri;
21 final Uri fileUri;
22
23 SourceFile targetFile;
24 List<SourceMapEntry> entries;
25
26 Map<String, int> sourceUrlMap;
27 List<String> sourceUrlList;
28 Map<String, int> sourceNameMap;
29 List<String> sourceNameList;
30
31 int previousTargetLine;
32 int previousTargetColumn;
33 int previousSourceUrlIndex;
34 int previousSourceLine;
35 int previousSourceColumn;
36 int previousSourceNameIndex;
37 bool firstEntryInLine;
38
39 SourceMapBuilder(this.uri, this.fileUri, this.targetFile) {
40 entries = new List<SourceMapEntry>();
41
42 sourceUrlMap = new Map<String, int>();
43 sourceUrlList = new List<String>();
44 sourceNameMap = new Map<String, int>();
45 sourceNameList = new List<String>();
46
47 previousTargetLine = 0;
48 previousTargetColumn = 0;
49 previousSourceUrlIndex = 0;
50 previousSourceLine = 0;
51 previousSourceColumn = 0;
52 previousSourceNameIndex = 0;
53 firstEntryInLine = true;
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
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 }
109 entries.add(new SourceMapEntry(sourceLocation, targetOffset));
110 }
111
112 void printStringListOn(List<String> strings, StringBuffer buffer) {
113 bool first = true;
114 buffer.write('[');
115 for (String string in strings) {
116 if (!first) buffer.write(',');
117 buffer.write('"');
118 writeJsonEscapedCharsOn(string, buffer);
119 buffer.write('"');
120 first = false;
121 }
122 buffer.write(']');
123 }
124
125 String build() {
126 resetPreviousSourceLocation();
127 StringBuffer mappingsBuffer = new StringBuffer();
128 entries.forEach((SourceMapEntry entry) => writeEntry(entry, targetFile,
129 mappingsBuffer));
130 StringBuffer buffer = new StringBuffer();
131 buffer.write('{\n');
132 buffer.write(' "version": 3,\n');
133 if (uri != null && fileUri != null) {
134 buffer.write(' "file": "${relativize(uri, fileUri, false)}",\n');
135 }
136 buffer.write(' "sourceRoot": "",\n');
137 buffer.write(' "sources": ');
138 if (uri != null) {
139 sourceUrlList =
140 sourceUrlList.map((url) => relativize(uri, Uri.parse(url), false))
141 .toList();
142 }
143 printStringListOn(sourceUrlList, buffer);
144 buffer.write(',\n');
145 buffer.write(' "names": ');
146 printStringListOn(sourceNameList, buffer);
147 buffer.write(',\n');
148 buffer.write(' "mappings": "');
149 buffer.write(mappingsBuffer);
150 buffer.write('"\n}\n');
151 return buffer.toString();
152 }
153
154 void writeEntry(SourceMapEntry entry, SourceFile targetFile, StringBuffer outp ut) {
155 int targetLine = targetFile.getLine(entry.targetOffset);
156 int targetColumn = targetFile.getColumn(targetLine, entry.targetOffset);
157
158 if (targetLine > previousTargetLine) {
159 for (int i = previousTargetLine; i < targetLine; ++i) {
160 output.write(';');
161 }
162 previousTargetLine = targetLine;
163 previousTargetColumn = 0;
164 firstEntryInLine = true;
165 }
166
167 if (!firstEntryInLine) {
168 output.write(',');
169 }
170 firstEntryInLine = false;
171
172 encodeVLQ(output, targetColumn - previousTargetColumn);
173 previousTargetColumn = targetColumn;
174
175 if (entry.sourceLocation == null) return;
176
177 String sourceUrl = entry.sourceLocation.getSourceUrl();
178 int sourceLine = entry.sourceLocation.getLine();
179 int sourceColumn = entry.sourceLocation.getColumn();
180 String sourceName = entry.sourceLocation.getSourceName();
181
182 int sourceUrlIndex = indexOf(sourceUrlList, sourceUrl, sourceUrlMap);
183 encodeVLQ(output, sourceUrlIndex - previousSourceUrlIndex);
184 encodeVLQ(output, sourceLine - previousSourceLine);
185 encodeVLQ(output, sourceColumn - previousSourceColumn);
186
187 if (sourceName != null) {
188 int sourceNameIndex = indexOf(sourceNameList, sourceName, sourceNameMap);
189 encodeVLQ(output, sourceNameIndex - previousSourceNameIndex);
190 }
191
192 // Update previous source location to ensure the next indices are relative
193 // to those if [entry.sourceLocation].
194 updatePreviousSourceLocation(entry.sourceLocation);
195 }
196
197 int indexOf(List<String> list, String value, Map<String, int> map) {
198 return map.putIfAbsent(value, () {
199 int index = list.length;
200 list.add(value);
201 return index;
202 });
203 }
204
205 static void encodeVLQ(StringBuffer output, int value) {
206 int signBit = 0;
207 if (value < 0) {
208 signBit = 1;
209 value = -value;
210 }
211 value = (value << 1) | signBit;
212 do {
213 int digit = value & VLQ_BASE_MASK;
214 value >>= VLQ_BASE_SHIFT;
215 if (value > 0) {
216 digit |= VLQ_CONTINUATION_BIT;
217 }
218 output.write(BASE64_DIGITS[digit]);
219 } while (value > 0);
220 }
221 }
222
223 class SourceMapEntry {
224 SourceFileLocation sourceLocation;
225 int targetOffset;
226
227 SourceMapEntry(this.sourceLocation, this.targetOffset);
228 }
229
230 abstract class SourceFileLocation {
231 SourceFile sourceFile;
232
233 SourceFileLocation(this.sourceFile) {
234 assert(isValid());
235 }
236
237 int line;
238
239 int get offset;
240
241 String getSourceUrl() => sourceFile.filename;
242
243 int getLine() {
244 if (line == null) line = sourceFile.getLine(offset);
245 return line;
246 }
247
248 int getColumn() => sourceFile.getColumn(getLine(), offset);
249
250 String getSourceName();
251
252 bool isValid() => offset < sourceFile.length;
253 }
254
255 class TokenSourceFileLocation extends SourceFileLocation {
256 final Token token;
257 final String name;
258
259 TokenSourceFileLocation(SourceFile sourceFile, this.token, this.name)
260 : super(sourceFile);
261
262 int get offset => token.charOffset;
263
264 String getSourceName() {
265 return name;
266 }
267 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698