blob: 333aadcd429c4e951c0aef2c78a2f47db287e442 [file] [log] [blame]
// 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;
}
}