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

Unified Diff: pkg/source_maps/lib/printer.dart

Issue 22396004: Make observable transform a barback transform. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/pkg.status ('k') | pkg/source_maps/lib/refactor.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/source_maps/lib/printer.dart
diff --git a/pkg/source_maps/lib/printer.dart b/pkg/source_maps/lib/printer.dart
index 333aadcd429c4e951c0aef2c78a2f47db287e442..95539d2b77bf549a41d81bc90208581a71aa1260 100644
--- a/pkg/source_maps/lib/printer.dart
+++ b/pkg/source_maps/lib/printer.dart
@@ -12,8 +12,8 @@ import 'span.dart';
const int _LF = 10;
const int _CR = 13;
-/// A printer that keeps track of offset locations and records source maps
-/// locations.
+/// A simple printer that keeps track of offset locations and records source
+/// maps locations.
class Printer {
final String filename;
final StringBuffer _buff = new StringBuffer();
@@ -87,3 +87,159 @@ class Printer {
_loc = loc;
}
}
+
+/// A more advanced printer that keeps track of offset locations to record
+/// source maps, but additionally allows nesting of different kind of items,
+/// including [NestedPrinter]s, and it let's you automatically indent text.
+///
+/// This class is especially useful when doing code generation, where different
+/// peices of the code are generated independently on separate printers, and are
+/// finally put together in the end.
+class NestedPrinter implements NestedItem {
+
+ /// Items recoded by this printer, which can be [String] literals,
+ /// [NestedItem]s, and source map information like [Location] and [Span].
+ List _items = [];
+
+ /// Internal buffer to merge consecutive strings added to this printer.
+ StringBuffer _buff;
+
+ /// Current indentation, which can be updated from outside this class.
+ int indent;
+
+ /// Item used to indicate that the following item is copied from the original
+ /// source code, and hence we should preserve source-maps on every new line.
+ static final _ORIGINAL = new Object();
+
+ NestedPrinter([this.indent = 0]);
+
+ /// Adds [object] to this printer. [object] can be a [String],
+ /// [NestedPrinter], or anything implementing [NestedItem]. If [object] is a
+ /// [String], the value is appended directly, without doing any formatting
+ /// changes. If you wish to add a line of code with automatic indentation, use
+ /// [addLine] instead. [NestedPrinter]s and [NestedItem]s are not processed
+ /// until [build] gets called later on. We ensure that [build] emits every
+ /// object in the order that they were added to this printer.
+ ///
+ /// The [location] and [span] parameters indicate the corresponding source map
+ /// location of [object] in the original input. Only one, [location] or
+ /// [span], should be provided at a time.
+ ///
+ /// Indicate [isOriginal] when [object] is copied directly from the user code.
+ /// Setting [isOriginal] will make this printer propagate source map locations
+ /// on every line-break.
+ void add(object, {Location location, Span span, bool isOriginal: false}) {
+ if (object is! String || location != null || span != null || isOriginal) {
+ _flush();
+ assert(location == null || span == null);
+ if (location != null) _items.add(location);
+ if (span != null) _items.add(span);
+ if (isOriginal) _items.add(_ORIGINAL);
+ }
+
+ if (object is String) {
+ _appendString(object);
+ } else {
+ _items.add(object);
+ }
+ }
+
+ /// Append `2 * indent` spaces to this printer.
+ void insertIndent() => _indent(indent);
+
+ /// Add a [line], autoindenting to the current value of [indent]. Note,
+ /// indentation is not inferred from the contents added to this printer. If a
+ /// line starts or ends an indentation block, you need to also update [indent]
+ /// accordingly. Also, indentation is not adapted for nested printers. If
+ /// you add a [NestedPrinter] to this printer, its indentation is set
+ /// separately and will not include any the indentation set here.
+ ///
+ /// The [location] and [span] parameters indicate the corresponding source map
+ /// location of [object] in the original input. Only one, [location] or
+ /// [span], should be provided at a time.
+ void addLine(String line, {Location location, Span span}) {
+ if (location != null || span != null) {
+ _flush();
+ assert(location == null || span == null);
+ if (location != null) _items.add(location);
+ if (span != null) _items.add(span);
+ }
+ if (line == null) return;
+ if (line != '') {
+ // We don't indent empty lines.
+ _indent(indent);
+ _appendString(line);
+ }
+ _appendString('\n');
+ }
+
+ /// Appends a string merging it with any previous strings, if possible.
+ void _appendString(String s) {
+ if (_buff == null) _buff = new StringBuffer();
+ _buff.write(s);
+ }
+
+ /// Adds all of the current [_buff] contents as a string item.
+ void _flush() {
+ if (_buff != null) {
+ _items.add(_buff.toString());
+ _buff = null;
+ }
+ }
+
+ void _indent(int indent) {
+ for (int i = 0; i < indent; i++) _appendString(' ');
+ }
+
+ /// Returns a string representation of all the contents appended to this
+ /// printer, including source map location tokens.
+ String toString() {
+ _flush();
+ return (new StringBuffer()..writeAll(_items)).toString();
+ }
+
+ /// [Printer] used during the last call to [build], if any.
+ Printer printer;
+
+ /// Returns the text produced after calling [build].
+ String get text => printer.text;
+
+ /// Returns the source-map information produced after calling [build].
+ String get map => printer.map;
+
+ /// Builds the output of this printer and source map information. After
+ /// calling this function, you can use [text] and [map] to retrieve the
+ /// geenrated code and source map information, respectively.
+ void build(String filename) {
+ writeTo(printer = new Printer(filename));
+ }
+
+ /// Implements the [NestedItem] interface.
+ void writeTo(Printer printer) {
+ _flush();
+ bool propagate = false;
+ for (var item in _items) {
+ if (item is NestedItem) {
+ item.writeTo(printer);
+ } else if (item is String) {
+ printer.add(item, projectMarks: propagate);
+ propagate = false;
+ } else if (item is Location || item is Span) {
+ printer.mark(item);
+ } else if (item == _ORIGINAL) {
+ // we insert booleans when we are about to quote text that was copied
+ // from the original source. In such case, we will propagate marks on
+ // every new-line.
+ propagate = true;
+ } else {
+ throw new UnsupportedError('Unknown item type: $item');
+ }
+ }
+ }
+}
+
+/// An item added to a [NestedPrinter].
+abstract class NestedItem {
+ /// Write the contents of this item into [printer].
+ void writeTo(Printer printer);
+}
« no previous file with comments | « pkg/pkg.status ('k') | pkg/source_maps/lib/refactor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698