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

Side by Side Diff: lib/src/code_printer.dart

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

Powered by Google App Engine
This is Rietveld 408576698