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

Side by Side Diff: pkg/source_maps/lib/printer.dart

Issue 814113004: Pull args, intl, logging, shelf, and source_maps out of the SDK. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Also csslib. Created 6 years 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
« no previous file with comments | « pkg/source_maps/lib/parser.dart ('k') | pkg/source_maps/lib/refactor.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) 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 /// Contains a code printer that generates code by recording the source maps.
6 library source_maps.printer;
7
8 import 'package:source_span/source_span.dart';
9
10 import 'builder.dart';
11 import 'src/source_map_span.dart';
12
13 const int _LF = 10;
14 const int _CR = 13;
15
16 /// A simple printer that keeps track of offset locations and records source
17 /// maps locations.
18 class Printer {
19 final String filename;
20 final StringBuffer _buff = new StringBuffer();
21 final SourceMapBuilder _maps = new SourceMapBuilder();
22 String get text => _buff.toString();
23 String get map => _maps.toJson(filename);
24
25 /// Current source location mapping.
26 SourceLocation _loc;
27
28 /// Current line in the buffer;
29 int _line = 0;
30
31 /// Current column in the buffer.
32 int _column = 0;
33
34 Printer(this.filename);
35
36 /// Add [str] contents to the output, tracking new lines to track correct
37 /// positions for span locations. When [projectMarks] is true, this method
38 /// adds a source map location on each new line, projecting that every new
39 /// line in the target file (printed here) corresponds to a new line in the
40 /// source file.
41 void add(String str, {projectMarks: false}) {
42 var chars = str.runes.toList();
43 var length = chars.length;
44 for (int i = 0; i < length; i++) {
45 var c = chars[i];
46 if (c == _LF || (c == _CR && (i + 1 == length || chars[i + 1] != _LF))) {
47 // Return not followed by line-feed is treated as a new line.
48 _line++;
49 _column = 0;
50 if (projectMarks && _loc != null) {
51 if (_loc is FileLocation) {
52 var file = (_loc as FileLocation).file;
53 mark(file.location(file.getOffset(_loc.line + 1)));
54 } else {
55 mark(new SourceLocation(0,
56 sourceUrl: _loc.sourceUrl, line: _loc.line + 1, column: 0));
57 }
58 }
59 } else {
60 _column++;
61 }
62 }
63 _buff.write(str);
64 }
65
66
67 /// Append a [total] number of spaces in the target file. Typically used for
68 /// formatting indentation.
69 void addSpaces(int total) {
70 for (int i = 0; i < total; i++) _buff.write(' ');
71 _column += total;
72 }
73
74 /// Marks that the current point in the target file corresponds to the [mark]
75 /// in the source file, which can be either a [SourceLocation] or a
76 /// [SourceSpan]. When the mark is a [SourceMapSpan] with `isIdentifier` set,
77 /// this also records the name of the identifier in the source map
78 /// information.
79 void mark(mark) {
80 var loc;
81 var identifier = null;
82 if (mark is SourceLocation) {
83 loc = mark;
84 } else if (mark is SourceSpan) {
85 loc = mark.start;
86 if (mark is SourceMapSpan && mark.isIdentifier) identifier = mark.text;
87 }
88 _maps.addLocation(
89 loc,
90 new SourceLocation(_buff.length, line: _line, column: _column),
91 identifier);
92 _loc = loc;
93 }
94 }
95
96 /// A more advanced printer that keeps track of offset locations to record
97 /// source maps, but additionally allows nesting of different kind of items,
98 /// including [NestedPrinter]s, and it let's you automatically indent text.
99 ///
100 /// This class is especially useful when doing code generation, where different
101 /// peices of the code are generated independently on separate printers, and are
102 /// finally put together in the end.
103 class NestedPrinter implements NestedItem {
104
105 /// Items recoded by this printer, which can be [String] literals,
106 /// [NestedItem]s, and source map information like [SourceLocation] and
107 /// [SourceSpan].
108 List _items = [];
109
110 /// Internal buffer to merge consecutive strings added to this printer.
111 StringBuffer _buff;
112
113 /// Current indentation, which can be updated from outside this class.
114 int indent;
115
116 /// Item used to indicate that the following item is copied from the original
117 /// source code, and hence we should preserve source-maps on every new line.
118 static final _ORIGINAL = new Object();
119
120 NestedPrinter([this.indent = 0]);
121
122 /// Adds [object] to this printer. [object] can be a [String],
123 /// [NestedPrinter], or anything implementing [NestedItem]. If [object] is a
124 /// [String], the value is appended directly, without doing any formatting
125 /// changes. If you wish to add a line of code with automatic indentation, use
126 /// [addLine] instead. [NestedPrinter]s and [NestedItem]s are not processed
127 /// until [build] gets called later on. We ensure that [build] emits every
128 /// object in the order that they were added to this printer.
129 ///
130 /// The [location] and [span] parameters indicate the corresponding source map
131 /// location of [object] in the original input. Only one, [location] or
132 /// [span], should be provided at a time.
133 ///
134 /// Indicate [isOriginal] when [object] is copied directly from the user code.
135 /// Setting [isOriginal] will make this printer propagate source map locations
136 /// on every line-break.
137 void add(object, {SourceLocation location, SourceSpan span,
138 bool isOriginal: false}) {
139 if (object is! String || location != null || span != null || isOriginal) {
140 _flush();
141 assert(location == null || span == null);
142 if (location != null) _items.add(location);
143 if (span != null) _items.add(span);
144 if (isOriginal) _items.add(_ORIGINAL);
145 }
146
147 if (object is String) {
148 _appendString(object);
149 } else {
150 _items.add(object);
151 }
152 }
153
154 /// Append `2 * indent` spaces to this printer.
155 void insertIndent() => _indent(indent);
156
157 /// Add a [line], autoindenting to the current value of [indent]. Note,
158 /// indentation is not inferred from the contents added to this printer. If a
159 /// line starts or ends an indentation block, you need to also update [indent]
160 /// accordingly. Also, indentation is not adapted for nested printers. If
161 /// you add a [NestedPrinter] to this printer, its indentation is set
162 /// separately and will not include any the indentation set here.
163 ///
164 /// The [location] and [span] parameters indicate the corresponding source map
165 /// location of [object] in the original input. Only one, [location] or
166 /// [span], should be provided at a time.
167 void addLine(String line, {SourceLocation location, SourceSpan span}) {
168 if (location != null || span != null) {
169 _flush();
170 assert(location == null || span == null);
171 if (location != null) _items.add(location);
172 if (span != null) _items.add(span);
173 }
174 if (line == null) return;
175 if (line != '') {
176 // We don't indent empty lines.
177 _indent(indent);
178 _appendString(line);
179 }
180 _appendString('\n');
181 }
182
183 /// Appends a string merging it with any previous strings, if possible.
184 void _appendString(String s) {
185 if (_buff == null) _buff = new StringBuffer();
186 _buff.write(s);
187 }
188
189 /// Adds all of the current [_buff] contents as a string item.
190 void _flush() {
191 if (_buff != null) {
192 _items.add(_buff.toString());
193 _buff = null;
194 }
195 }
196
197 void _indent(int indent) {
198 for (int i = 0; i < indent; i++) _appendString(' ');
199 }
200
201 /// Returns a string representation of all the contents appended to this
202 /// printer, including source map location tokens.
203 String toString() {
204 _flush();
205 return (new StringBuffer()..writeAll(_items)).toString();
206 }
207
208 /// [Printer] used during the last call to [build], if any.
209 Printer printer;
210
211 /// Returns the text produced after calling [build].
212 String get text => printer.text;
213
214 /// Returns the source-map information produced after calling [build].
215 String get map => printer.map;
216
217 /// Builds the output of this printer and source map information. After
218 /// calling this function, you can use [text] and [map] to retrieve the
219 /// geenrated code and source map information, respectively.
220 void build(String filename) {
221 writeTo(printer = new Printer(filename));
222 }
223
224 /// Implements the [NestedItem] interface.
225 void writeTo(Printer printer) {
226 _flush();
227 bool propagate = false;
228 for (var item in _items) {
229 if (item is NestedItem) {
230 item.writeTo(printer);
231 } else if (item is String) {
232 printer.add(item, projectMarks: propagate);
233 propagate = false;
234 } else if (item is SourceLocation || item is SourceSpan) {
235 printer.mark(item);
236 } else if (item == _ORIGINAL) {
237 // we insert booleans when we are about to quote text that was copied
238 // from the original source. In such case, we will propagate marks on
239 // every new-line.
240 propagate = true;
241 } else {
242 throw new UnsupportedError('Unknown item type: $item');
243 }
244 }
245 }
246 }
247
248 /// An item added to a [NestedPrinter].
249 abstract class NestedItem {
250 /// Write the contents of this item into [printer].
251 void writeTo(Printer printer);
252 }
OLDNEW
« no previous file with comments | « pkg/source_maps/lib/parser.dart ('k') | pkg/source_maps/lib/refactor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698