| OLD | NEW |
| 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 import 'dart:math' as math; | 7 import 'dart:math' as math; |
| 8 | 8 |
| 9 class Line { | 9 class Line { |
| 10 | 10 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 return buf.toString(); | 94 return buf.toString(); |
| 95 } | 95 } |
| 96 | 96 |
| 97 String indent(Chunk chunk, int level) { | 97 String indent(Chunk chunk, int level) { |
| 98 return '\n' + indenter(level) + chunk.toString(); | 98 return '\n' + indenter(level) + chunk.toString(); |
| 99 } | 99 } |
| 100 | 100 |
| 101 List<Chunk> breakLine(Line line) { | 101 List<Chunk> breakLine(Line line) { |
| 102 List<LineToken> tokens = preprocess(line.tokens); | 102 List<LineToken> tokens = preprocess(line.tokens); |
| 103 List<Chunk> chunks = <Chunk>[new Chunk(line.indentLevel, maxLength, tokens)]
; | 103 List<Chunk> chunks = <Chunk>[new Chunk(line.indentLevel, maxLength, tokens)]
; |
| 104 // try SINGLE_SPACE_WEIGHT |
| 105 { |
| 106 Chunk chunk = chunks[0]; |
| 107 if (chunk.length > maxLength) { |
| 108 for (int i = 0; i < tokens.length; i++) { |
| 109 LineToken token = tokens[i]; |
| 110 if (token is SpaceToken && token.breakWeight == SINGLE_SPACE_WEIGHT) { |
| 111 var beforeChunk = chunk.subChunk(chunk.indent, 0, i); |
| 112 var restChunk = chunk.subChunk(chunk.indent + 2, i + 1); |
| 113 // check if 'init' in 'var v = init;' fits a line |
| 114 if (restChunk.length < maxLength) { |
| 115 return [beforeChunk, restChunk]; |
| 116 } |
| 117 // check if 'var v = method(' in 'var v = method(args)' does not fit |
| 118 int weight = chunk.findMinSpaceWeight(); |
| 119 if (chunk.getLengthToSpaceWithWeight(weight) > maxLength) { |
| 120 chunks = [beforeChunk, restChunk]; |
| 121 } |
| 122 // done anyway |
| 123 break; |
| 124 } |
| 125 } |
| 126 } |
| 127 } |
| 128 // other spaces |
| 104 while (true) { | 129 while (true) { |
| 105 List<Chunk> newChunks = <Chunk>[]; | 130 List<Chunk> newChunks = <Chunk>[]; |
| 106 bool hasChanges = false; | 131 bool hasChanges = false; |
| 107 for (Chunk chunk in chunks) { | 132 for (Chunk chunk in chunks) { |
| 108 tokens = chunk.tokens; | 133 tokens = chunk.tokens; |
| 109 if (chunk.length > maxLength) { | 134 if (chunk.length > maxLength) { |
| 110 if (chunk.hasAnySpace()) { | 135 if (chunk.hasAnySpace()) { |
| 111 int weight = chunk.findMinSpaceWeight(); | 136 int weight = chunk.findMinSpaceWeight(); |
| 112 int newIndent = chunk.indent; | 137 int newIndent = chunk.indent; |
| 113 if (weight == DEFAULT_SPACE_WEIGHT) { | 138 if (weight == DEFAULT_SPACE_WEIGHT) { |
| 114 int start = 0; | 139 int start = 0; |
| 115 int length = 0; | 140 int length = 0; |
| 116 for (int i = 0; i < tokens.length; i++) { | 141 for (int i = 0; i < tokens.length; i++) { |
| 117 LineToken token = tokens[i]; | 142 LineToken token = tokens[i]; |
| 118 if (token is SpaceToken && token.breakWeight == weight | 143 if (token is SpaceToken && token.breakWeight == weight && |
| 119 && i < tokens.length - 1) { | 144 i < tokens.length - 1) { |
| 120 LineToken nextToken = tokens[i + 1]; | 145 LineToken nextToken = tokens[i + 1]; |
| 121 if (length + token.length + nextToken.length > maxLength) { | 146 if (length + token.length + nextToken.length > maxLength) { |
| 122 newChunks.add(chunk.subChunk(newIndent, start, i)); | 147 newChunks.add(chunk.subChunk(newIndent, start, i)); |
| 123 newIndent = chunk.indent + 2; | 148 newIndent = chunk.indent + 2; |
| 124 start = i + 1; | 149 start = i + 1; |
| 125 length = 0; | 150 length = 0; |
| 126 continue; | 151 continue; |
| 127 } | 152 } |
| 128 } | 153 } |
| 129 length += token.length; | 154 length += token.length; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 } | 229 } |
| 205 | 230 |
| 206 /// Test if this [string] contains only whitespace characters | 231 /// Test if this [string] contains only whitespace characters |
| 207 bool isWhitespace(String string) => string.codeUnits.every( | 232 bool isWhitespace(String string) => string.codeUnits.every( |
| 208 (c) => c == 0x09 || c == 0x20 || c == 0x0A || c == 0x0D); | 233 (c) => c == 0x09 || c == 0x20 || c == 0x0A || c == 0x0D); |
| 209 | 234 |
| 210 /// Special token indicating a line start | 235 /// Special token indicating a line start |
| 211 final LINE_START = new SpaceToken(0); | 236 final LINE_START = new SpaceToken(0); |
| 212 | 237 |
| 213 const DEFAULT_SPACE_WEIGHT = UNBREAKABLE_SPACE_WEIGHT - 1; | 238 const DEFAULT_SPACE_WEIGHT = UNBREAKABLE_SPACE_WEIGHT - 1; |
| 239 /// The weight of a space after '=' in variable declaration or assignment |
| 240 const SINGLE_SPACE_WEIGHT = UNBREAKABLE_SPACE_WEIGHT - 2; |
| 214 const UNBREAKABLE_SPACE_WEIGHT = 100000000; | 241 const UNBREAKABLE_SPACE_WEIGHT = 100000000; |
| 215 | 242 |
| 216 /// Simple non-breaking printer | 243 /// Simple non-breaking printer |
| 217 class SimpleLinePrinter extends LinePrinter { | 244 class SimpleLinePrinter extends LinePrinter { |
| 218 | 245 |
| 219 const SimpleLinePrinter(); | 246 const SimpleLinePrinter(); |
| 220 | 247 |
| 221 String printLine(Line line) { | 248 String printLine(Line line) { |
| 222 var buffer = new StringBuffer(); | 249 var buffer = new StringBuffer(); |
| 223 line.tokens.forEach((tok) => buffer.write(tok.toString())); | 250 line.tokens.forEach((tok) => buffer.write(tok.toString())); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 236 /// A working piece of text used in calculating line breaks | 263 /// A working piece of text used in calculating line breaks |
| 237 class Chunk { | 264 class Chunk { |
| 238 final int indent; | 265 final int indent; |
| 239 final int maxLength; | 266 final int maxLength; |
| 240 final List<LineToken> tokens = <LineToken>[]; | 267 final List<LineToken> tokens = <LineToken>[]; |
| 241 | 268 |
| 242 Chunk(this.indent, this.maxLength, [List<LineToken> tokens]) { | 269 Chunk(this.indent, this.maxLength, [List<LineToken> tokens]) { |
| 243 this.tokens.addAll(tokens); | 270 this.tokens.addAll(tokens); |
| 244 } | 271 } |
| 245 | 272 |
| 246 int get length => tokens.fold(0, (len, token) => len + token.length); | 273 int get length { |
| 274 return tokens.fold(0, (len, token) => len + token.length); |
| 275 } |
| 276 |
| 277 int getLengthToSpaceWithWeight(int weight) { |
| 278 int length = 0; |
| 279 for (LineToken token in tokens) { |
| 280 if (token is SpaceToken && token.breakWeight == weight) { |
| 281 break; |
| 282 } |
| 283 length += token.length; |
| 284 } |
| 285 return length; |
| 286 } |
| 247 | 287 |
| 248 bool fits(LineToken a, LineToken b) { | 288 bool fits(LineToken a, LineToken b) { |
| 249 return length + a.length + a.length <= maxLength; | 289 return length + a.length + a.length <= maxLength; |
| 250 } | 290 } |
| 251 | 291 |
| 252 void add(LineToken token) { | 292 void add(LineToken token) { |
| 253 tokens.add(token); | 293 tokens.add(token); |
| 254 } | 294 } |
| 255 | 295 |
| 296 bool hasInitializerSpace() { |
| 297 return tokens.any((token) { |
| 298 return token is SpaceToken && token.breakWeight == SINGLE_SPACE_WEIGHT; |
| 299 }); |
| 300 } |
| 301 |
| 256 bool hasAnySpace() { | 302 bool hasAnySpace() { |
| 257 return tokens.any((token) => token is SpaceToken); | 303 return tokens.any((token) => token is SpaceToken); |
| 258 } | 304 } |
| 259 | 305 |
| 260 int findMinSpaceWeight() { | 306 int findMinSpaceWeight() { |
| 261 int minWeight = UNBREAKABLE_SPACE_WEIGHT; | 307 int minWeight = UNBREAKABLE_SPACE_WEIGHT; |
| 262 for (var token in tokens) { | 308 for (var token in tokens) { |
| 263 if (token is SpaceToken) { | 309 if (token is SpaceToken) { |
| 264 minWeight = math.min(minWeight, token.breakWeight); | 310 minWeight = math.min(minWeight, token.breakWeight); |
| 265 } | 311 } |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 | 509 |
| 464 String getTabs(int n) => n < TABS.length ? TABS[n] : repeat('\t', n); | 510 String getTabs(int n) => n < TABS.length ? TABS[n] : repeat('\t', n); |
| 465 | 511 |
| 466 String repeat(String ch, int times) { | 512 String repeat(String ch, int times) { |
| 467 var sb = new StringBuffer(); | 513 var sb = new StringBuffer(); |
| 468 for (var i = 0; i < times; ++i) { | 514 for (var i = 0; i < times; ++i) { |
| 469 sb.write(ch); | 515 sb.write(ch); |
| 470 } | 516 } |
| 471 return sb.toString(); | 517 return sb.toString(); |
| 472 } | 518 } |
| OLD | NEW |