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

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

Issue 136863003: Line breaking plumbing (continued). (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 tokens = <LineToken>[]; 10 final tokens = <LineToken>[];
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 56
57 /// A simple line breaking [LinePrinter] 57 /// A simple line breaking [LinePrinter]
58 class SimpleLineBreaker extends LinePrinter { 58 class SimpleLineBreaker extends LinePrinter {
59 59
60 final chunks = <Chunk>[]; 60 final chunks = <Chunk>[];
61 final int maxLength; 61 final int maxLength;
62 62
63 SimpleLineBreaker(this.maxLength); 63 SimpleLineBreaker(this.maxLength);
64 64
65 String printLine(Line line) { 65 String printLine(Line line) {
66 //TODO(pquitslund): implement 66 var buf = new StringBuffer();
67 var chunks = breakLine(line);
68 for (var i = 0; i < chunks.length; ++i) {
69 if (i > 0) {
70 buf.write(indent(chunks[i]));
71 } else {
72 buf.write(chunks[i]);
73 }
74 }
75 return buf.toString();
76 }
77
78 String indent(Chunk chunk) {
79 return '\n' + chunk.toString();
67 } 80 }
68 81
69 List<Chunk> breakLine(Line line) { 82 List<Chunk> breakLine(Line line) {
70 83
71 var chunks = <Chunk>[]; 84 var chunks = <Chunk>[];
72 85
73 // The current unbroken line 86 // The current unbroken line
74 var current = new Chunk(maxLength: maxLength); 87 var current = new Chunk(maxLength: maxLength);
75 88
76 // A tentative working chunk that will either start a new line or get 89 // A tentative working chunk that will either start a new line or get
77 // absorbed into 'current' 90 // absorbed into 'current'
78 var work = new Chunk(maxLength: maxLength); 91 var work = new Chunk(maxLength: maxLength);
79 92
80 line.tokens.forEach((tok) { 93 line.tokens.forEach((tok) {
81 94
82 if (goodStart(tok, work)) { 95 if (goodStart(tok, work)) {
83 if (current.fits(work)) { 96 if (current.fits(work)) {
84 current.add(work); 97 current.add(work);
85 } else { 98 } else {
86 if (current.length > 0) { 99 if (current.length > 0) {
87 chunks.add(current); 100 chunks.add(current);
88 } 101 }
89 current = work; 102 current = work;
90 } 103 }
91 work = new Chunk(start: tok, maxLength: maxLength - current.length); 104 work = new Chunk(start: tok, maxLength: maxLength - current.length);
92 } else { 105 } else {
93 if (work.fits(tok)) { 106 if (work.fits(tok)) {
94 work.add(tok); 107 work.add(tok);
95 } else { 108 } else {
96 current.add(work); 109 if (!isWhitespace(work)) {
110 current.add(work);
111 }
97 if (current.length > 0) { 112 if (current.length > 0) {
98 chunks.add(current); 113 chunks.add(current);
99 current = new Chunk(maxLength: maxLength); 114 current = new Chunk(maxLength: maxLength);
100 } 115 }
101 work = new Chunk(maxLength: maxLength); 116 work = new Chunk(maxLength: maxLength);
102 work.add(tok); 117 work.add(tok);
103 } 118 }
104 } 119 }
105 120
106 }); 121 });
107 122
108 current.add(work); 123 current.add(work);
109 if (current.length > 0) { 124 if (current.length > 0) {
110 chunks.add(current); 125 chunks.add(current);
111 } 126 }
112 return chunks; 127 return chunks;
113 } 128 }
114 129
130 bool isWhitespace(Chunk chunk) {
pquitslund 2014/01/13 16:39:55 This *can't* be the best way to test this... Idea
131 var str = chunk.buffer.toString();
132 return str.lastIndexOf(new RegExp(r"(\w+)")) == str.length - 1;
133 }
134
115 /// Test whether this token is a good start for a new working chunk 135 /// Test whether this token is a good start for a new working chunk
116 bool goodStart(LineToken tok, Chunk workingChunk) => 136 bool goodStart(LineToken tok, Chunk workingChunk) =>
117 tok is SpaceToken && tok.breakWeight >= workingChunk.start.breakWeight; 137 tok is SpaceToken && tok.breakWeight >= workingChunk.start.breakWeight;
118 138
119 } 139 }
120 140
121 141
122 /// Special token indicating a line start 142 /// Special token indicating a line start
123 final LINE_START = new SpaceToken(0); 143 final LINE_START = new SpaceToken(0);
124 144
(...skipping 16 matching lines...) Expand all
141 /// Describes a piece of text in a [Line]. 161 /// Describes a piece of text in a [Line].
142 abstract class LineText { 162 abstract class LineText {
143 int get length; 163 int get length;
144 void addTo(Chunk chunk); 164 void addTo(Chunk chunk);
145 } 165 }
146 166
147 167
148 /// A working piece of text used in calculating line breaks 168 /// A working piece of text used in calculating line breaks
149 class Chunk implements LineText { 169 class Chunk implements LineText {
150 170
151 final buffer = new StringBuffer(); 171 final StringBuffer buffer = new StringBuffer();
152 172
153 int maxLength; 173 int maxLength;
154 SpaceToken start; 174 SpaceToken start;
155 175
156 Chunk({this.start, this.maxLength}) { 176 Chunk({this.start, this.maxLength}) {
157 if (start == null) { 177 if (start == null) {
158 start = LINE_START; 178 start = LINE_START;
159 } 179 }
160 } 180 }
161 181
162 bool fits(LineText text) => length + text.length < maxLength; 182 bool fits(LineText text) => length + text.length < maxLength;
163 183
164 int get length => start.value.length + buffer.length; 184 int get length => start.value.length + buffer.length;
165 185
166 void add(LineText text) { 186 void add(LineText text) {
167 text.addTo(this); 187 text.addTo(this);
168 } 188 }
169 189
170 String toString() => buffer.toString().trim(); 190 String toString() => buffer.toString();
171 191
172 void addTo(Chunk chunk) { 192 void addTo(Chunk chunk) {
173 chunk.buffer.write(start.value); 193 chunk.buffer.write(start.value);
174 chunk.buffer.write(buffer.toString()); 194 chunk.buffer.write(buffer.toString());
175 } 195 }
176 } 196 }
177 197
178 198
179 class LineToken implements LineText { 199 class LineToken implements LineText {
180 200
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 Line currentLine; 239 Line currentLine;
220 240
221 final String lineSeparator; 241 final String lineSeparator;
222 int indentCount = 0; 242 int indentCount = 0;
223 243
224 LinePrinter linePrinter; 244 LinePrinter linePrinter;
225 LineToken _lastToken; 245 LineToken _lastToken;
226 246
227 SourceWriter({this.indentCount: 0, this.lineSeparator: NEW_LINE, 247 SourceWriter({this.indentCount: 0, this.lineSeparator: NEW_LINE,
228 int maxLineLength: 80}) { 248 int maxLineLength: 80}) {
229 linePrinter = new SimpleLinePrinter(); 249 linePrinter = new SimpleLineBreaker(maxLineLength);
230 currentLine = new Line(indent: indentCount, printer: linePrinter); 250 currentLine = new Line(indent: indentCount, printer: linePrinter);
231 } 251 }
232 252
233 LineToken get lastToken => _lastToken; 253 LineToken get lastToken => _lastToken;
234 254
235 _addToken(LineToken token) { 255 _addToken(LineToken token) {
236 _lastToken = token; 256 _lastToken = token;
237 currentLine.addToken(token); 257 currentLine.addToken(token);
238 } 258 }
239 259
(...skipping 22 matching lines...) Expand all
262 282
263 void println(String s) { 283 void println(String s) {
264 print(s); 284 print(s);
265 newline(); 285 newline();
266 } 286 }
267 287
268 void space() { 288 void space() {
269 spaces(1); 289 spaces(1);
270 } 290 }
271 291
272 void spaces(n, {breakWeight: null}) { 292 void spaces(n, {breakWeight: DEFAULT_SPACE_WEIGHT}) {
273 currentLine.addSpaces(n, breakWeight: breakWeight); 293 currentLine.addSpaces(n, breakWeight: breakWeight);
274 } 294 }
275 295
276 void unindent() { 296 void unindent() {
277 --indentCount; 297 --indentCount;
278 } 298 }
279 299
280 String toString() { 300 String toString() {
281 var source = new StringBuffer(buffer.toString()); 301 var source = new StringBuffer(buffer.toString());
282 if (!currentLine.isWhitespace()) { 302 if (!currentLine.isWhitespace()) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 354
335 String getTabs(int n) => n < TABS.length ? TABS[n] : repeat('\t', n); 355 String getTabs(int n) => n < TABS.length ? TABS[n] : repeat('\t', n);
336 356
337 String repeat(String ch, int times) { 357 String repeat(String ch, int times) {
338 var sb = new StringBuffer(); 358 var sb = new StringBuffer();
339 for (var i = 0; i < times; ++i) { 359 for (var i = 0; i < times; ++i) {
340 sb.write(ch); 360 sb.write(ch);
341 } 361 }
342 return sb.toString(); 362 return sb.toString();
343 } 363 }
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