OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 dart_style.src.line_splitter; | 5 library dart_style.src.line_splitter; |
6 | 6 |
7 import 'dart:math' as math; | 7 import 'dart:math' as math; |
8 | 8 |
9 import 'chunk.dart'; | 9 import 'chunk.dart'; |
10 import 'debug.dart'; | 10 import 'debug.dart'; |
11 import 'line_prefix.dart'; | 11 import 'line_prefix.dart'; |
| 12 import 'line_writer.dart'; |
12 | 13 |
13 /// The number of spaces in a single level of indentation. | 14 /// The number of spaces in a single level of indentation. |
14 const spacesPerIndent = 2; | 15 const spacesPerIndent = 2; |
15 | 16 |
16 /// The number of indentation levels in a single level of expression nesting. | 17 /// The number of indentation levels in a single level of expression nesting. |
17 const indentsPerNest = 2; | 18 const indentsPerNest = 2; |
18 | 19 |
19 /// Cost or indent value used to indication no solution could be found. | 20 /// Cost or indent value used to indication no solution could be found. |
20 const invalidSplits = -1; | 21 const invalidSplits = -1; |
21 | 22 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 /// given page width. | 88 /// given page width. |
88 LineSplitter(this._lineEnding, this._pageWidth, this._chunks, this._spans, | 89 LineSplitter(this._lineEnding, this._pageWidth, this._chunks, this._spans, |
89 this._indent) { | 90 this._indent) { |
90 assert(_chunks.isNotEmpty); | 91 assert(_chunks.isNotEmpty); |
91 } | 92 } |
92 | 93 |
93 /// Convert the line to a [String] representation. | 94 /// Convert the line to a [String] representation. |
94 /// | 95 /// |
95 /// It will determine how best to split it into multiple lines of output and | 96 /// It will determine how best to split it into multiple lines of output and |
96 /// return a single string that may contain one or more newline characters. | 97 /// return a single string that may contain one or more newline characters. |
97 void apply(StringBuffer buffer) { | 98 /// |
| 99 /// Returns a two-element list. The first element will be an [int] indicating |
| 100 /// where in [buffer] the selection start point should appear if it was |
| 101 /// contained in the formatted list of chunks. Otherwise it will be `null`. |
| 102 /// Likewise, the second element will be non-`null` if the selection endpoint |
| 103 /// is within the list of chunks. |
| 104 List<int> apply(StringBuffer buffer) { |
98 if (debugFormatter) dumpLine(_chunks, _indent); | 105 if (debugFormatter) dumpLine(_chunks, _indent); |
99 | 106 |
100 var splits = _findBestSplits(new LinePrefix()); | 107 var splits = _findBestSplits(new LinePrefix()); |
| 108 var selection = [null, null]; |
101 | 109 |
102 // Write each chunk and the split after it. | 110 // Write each chunk and the split after it. |
103 buffer.write(" " * (_indent * spacesPerIndent)); | 111 buffer.write(" " * (_indent * spacesPerIndent)); |
104 for (var i = 0; i < _chunks.length - 1; i++) { | 112 for (var i = 0; i < _chunks.length; i++) { |
105 var chunk = _chunks[i]; | 113 var chunk = _chunks[i]; |
106 | 114 |
| 115 // If this chunk contains one of the selection markers, tell the writer |
| 116 // where it ended up in the final output. |
| 117 if (chunk.selectionStart != null) { |
| 118 selection[0] = buffer.length + chunk.selectionStart; |
| 119 } |
| 120 |
| 121 if (chunk.selectionEnd != null) { |
| 122 selection[1] = buffer.length + chunk.selectionEnd; |
| 123 } |
| 124 |
107 buffer.write(chunk.text); | 125 buffer.write(chunk.text); |
108 | 126 |
109 if (splits.shouldSplitAt(i)) { | 127 if (i == _chunks.length - 1) { |
| 128 // Don't write trailing whitespace after the last chunk. |
| 129 } else if (splits.shouldSplitAt(i)) { |
110 buffer.write(_lineEnding); | 130 buffer.write(_lineEnding); |
111 if (chunk.isDouble) buffer.write(_lineEnding); | 131 if (chunk.isDouble) buffer.write(_lineEnding); |
112 | 132 |
113 var indent = chunk.indent + splits.getNesting(i); | 133 var indent = chunk.indent + splits.getNesting(i); |
114 buffer.write(" " * (indent * spacesPerIndent)); | 134 buffer.write(" " * (indent * spacesPerIndent)); |
115 | 135 |
116 // Should have a valid set of splits when we get here. | 136 // Should have a valid set of splits when we get here. |
117 assert(indent != invalidSplits); | 137 assert(indent != invalidSplits); |
118 } else { | 138 } else { |
119 if (chunk.spaceWhenUnsplit) buffer.write(" "); | 139 if (chunk.spaceWhenUnsplit) buffer.write(" "); |
120 } | 140 } |
121 } | 141 } |
122 | 142 |
123 // Write the final chunk without any trailing newlines. | 143 return selection; |
124 buffer.write(_chunks.last.text); | |
125 } | 144 } |
126 | 145 |
127 /// Finds the best set of splits to apply to the remainder of the line | 146 /// Finds the best set of splits to apply to the remainder of the line |
128 /// following [prefix]. | 147 /// following [prefix]. |
129 SplitSet _findBestSplits(LinePrefix prefix) { | 148 SplitSet _findBestSplits(LinePrefix prefix) { |
130 // Use the memoized result if we have it. | 149 // Use the memoized result if we have it. |
131 if (_bestSplits.containsKey(prefix)) return _bestSplits[prefix]; | 150 if (_bestSplits.containsKey(prefix)) return _bestSplits[prefix]; |
132 | 151 |
133 var indent = prefix.getNextLineIndent(_chunks, _indent); | 152 var indent = prefix.getNextLineIndent(_chunks, _indent); |
134 | 153 |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 var result = []; | 472 var result = []; |
454 for (var i = 0; i < _splitNesting.length; i++) { | 473 for (var i = 0; i < _splitNesting.length; i++) { |
455 if (_splitNesting[i] != null) { | 474 if (_splitNesting[i] != null) { |
456 result.add("$i:${_splitNesting[i]}"); | 475 result.add("$i:${_splitNesting[i]}"); |
457 } | 476 } |
458 } | 477 } |
459 | 478 |
460 return result.join(" "); | 479 return result.join(" "); |
461 } | 480 } |
462 } | 481 } |
OLD | NEW |