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

Side by Side Diff: pkg/codegen/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: changes alone (patchset 1 has the existing code, in the new location) 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library codegen.printer;
6
7 import 'package:source_maps/source_maps.dart';
8
9 /**
10 * Helper class to format generated code and keep track of source map
11 * information.
12 */
13 class CodePrinter {
14
15 /**
16 * Items recoded by this printer, which can be [String] literals,
17 * other printing helpers such as [Declarations] and [CodePrinter],
18 * and source map information like [Location] and [Span].
19 */
20 List _items = [];
21
22 /** Internal buffer to merge consecutive strings added to this printer. */
23 StringBuffer _buff;
24
25 /** Current indentation, which can be updated from outside this class. */
26 int indent = 0;
27
28 /**
29 * Item used to indicate that the following item is copied from the original
30 * source code, and hence we should preserve source-maps on every new line.
31 */
32 static final _ORIGINAL = new Object();
33
34 CodePrinter(this.indent);
35
36 /**
37 * Adds [object] to this printer. [object] can be a [String], [Declarations],
38 * or a [CodePrinter]. If [object] is a [String], the value is appended
39 * directly, without doing any formatting changes. If you wish to add a line
40 * of code with automatic indentation, use [addLine] instead. [Declarations]
41 * and [CodePrinter] are not processed until [build] gets called later on.
42 * We ensure that [build] emits every object in the order that they were added
43 * to this printer.
44 *
45 * The [location] and [span] parameters indicate the corresponding source map
46 * location of [object] in the original input. Only one, [location] or
47 * [span], should be provided at a time.
48 *
49 * Indicate [isOriginal] when [object] is copied directly from the user code.
50 * Setting [isOriginal] will make this printer propagate source map locations
51 * on every line-break.
52 */
53 void add(object, {Location location, Span span, bool isOriginal: false}) {
54 if (object is! String || location != null || span != null || isOriginal) {
55 _flush();
56 assert(location == null || span == null);
57 if (location != null) _items.add(location);
58 if (span != null) _items.add(span);
59 if (isOriginal) _items.add(_ORIGINAL);
60 }
61
62 if (object is String) {
63 _appendString(object);
64 } else {
65 _items.add(object);
66 }
67 }
68
69 /** Append `2 * indent` spaces to this printer. */
70 void insertIndent() => _indent(indent);
71
72 /**
73 * Add a [line], autoindenting to the current value of [indent]. Note,
74 * indentation is not inferred, so if a line opens or closes an indentation
75 * block, you need to also update [indent] accordingly. Also, indentation is
76 * not adapted for nested code printers. If you add a [CodePrinter] to this
77 * printer, its indentation is set separately and will not include any
78 * the indentation set here.
79 *
80 * The [location] and [span] parameters indicate the corresponding source map
81 * location of [object] in the original input. Only one, [location] or
82 * [span], should be provided at a time.
83 */
84 void addLine(String line, {Location location, Span span}) {
85 if (location != null || span != null) {
86 _flush();
87 assert(location == null || span == null);
88 if (location != null) _items.add(location);
89 if (span != null) _items.add(span);
90 }
91 if (line == null) return;
92 if (line != '') {
93 // We don't indent empty lines.
94 _indent(indent);
95 _appendString(line);
96 }
97 _appendString('\n');
98 }
99
100 /** Appends a string merging it with any previous strings, if possible. */
101 void _appendString(String s) {
102 if (_buff == null) _buff = new StringBuffer();
103 _buff.write(s);
104 }
105
106 /** Adds all of the current [_buff] contents as a string item. */
107 void _flush() {
108 if (_buff != null) {
109 _items.add(_buff.toString());
110 _buff = null;
111 }
112 }
113
114 void _indent(int indent) {
115 for (int i = 0; i < indent; i++) _appendString(' ');
116 }
117
118 /**
119 * Returns a string representation of all the contents appended to this
120 * printer, including source map location tokens.
121 */
122 String toString() {
123 _flush();
124 return (new StringBuffer()..writeAll(_items)).toString();
125 }
126
127 /** [Printer] used during the last call to [build], if any. */
128 Printer _printer;
129
130 /** Returns the text produced after calling [build]. */
131 String get text => _printer.text;
132
133 /** Returns the source-map information produced after calling [build]. */
134 String get map => _printer.map;
135
136 /**
137 * Builds the output of this printer and source map information. After calling
138 * this function, you can use [text] and [map] to retrieve the geenrated code
139 * and source map information, respectively.
140 */
141 void build(String filename) {
142 _build(_printer = new Printer(filename));
143 }
144
145 void _build(Printer printer) {
146 _flush();
147 bool propagate = false;
148 for (var item in _items) {
149 if (item is Declarations) {
150 item._build(printer);
151 } else if (item is CodePrinter) {
152 item._build(printer);
153 } else if (item is String) {
154 printer.add(item, projectMarks: propagate);
155 propagate = false;
156 } else if (item is Location || item is Span) {
157 printer.mark(item);
158 } else if (item == _ORIGINAL) {
159 // we insert booleans when we are about to quote text that was copied
160 // from the original source. In such case, we will propagate marks on
161 // every new-line.
162 propagate = true;
163 } else {
164 throw new UnsupportedError('Unknown item type: $item');
165 }
166 }
167 }
168 }
169
170 /** A declaration of a field or local variable. */
171 class Declaration implements Comparable {
172 final String type;
173 final String name;
174 final Span sourceSpan;
175 final String initializer;
176
177 Declaration(this.type, this.name, this.sourceSpan, [this.initializer]);
178
179 /**
180 * Sort declarations by type, so they can be merged together in a declaration
181 * group.
182 */
183 int compareTo(Declaration other) {
184 if (type != other.type) return type.compareTo(other.type);
185 return name.compareTo(other.name);
186 }
187 }
188
189 /** A set of declarations grouped together. */
190 class Declarations {
191
192 /** All declarations in this group. */
193 final List<Declaration> declarations = <Declaration>[];
194
195 /** Indentation associated with this declaration group. */
196 final int indent;
197
198 /** Whether these declarations are local variables or fields in a class. */
199 final bool isLocal;
200
201 /** Whether types should be prefixed with the "static" keyword. */
202 final bool staticKeyword;
203
204 Declarations(this.indent, {this.isLocal: false, this.staticKeyword: false});
205
206 /** Add a declaration to this group. */
207 void add(String type, String identifier, Span sourceSpan, [String init]) {
208 declarations.add(
209 new Declaration(isLocal ? 'var' : type, identifier, sourceSpan, init));
210 }
211
212 String toString() {
213 var printer = new Printer(null);
214 _build(printer);
215 return printer.text;
216 }
217
218 void _build(Printer printer) {
219 if (declarations.length == 0) return;
220 declarations.sort();
221 var lastType = null;
222 printer.addSpaces(2 * indent);
223 for (var d in declarations) {
224 if (d.type != lastType) {
225 if (lastType != null) {
226 printer.add(';\n');
227 printer.addSpaces(2 * indent);
228 }
229 if (staticKeyword) printer.add('static ');
230 printer.add(d.type);
231 lastType = d.type;
232 } else {
233 printer.add(',');
234 }
235 printer.add(' ');
236 if (d.sourceSpan != null) printer.mark(d.sourceSpan);
237 printer.add(d.name);
238 if (d.initializer != null) {
239 printer..add(' = ')..add(d.initializer);
240 }
241 }
242 printer.add(';\n');
243 }
244 }
245
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698