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

Side by Side Diff: pkg/source_maps/lib/parser.dart

Issue 372153002: Moving logic for writing source maps from SourceMapBuilder into the Mapping class. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 5 months 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
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 /// Contains the top-level function to parse source maps version 3. 5 /// Contains the top-level function to parse source maps version 3.
6 library source_maps.parser; 6 library source_maps.parser;
7 7
8 import 'dart:collection';
8 import 'dart:convert'; 9 import 'dart:convert';
9 10
11 import 'builder.dart';
10 import 'span.dart'; 12 import 'span.dart';
11 import 'src/utils.dart'; 13 import 'src/utils.dart';
12 import 'src/vlq.dart'; 14 import 'src/vlq.dart';
13 15
14 /// Parses a source map directly from a json string. 16 /// Parses a source map directly from a json string.
15 // TODO(sigmund): evaluate whether other maps should have the json parsed, or 17 // TODO(sigmund): evaluate whether other maps should have the json parsed, or
16 // the string represenation. 18 // the string represenation.
17 Mapping parse(String jsonMap, {Map<String, Map> otherMaps}) => 19 Mapping parse(String jsonMap, {Map<String, Map> otherMaps}) =>
18 parseJson(JSON.decode(jsonMap), otherMaps: otherMaps); 20 parseJson(JSON.decode(jsonMap), otherMaps: otherMaps);
19 21
(...skipping 14 matching lines...) Expand all
34 map.containsKey('names')) { 36 map.containsKey('names')) {
35 throw new FormatException('map containing "sections" ' 37 throw new FormatException('map containing "sections" '
36 'cannot contain "mappings", "sources", or "names".'); 38 'cannot contain "mappings", "sources", or "names".');
37 } 39 }
38 return new MultiSectionMapping.fromJson(map['sections'], otherMaps); 40 return new MultiSectionMapping.fromJson(map['sections'], otherMaps);
39 } 41 }
40 return new SingleMapping.fromJson(map); 42 return new SingleMapping.fromJson(map);
41 } 43 }
42 44
43 45
44 /// A mapping parsed our of a source map. 46 /// A mapping parsed out of a source map.
45 abstract class Mapping { 47 abstract class Mapping {
46 Span spanFor(int line, int column, {Map<String, SourceFile> files}); 48 Span spanFor(int line, int column, {Map<String, SourceFile> files});
47 49
48 Span spanForLocation(Location loc, {Map<String, SourceFile> files}) { 50 Span spanForLocation(Location loc, {Map<String, SourceFile> files}) {
49 return spanFor(loc.line, loc.column, files: files); 51 return spanFor(loc.line, loc.column, files: files);
50 } 52 }
51 } 53 }
52 54
53 /// A meta-level map containing sections. 55 /// A meta-level map containing sections.
54 class MultiSectionMapping extends Mapping { 56 class MultiSectionMapping extends Mapping {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 ..write(':') 126 ..write(':')
125 ..write(_maps[i]) 127 ..write(_maps[i])
126 ..write(')'); 128 ..write(')');
127 } 129 }
128 buff.write(']'); 130 buff.write(']');
129 return buff.toString(); 131 return buff.toString();
130 } 132 }
131 } 133 }
132 134
133 /// A map containing direct source mappings. 135 /// A map containing direct source mappings.
134 // TODO(sigmund): integrate mapping and sourcemap builder? 136 // TODO(sigmund): integrate mapping and sourcemap builder?
Siggi Cherem (dart-lang) 2014/07/08 00:31:00 delete TODO :-)
tjblasi 2014/07/08 16:36:19 Done.
135 class SingleMapping extends Mapping { 137 class SingleMapping extends Mapping {
136 /// Url of the target file. 138 /// Url of the target file.
137 final String targetUrl; 139 final String targetUrl;
138 140
139 /// Source urls used in the mapping, indexed by id. 141 /// Source urls used in the mapping, indexed by id.
140 final List<String> urls; 142 final List<String> urls;
141 143
142 /// Source names used in the mapping, indexed by id. 144 /// Source names used in the mapping, indexed by id.
143 final List<String> names; 145 final List<String> names;
144 146
145 /// Entries indicating the beginning of each span. 147 /// Entries indicating the beginning of each span.
146 final List<TargetLineEntry> lines = <TargetLineEntry>[]; 148 final List<TargetLineEntry> lines = <TargetLineEntry>[];
147 149
150 SingleMapping._internal(this.targetUrl, this.urls, this.names);
151
152 factory SingleMapping.fromBuilder(SourceMapBuilder builder, [String fileUrl]) {
Siggi Cherem (dart-lang) 2014/07/08 00:31:01 how about switching to take a list of entries inst
tjblasi 2014/07/08 16:36:20 Done.
153 List<Entry> sourceEntries = builder.entries;
154 List<TargetLineEntry> lines = [];
Siggi Cherem (dart-lang) 2014/07/08 00:31:01 style nit: use 'var' for local variables
tjblasi 2014/07/08 16:36:20 Done.
155
156 // Indices associated with file urls that will be part of the source map. We
157 // use a linked hash-map so that `_urls.keys[_urls[u]] == u`
158 Map<String, int> urls = new LinkedHashMap<String, int>();
Siggi Cherem (dart-lang) 2014/07/08 00:31:00 same here and below (var urls = ...)
tjblasi 2014/07/08 16:36:20 Done.
159
160 // Indices associated with identifiers that will be part of the source map.
161 // We use a linked hash-map so that `_names.keys[_names[n]] == n`
162 Map<String, int> names = new LinkedHashMap<String, int>();
163
164 // The encoding needs to be sorted by the target offsets.
165 sourceEntries.sort();
Siggi Cherem (dart-lang) 2014/07/08 00:31:00 since sorting modifies the list in-place, we might
tjblasi 2014/07/08 16:36:20 Done.
166 for (var sourceEntry in sourceEntries) {
167 if (lines.isEmpty || sourceEntry.target.line > lines.last.line) {
168 lines.add(new TargetLineEntry(sourceEntry.target.line, []));
169 }
170
171 if (sourceEntry.source == null) {
172 lines.last.entries.add(new TargetEntry(sourceEntry.target.column));
Siggi Cherem (dart-lang) 2014/07/08 00:31:01 since `lines.last` can be expensive, maybe we coul
tjblasi 2014/07/08 16:36:20 Done.
173 } else {
174 var urlId = urls.putIfAbsent(sourceEntry.source.sourceUrl, () => urls.le ngth);
Siggi Cherem (dart-lang) 2014/07/08 00:31:00 nit: 80 columns (here and elsewhere)
tjblasi 2014/07/08 16:36:20 Done.
175 var srcNameId = sourceEntry.identifierName != null ?
Siggi Cherem (dart-lang) 2014/07/08 00:31:01 minor nit: maybe swapping this branch might make i
tjblasi 2014/07/08 16:36:20 Done.
176 names.putIfAbsent(sourceEntry.identifierName, () => names.length) : null;
177 lines.last.entries.add(new TargetEntry(
178 sourceEntry.target.column,
179 urlId,
180 sourceEntry.source.line,
181 sourceEntry.source.column,
182 srcNameId));
183 }
184 }
185 var mapping = new SingleMapping._internal(fileUrl, urls.keys.toList(), names .keys.toList());
186 mapping.lines.addAll(lines);
Siggi Cherem (dart-lang) 2014/07/08 00:31:01 nit: maybe move the default initialization above t
tjblasi 2014/07/08 16:36:20 Done.
187 return mapping;
188 }
189
148 SingleMapping.fromJson(Map map) 190 SingleMapping.fromJson(Map map)
149 : targetUrl = map['file'], 191 : targetUrl = map['file'],
150 // TODO(sigmund): add support for 'sourceRoot' 192 // TODO(sigmund): add support for 'sourceRoot'
151 urls = map['sources'], 193 urls = map['sources'],
152 names = map['names'] { 194 names = map['names'] {
153 int line = 0; 195 int line = 0;
154 int column = 0; 196 int column = 0;
155 int srcUrlId = 0; 197 int srcUrlId = 0;
156 int srcLine = 0; 198 int srcLine = 0;
157 int srcColumn = 0; 199 int srcColumn = 0;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 srcNameId)); 250 srcNameId));
209 } 251 }
210 } 252 }
211 if (tokenizer.nextKind.isNewSegment) tokenizer._consumeNewSegment(); 253 if (tokenizer.nextKind.isNewSegment) tokenizer._consumeNewSegment();
212 } 254 }
213 if (!entries.isEmpty) { 255 if (!entries.isEmpty) {
214 lines.add(new TargetLineEntry(line, entries)); 256 lines.add(new TargetLineEntry(line, entries));
215 } 257 }
216 } 258 }
217 259
260 /// Encodes the Mapping mappings as a json map.
261 Map toMap() {
Siggi Cherem (dart-lang) 2014/07/08 00:31:00 suggestion: maybe rename as toJson (to make it con
tjblasi 2014/07/08 16:36:20 Done.
262 var buff = new StringBuffer();
263 var line = 0;
264 var column = 0;
265 var srcLine = 0;
266 var srcColumn = 0;
267 var srcUrlId = 0;
268 var srcNameId = 0;
269 var first = true;
270
271 for (var entry in lines) {
272 int nextLine = entry.line;
273 if (nextLine > line) {
274 for (int i = line; i < nextLine; ++i) {
275 buff.write(';');
276 }
277 line = nextLine;
278 column = 0;
279 first = true;
280 }
281
282 for (var segment in entry.entries) {
283 if (!first) buff.write(',');
284 first = false;
285 column = _append(buff, column, segment.column);
286
287 // Encoding can be just the column offset if there is no source
288 // information.
289 var newUrlId = segment.sourceUrlId;
290 if (newUrlId == null) continue;
291 srcUrlId = _append(buff, srcUrlId, newUrlId);
292 srcLine = _append(buff, srcLine, segment.sourceLine);
293 srcColumn = _append(buff, srcColumn, segment.sourceColumn);
294
295 if (segment.sourceNameId == null) continue;
296 srcNameId = _append(buff, srcNameId, segment.sourceNameId);
297 }
298 }
299
300 var result = {
301 'version': 3,
302 'sourceRoot': '',
303 'sources': urls,
304 'names' : names,
305 'mappings' : buff.toString()
306 };
307 if (targetUrl != null) {
308 result['file'] = targetUrl;
309 }
310 return result;
311 }
312
313 /// Appends to [buff] a VLQ encoding of [newValue] using the difference
314 /// between [oldValue] and [newValue]
315 static int _append(StringBuffer buff, int oldValue, int newValue) {
316 buff.writeAll(encodeVlq(newValue - oldValue));
317 return newValue;
318 }
319
218 _segmentError(int seen, int line) => new StateError( 320 _segmentError(int seen, int line) => new StateError(
219 'Invalid entry in sourcemap, expected 1, 4, or 5' 321 'Invalid entry in sourcemap, expected 1, 4, or 5'
220 ' values, but got $seen.\ntargeturl: $targetUrl, line: $line'); 322 ' values, but got $seen.\ntargeturl: $targetUrl, line: $line');
221 323
222 /// Returns [TargetLineEntry] which includes the location in the target [line] 324 /// Returns [TargetLineEntry] which includes the location in the target [line]
223 /// number. In particular, the resulting entry is the last entry whose line 325 /// number. In particular, the resulting entry is the last entry whose line
224 /// number is lower or equal to [line]. 326 /// number is lower or equal to [line].
225 TargetLineEntry _findLine(int line) { 327 TargetLineEntry _findLine(int line) {
226 int index = binarySearch(lines, (e) => e.line > line); 328 int index = binarySearch(lines, (e) => e.line > line);
227 return (index <= 0) ? null : lines[index - 1]; 329 return (index <= 0) ? null : lines[index - 1];
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 static const _TokenKind EOF = const _TokenKind(isEof: true); 483 static const _TokenKind EOF = const _TokenKind(isEof: true);
382 static const _TokenKind VALUE = const _TokenKind(); 484 static const _TokenKind VALUE = const _TokenKind();
383 final bool isNewLine; 485 final bool isNewLine;
384 final bool isNewSegment; 486 final bool isNewSegment;
385 final bool isEof; 487 final bool isEof;
386 bool get isValue => !isNewLine && !isNewSegment && !isEof; 488 bool get isValue => !isNewLine && !isNewSegment && !isEof;
387 489
388 const _TokenKind( 490 const _TokenKind(
389 {this.isNewLine: false, this.isNewSegment: false, this.isEof: false}); 491 {this.isNewLine: false, this.isNewSegment: false, this.isEof: false});
390 } 492 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698