| // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| /// Contains a code printer that generates code by recording the source maps. |
| library source_maps.printer; |
| |
| import 'dart:utf' show stringToCodepoints; |
| import 'builder.dart'; |
| import 'span.dart'; |
| |
| const int _LF = 10; |
| const int _CR = 13; |
| |
| /// A printer that keeps track of offset locations and records source maps |
| /// locations. |
| class Printer { |
| final String filename; |
| final StringBuffer _buff = new StringBuffer(); |
| final SourceMapBuilder _maps = new SourceMapBuilder(); |
| String get text => _buff.toString(); |
| String get map => _maps.toJson(filename); |
| |
| /// Current source location mapping. |
| Location _loc; |
| |
| /// Current line in the buffer; |
| int _line = 0; |
| |
| /// Current column in the buffer. |
| int _column = 0; |
| |
| Printer(this.filename); |
| |
| /// Add [str] contents to the output, tracking new lines to track correct |
| /// positions for span locations. When [projectMarks] is true, this method |
| /// adds a source map location on each new line, projecting that every new |
| /// line in the target file (printed here) corresponds to a new line in the |
| /// source file. |
| void add(String str, {projectMarks: false}) { |
| var chars = stringToCodepoints(str); |
| var length = chars.length; |
| for (int i = 0; i < length; i++) { |
| var c = chars[i]; |
| if (c == _LF || (c == _CR && (i + 1 == length || chars[i + 1] != _LF))) { |
| // Return not followed by line-feed is treated as a new line. |
| _line++; |
| _column = 0; |
| if (projectMarks && _loc != null) { |
| if (_loc is FixedLocation) { |
| mark(new FixedLocation(0, _loc.sourceUrl, _loc.line + 1, 0)); |
| } else if (_loc is FileLocation) { |
| var file = (_loc as FileLocation).file; |
| mark(new FileLocation(file, file.getOffset(_loc.line + 1, 0))); |
| } |
| } |
| } else { |
| _column++; |
| } |
| } |
| _buff.write(str); |
| } |
| |
| |
| /// Append a [total] number of spaces in the target file. Typically used for |
| /// formatting indentation. |
| void addSpaces(int total) { |
| for (int i = 0; i < total; i++) _buff.write(' '); |
| _column += total; |
| } |
| |
| /// Marks that the current point in the target file corresponds to the [mark] |
| /// in the source file, which can be either a [Location] or a [Span]. When the |
| /// mark is an identifier's Span, this also records the name of the identifier |
| /// in the source map information. |
| void mark(mark) { |
| var loc; |
| var identifier = null; |
| if (mark is Location) { |
| loc = mark; |
| } else if (mark is Span) { |
| loc = mark.start; |
| if (mark.isIdentifier) identifier = mark.text; |
| } |
| _maps.addLocation(loc, |
| new FixedLocation(_buff.length, null, _line, _column), identifier); |
| _loc = loc; |
| } |
| } |