| 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.chunk_builder; | 5 library dart_style.src.chunk_builder; |
| 6 | 6 |
| 7 import 'chunk.dart'; | 7 import 'chunk.dart'; |
| 8 import 'dart_formatter.dart'; | 8 import 'dart_formatter.dart'; |
| 9 import 'debug.dart' as debug; | 9 import 'debug.dart' as debug; |
| 10 import 'line_splitter.dart'; | 10 import 'line_splitter.dart'; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 bool _firstFlushLeft = false; | 84 bool _firstFlushLeft = false; |
| 85 | 85 |
| 86 /// Whether there is pending whitespace that depends on the number of | 86 /// Whether there is pending whitespace that depends on the number of |
| 87 /// newlines in the source. | 87 /// newlines in the source. |
| 88 /// | 88 /// |
| 89 /// This is used to avoid calculating the newlines between tokens unless | 89 /// This is used to avoid calculating the newlines between tokens unless |
| 90 /// actually needed since doing so is slow when done between every single | 90 /// actually needed since doing so is slow when done between every single |
| 91 /// token pair. | 91 /// token pair. |
| 92 bool get needsToPreserveNewlines => | 92 bool get needsToPreserveNewlines => |
| 93 _pendingWhitespace == Whitespace.oneOrTwoNewlines || | 93 _pendingWhitespace == Whitespace.oneOrTwoNewlines || |
| 94 _pendingWhitespace == Whitespace.spaceOrNewline; | 94 _pendingWhitespace == Whitespace.spaceOrNewline; |
| 95 | 95 |
| 96 /// The number of characters of code that can fit in a single line. | 96 /// The number of characters of code that can fit in a single line. |
| 97 int get pageWidth => _formatter.pageWidth; | 97 int get pageWidth => _formatter.pageWidth; |
| 98 | 98 |
| 99 /// The current innermost rule. | 99 /// The current innermost rule. |
| 100 Rule get rule => _rules.last; | 100 Rule get rule => _rules.last; |
| 101 | 101 |
| 102 ChunkBuilder(this._formatter, this._source) | 102 ChunkBuilder(this._formatter, this._source) |
| 103 : _parent = null, | 103 : _parent = null, |
| 104 _chunks = [] { | 104 _chunks = [] { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 /// Write a split owned by the current innermost rule. | 141 /// Write a split owned by the current innermost rule. |
| 142 /// | 142 /// |
| 143 /// If [nesting] is given, uses that. Otherwise, uses the current nesting | 143 /// If [nesting] is given, uses that. Otherwise, uses the current nesting |
| 144 /// level. If unsplit, it expands to a space if [space] is `true`. | 144 /// level. If unsplit, it expands to a space if [space] is `true`. |
| 145 /// | 145 /// |
| 146 /// If [flushLeft] is `true`, then forces the next line to start at column | 146 /// If [flushLeft] is `true`, then forces the next line to start at column |
| 147 /// one regardless of any indentation or nesting. | 147 /// one regardless of any indentation or nesting. |
| 148 /// | 148 /// |
| 149 /// If [isDouble] is passed, forces the split to either be a single or double | 149 /// If [isDouble] is passed, forces the split to either be a single or double |
| 150 /// newline. Otherwise, leaves it indeterminate. | 150 /// newline. Otherwise, leaves it indeterminate. |
| 151 Chunk split({bool space, bool isDouble, bool flushLeft}) => | 151 Chunk split({bool space, bool isDouble, bool flushLeft}) => _writeSplit( |
| 152 _writeSplit(_rules.last, null, | 152 _rules.last, null, |
| 153 flushLeft: flushLeft, isDouble: isDouble, spaceWhenUnsplit: space); | 153 flushLeft: flushLeft, isDouble: isDouble, spaceWhenUnsplit: space); |
| 154 | 154 |
| 155 /// Write a split owned by the current innermost rule. | 155 /// Write a split owned by the current innermost rule. |
| 156 /// | 156 /// |
| 157 /// Unlike [split()], this ignores any current expression nesting. It always | 157 /// Unlike [split()], this ignores any current expression nesting. It always |
| 158 /// indents the next line at the statement level. | 158 /// indents the next line at the statement level. |
| 159 Chunk blockSplit({bool space, bool isDouble}) => | 159 Chunk blockSplit({bool space, bool isDouble}) => _writeSplit( |
| 160 _writeSplit(_rules.last, _nesting.blockNesting, | 160 _rules.last, _nesting.blockNesting, |
| 161 isDouble: isDouble, | 161 isDouble: isDouble, spaceWhenUnsplit: space); |
| 162 spaceWhenUnsplit: space); | |
| 163 | 162 |
| 164 /// Outputs the series of [comments] and associated whitespace that appear | 163 /// Outputs the series of [comments] and associated whitespace that appear |
| 165 /// before [token] (which is not written by this). | 164 /// before [token] (which is not written by this). |
| 166 /// | 165 /// |
| 167 /// The list contains each comment as it appeared in the source between the | 166 /// The list contains each comment as it appeared in the source between the |
| 168 /// last token written and the next one that's about to be written. | 167 /// last token written and the next one that's about to be written. |
| 169 /// | 168 /// |
| 170 /// [linesBeforeToken] is the number of lines between the last comment (or | 169 /// [linesBeforeToken] is the number of lines between the last comment (or |
| 171 /// previous token if there are no comments) and the next token. | 170 /// previous token if there are no comments) and the next token. |
| 172 void writeComments(List<SourceComment> comments, int linesBeforeToken, | 171 void writeComments( |
| 173 String token) { | 172 List<SourceComment> comments, int linesBeforeToken, String token) { |
| 174 // Corner case: if we require a blank line, but there exists one between | 173 // Corner case: if we require a blank line, but there exists one between |
| 175 // some of the comments, or after the last one, then we don't need to | 174 // some of the comments, or after the last one, then we don't need to |
| 176 // enforce one before the first comment. Example: | 175 // enforce one before the first comment. Example: |
| 177 // | 176 // |
| 178 // library foo; | 177 // library foo; |
| 179 // // comment | 178 // // comment |
| 180 // | 179 // |
| 181 // class Bar {} | 180 // class Bar {} |
| 182 // | 181 // |
| 183 // Normally, a blank line is required after `library`, but since there is | 182 // Normally, a blank line is required after `library`, but since there is |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 _chunks.last.allowText(); | 239 _chunks.last.allowText(); |
| 241 } | 240 } |
| 242 | 241 |
| 243 // The comment follows other text, so we need to decide if it gets a | 242 // The comment follows other text, so we need to decide if it gets a |
| 244 // space before it or not. | 243 // space before it or not. |
| 245 if (_needsSpaceBeforeComment(isLineComment: comment.isLineComment)) { | 244 if (_needsSpaceBeforeComment(isLineComment: comment.isLineComment)) { |
| 246 _writeText(" "); | 245 _writeText(" "); |
| 247 } | 246 } |
| 248 } else { | 247 } else { |
| 249 // The comment starts a line, so make sure it stays on its own line. | 248 // The comment starts a line, so make sure it stays on its own line. |
| 250 _writeHardSplit(nest: true, flushLeft: comment.flushLeft, | 249 _writeHardSplit( |
| 250 nest: true, |
| 251 flushLeft: comment.flushLeft, |
| 251 double: comment.linesBefore > 1); | 252 double: comment.linesBefore > 1); |
| 252 } | 253 } |
| 253 | 254 |
| 254 _writeText(comment.text); | 255 _writeText(comment.text); |
| 255 | 256 |
| 256 if (comment.selectionStart != null) { | 257 if (comment.selectionStart != null) { |
| 257 startSelectionFromEnd(comment.text.length - comment.selectionStart); | 258 startSelectionFromEnd(comment.text.length - comment.selectionStart); |
| 258 } | 259 } |
| 259 | 260 |
| 260 if (comment.selectionEnd != null) { | 261 if (comment.selectionEnd != null) { |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 | 454 |
| 454 /// Releases the last nesting level captured by [startBlockArgumentNesting]. | 455 /// Releases the last nesting level captured by [startBlockArgumentNesting]. |
| 455 void endBlockArgumentNesting() { | 456 void endBlockArgumentNesting() { |
| 456 _blockArgumentNesting.removeLast(); | 457 _blockArgumentNesting.removeLast(); |
| 457 } | 458 } |
| 458 | 459 |
| 459 /// Starts a new block as a child of the current chunk. | 460 /// Starts a new block as a child of the current chunk. |
| 460 /// | 461 /// |
| 461 /// Nested blocks are handled using their own independent [LineWriter]. | 462 /// Nested blocks are handled using their own independent [LineWriter]. |
| 462 ChunkBuilder startBlock() { | 463 ChunkBuilder startBlock() { |
| 463 var builder = new ChunkBuilder._(this, _formatter, _source, | 464 var builder = |
| 464 _chunks.last.blockChunks); | 465 new ChunkBuilder._(this, _formatter, _source, _chunks.last.blockChunks); |
| 465 | 466 |
| 466 // A block always starts off indented one level. | 467 // A block always starts off indented one level. |
| 467 builder.indent(); | 468 builder.indent(); |
| 468 | 469 |
| 469 return builder; | 470 return builder; |
| 470 } | 471 } |
| 471 | 472 |
| 472 /// Ends this [ChunkBuilder], which must have been created by [startBlock()]. | 473 /// Ends this [ChunkBuilder], which must have been created by [startBlock()]. |
| 473 /// | 474 /// |
| 474 /// Forces the chunk that owns the block to split if it can tell that the | 475 /// Forces the chunk that owns the block to split if it can tell that the |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 /// was just written and the token that will be written. | 637 /// was just written and the token that will be written. |
| 637 bool _needsSpaceAfterLastComment(List<SourceComment> comments, String token) { | 638 bool _needsSpaceAfterLastComment(List<SourceComment> comments, String token) { |
| 638 // Not if there are no comments. | 639 // Not if there are no comments. |
| 639 if (comments.isEmpty) return false; | 640 if (comments.isEmpty) return false; |
| 640 | 641 |
| 641 // Not at the beginning of a line. | 642 // Not at the beginning of a line. |
| 642 if (!_chunks.last.canAddText) return false; | 643 if (!_chunks.last.canAddText) return false; |
| 643 | 644 |
| 644 // Otherwise, it gets a space if the following token is not a delimiter or | 645 // Otherwise, it gets a space if the following token is not a delimiter or |
| 645 // the empty string, for EOF. | 646 // the empty string, for EOF. |
| 646 return token != ")" && token != "]" && token != "}" && | 647 return token != ")" && |
| 647 token != "," && token != ";" && token != ""; | 648 token != "]" && |
| 649 token != "}" && |
| 650 token != "," && |
| 651 token != ";" && |
| 652 token != ""; |
| 648 } | 653 } |
| 649 | 654 |
| 650 /// Appends a hard split with the current indentation and nesting (the latter | 655 /// Appends a hard split with the current indentation and nesting (the latter |
| 651 /// only if [nest] is `true`). | 656 /// only if [nest] is `true`). |
| 652 /// | 657 /// |
| 653 /// If [double] is `true` or `false`, forces a since or double line to be | 658 /// If [double] is `true` or `false`, forces a since or double line to be |
| 654 /// output. Otherwise, it is left indeterminate. | 659 /// output. Otherwise, it is left indeterminate. |
| 655 /// | 660 /// |
| 656 /// If [flushLeft] is `true`, then the split will always cause the next line | 661 /// If [flushLeft] is `true`, then the split will always cause the next line |
| 657 /// to be at column zero. Otherwise, it uses the normal indentation and | 662 /// to be at column zero. Otherwise, it uses the normal indentation and |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 882 if (rule.constrain(rule.fullySplitValue, other) == | 887 if (rule.constrain(rule.fullySplitValue, other) == |
| 883 other.fullySplitValue) { | 888 other.fullySplitValue) { |
| 884 harden(other); | 889 harden(other); |
| 885 } | 890 } |
| 886 } | 891 } |
| 887 } | 892 } |
| 888 | 893 |
| 889 harden(rule); | 894 harden(rule); |
| 890 } | 895 } |
| 891 } | 896 } |
| OLD | NEW |