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

Side by Side Diff: pkg/analyzer/lib/src/services/writer.dart

Issue 132383002: Line-breaking plumbing and bits and pieces. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 11 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
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library source_writer; 5 library source_writer;
6 6
7 7
8 class Line { 8 class Line {
9 9
10 final int lineLength;
11 final tokens = <LineToken>[]; 10 final tokens = <LineToken>[];
12 final bool useTabs; 11 final bool useTabs;
13 final int spacesPerIndent; 12 final int spacesPerIndent;
13 final LinePrinter printer;
14 14
15 Line({indent: 0, this.lineLength: 80, this.useTabs: false, 15 Line({indent: 0, this.useTabs: false, this.spacesPerIndent: 2,
16 this.spacesPerIndent: 2}) { 16 this.printer: const SimpleLinePrinter()}) {
17 if (indent > 0) { 17 if (indent > 0) {
18 _indent(indent); 18 _indent(indent);
19 } 19 }
20 } 20 }
21 21
22 void addSpace() { 22 void addSpace() {
23 addSpaces(1); 23 addSpaces(1);
24 } 24 }
25 25
26 void addSpaces(int n) { 26 void addSpaces(int n, {breakWeight: DEFAULT_SPACE_WEIGHT}) {
27 if (n > 0) { 27 if (n > 0) {
28 tokens.add(new SpaceToken(n)); 28 tokens.add(new SpaceToken(n, breakWeight: breakWeight));
29 } 29 }
30 } 30 }
31 31
32 void addToken(LineToken token) { 32 void addToken(LineToken token) {
33 tokens.add(token); 33 tokens.add(token);
34 } 34 }
35 35
36 bool isWhitespace() => tokens.every((tok) => tok is SpaceToken); 36 bool isWhitespace() => tokens.every((tok) => tok is SpaceToken);
37 37
38 void _indent(int n) { 38 void _indent(int n) {
39 tokens.add(useTabs ? new TabToken(n) : new SpaceToken(n * spacesPerIndent)); 39 tokens.add(useTabs ? new TabToken(n) : new SpaceToken(n * spacesPerIndent));
40 } 40 }
41 41
42 String toString() { 42 String toString() => printer.printLine(this);
43
44 }
45
46
47 /// Base class for line printers
48 abstract class LinePrinter {
49
50 const LinePrinter();
51
52 /// Convert this [line] to a [String] representation.
53 String printLine(Line line);
54 }
55
56
57 /// A simple line breaking [LinePrinter]
58 class SimpleLineBreaker extends LinePrinter {
59
60 final chunks = <Chunk>[];
61 final int maxLength;
62
63 SimpleLineBreaker(this.maxLength);
64
65 String printLine(Line line) {
66 //TODO(pquitslund): implement
67 }
68
69 List<Chunk> breakLine(Line line) {
Brian Wilkerson 2014/01/09 19:29:24 Try as I might, I don't understand how this method
pquitslund 2014/01/09 23:04:12 Ah yes. 'tent' was short-hand for 'tentative'. A
70 var chunks = <Chunk>[];
71 var current = new Chunk(maxLength: maxLength);
72 var tent = new Chunk(maxLength: maxLength);
73
74 line.tokens.forEach((tok) {
75
76 if (goodStart(tok, tent)) {
77 if (current.fits(tent)) {
78 current.add(tent);
79 } else {
80 if (current.length > 0) {
81 chunks.add(current);
82 }
83 current = tent;
84 }
85 tent = new Chunk(start: tok, maxLength: maxLength - current.length);
86 } else {
87 if (tent.fits(tok)) {
88 tent.add(tok);
89 } else {
90 current.add(tent);
91 if (current.length > 0) {
92 chunks.add(current);
93 current = new Chunk(maxLength: maxLength);
94 }
95 tent = new Chunk(maxLength: maxLength);
96 tent.add(tok);
97 }
98 }
99
100 });
101
102 current.add(tent);
103 if (current.length > 0) {
104 chunks.add(current);
105 }
106 return chunks;
107 }
108
109 bool goodStart(LineToken tok, Chunk tent) =>
110 tok is SpaceToken && tok.breakWeight >= tent.start.breakWeight;
111
112 }
113
114
115 /// Special token indicating a line start
116 final LINE_START = new SpaceToken(0);
117
118 const DEFAULT_SPACE_WEIGHT = -1;
119
120 /// Simple non-breaking printer
121 class SimpleLinePrinter extends LinePrinter {
122
123 const SimpleLinePrinter();
124
125 String printLine(Line line) {
43 var buffer = new StringBuffer(); 126 var buffer = new StringBuffer();
44 tokens.forEach((tok) => buffer.write(tok.toString())); 127 line.tokens.forEach((tok) => buffer.write(tok.toString()));
45 return buffer.toString(); 128 return buffer.toString();
46 } 129 }
47 130
48 } 131 }
49 132
50 133
51 class LineToken { 134 /// Describes a piece of text in a [Line].
135 abstract class LineText {
136 int get length;
137 void addTo(Chunk chunk);
138 }
139
140
141 /// A working piece of text used in calculating line breaks
142 class Chunk implements LineText {
143
144 final buffer = new StringBuffer();
145
146 int maxLength;
147 SpaceToken start;
148
149 Chunk({this.start, this.maxLength}) {
150 if (start == null) {
151 start = LINE_START;
152 }
153 }
154
155 bool fits(LineText text) => length + text.length < maxLength;
156
157 int get length => start.value.length + buffer.length;
158
159 void add(LineText text) {
160 text.addTo(this);
161 }
162
163 String toString() => buffer.toString().trim();
164
165 void addTo(Chunk chunk) {
166 chunk.buffer.write(start.value);
167 chunk.buffer.write(buffer.toString());
168 }
169 }
170
171
172 class LineToken implements LineText {
52 173
53 final String value; 174 final String value;
54 175
55 LineToken(this.value); 176 LineToken(this.value);
56 177
57 String toString() => value; 178 String toString() => value;
179
180 int get length => value.length;
181
182 void addTo(Chunk chunk) {
183 chunk.buffer.write(value);
184 }
58 } 185 }
59 186
187
60 class SpaceToken extends LineToken { 188 class SpaceToken extends LineToken {
61 189
62 SpaceToken(int n) : super(getSpaces(n)); 190 final int breakWeight;
191
192 SpaceToken(int n, {this.breakWeight: DEFAULT_SPACE_WEIGHT}) :
193 super(getSpaces(n));
63 } 194 }
64 195
196
65 class TabToken extends LineToken { 197 class TabToken extends LineToken {
66 198
67 TabToken(int n) : super(getTabs(n)); 199 TabToken(int n) : super(getTabs(n));
68 } 200 }
69 201
70 202
71 class NewlineToken extends LineToken { 203 class NewlineToken extends LineToken {
72 204
73 NewlineToken(String value) : super(value); 205 NewlineToken(String value) : super(value);
74 } 206 }
75 207
76 208
77
78 class SourceWriter { 209 class SourceWriter {
79 210
80 final StringBuffer buffer = new StringBuffer(); 211 final buffer = new StringBuffer();
Brian Wilkerson 2014/01/09 19:29:24 Not sure why you deleted the type. Because this is
pquitslund 2014/01/09 23:04:12 That was overzealous on my part. Added back.
81 Line currentLine; 212 Line currentLine;
82 213
83 final String lineSeparator; 214 final String lineSeparator;
84 int indentCount = 0; 215 int indentCount = 0;
85 216
217 LinePrinter linePrinter;
86 LineToken _lastToken; 218 LineToken _lastToken;
87 219
88 SourceWriter({this.indentCount: 0, this.lineSeparator: NEW_LINE}) { 220 SourceWriter({this.indentCount: 0, this.lineSeparator: NEW_LINE,
89 currentLine = new Line(indent: indentCount); 221 int maxLineLength: 80}) {
222 linePrinter = new SimpleLinePrinter();
223 currentLine = new Line(indent: indentCount, printer: linePrinter);
90 } 224 }
91 225
92 LineToken get lastToken => _lastToken; 226 LineToken get lastToken => _lastToken;
93 227
94 _addToken(LineToken token) { 228 _addToken(LineToken token) {
95 _lastToken = token; 229 _lastToken = token;
96 currentLine.addToken(token); 230 currentLine.addToken(token);
97 } 231 }
98 232
99 void indent() { 233 void indent() {
100 ++indentCount; 234 ++indentCount;
101 } 235 }
102 236
103 void newline() { 237 void newline() {
104 if (currentLine.isWhitespace()) { 238 if (currentLine.isWhitespace()) {
105 currentLine.tokens.clear(); 239 currentLine.tokens.clear();
106 } 240 }
107 _addToken(new NewlineToken(this.lineSeparator)); 241 _addToken(new NewlineToken(this.lineSeparator));
108 buffer.write(currentLine.toString()); 242 buffer.write(currentLine.toString());
109 currentLine = new Line(indent: indentCount); 243 currentLine = new Line(indent: indentCount, printer: linePrinter);
110 } 244 }
111 245
112 void newlines(int num) { 246 void newlines(int num) {
113 while (num-- > 0) { 247 while (num-- > 0) {
114 newline(); 248 newline();
115 } 249 }
116 } 250 }
117 251
118 void print(x) { 252 void print(x) {
119 _addToken(new LineToken(x)); 253 _addToken(new LineToken(x));
120 } 254 }
121 255
122 void println(String s) { 256 void println(String s) {
123 print(s); 257 print(s);
124 newline(); 258 newline();
125 } 259 }
126 260
127 void space() { 261 void space() {
128 spaces(1); 262 spaces(1);
129 } 263 }
130 264
131 void spaces(n) { 265 void spaces(n, {breakWeight: null}) {
132 currentLine.addSpaces(n); 266 currentLine.addSpaces(n, breakWeight: breakWeight);
133 } 267 }
134 268
135 void unindent() { 269 void unindent() {
136 --indentCount; 270 --indentCount;
137 } 271 }
138 272
139 String toString() { 273 String toString() {
140 var source = new StringBuffer(buffer.toString()); 274 var source = new StringBuffer(buffer.toString());
141 if (!currentLine.isWhitespace()) { 275 if (!currentLine.isWhitespace()) {
142 source.write(currentLine); 276 source.write(currentLine);
143 } 277 }
144 return source.toString(); 278 return source.toString();
145 } 279 }
146 280
147 } 281 }
148 282
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 327
194 String getTabs(int n) => n < TABS.length ? TABS[n] : repeat('\t', n); 328 String getTabs(int n) => n < TABS.length ? TABS[n] : repeat('\t', n);
195 329
196 String repeat(String ch, int times) { 330 String repeat(String ch, int times) {
197 var sb = new StringBuffer(); 331 var sb = new StringBuffer();
198 for (var i = 0; i < times; ++i) { 332 for (var i = 0; i < times; ++i) {
199 sb.write(ch); 333 sb.write(ch);
200 } 334 }
201 return sb.toString(); 335 return sb.toString();
202 } 336 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/services/formatter_impl.dart ('k') | pkg/analyzer/test/services/formatter_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698