| 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_writer.dart'; | 10 import 'line_writer.dart'; |
| 11 import 'nesting_level.dart'; | 11 import 'nesting_level.dart'; |
| 12 import 'nesting_builder.dart'; | 12 import 'nesting_builder.dart'; |
| 13 import 'rule/rule.dart'; | 13 import 'rule/rule.dart'; |
| 14 import 'source_code.dart'; | 14 import 'source_code.dart'; |
| 15 import 'whitespace.dart'; | 15 import 'whitespace.dart'; |
| 16 | 16 |
| 17 /// Matches if the last character of a string is an identifier character. |
| 18 final _trailingIdentifierChar = new RegExp(r"[a-zA-Z0-9_]$"); |
| 19 |
| 17 /// Takes the incremental serialized output of [SourceVisitor]--the source text | 20 /// Takes the incremental serialized output of [SourceVisitor]--the source text |
| 18 /// along with any comments and preserved whitespace--and produces a coherent | 21 /// along with any comments and preserved whitespace--and produces a coherent |
| 19 /// tree of [Chunk]s which can then be split into physical lines. | 22 /// tree of [Chunk]s which can then be split into physical lines. |
| 20 /// | 23 /// |
| 21 /// Keeps track of leading indentation, expression nesting, and all of the hairy | 24 /// Keeps track of leading indentation, expression nesting, and all of the hairy |
| 22 /// code required to seamlessly integrate existing comments into the pure | 25 /// code required to seamlessly integrate existing comments into the pure |
| 23 /// output produced by [SourceVisitor]. | 26 /// output produced by [SourceVisitor]. |
| 24 class ChunkBuilder { | 27 class ChunkBuilder { |
| 25 final DartFormatter _formatter; | 28 final DartFormatter _formatter; |
| 26 | 29 |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 | 236 |
| 234 if (comment.linesBefore == 0) { | 237 if (comment.linesBefore == 0) { |
| 235 // If we're sitting on a split, move the comment before it to adhere it | 238 // If we're sitting on a split, move the comment before it to adhere it |
| 236 // to the preceding text. | 239 // to the preceding text. |
| 237 if (_shouldMoveCommentBeforeSplit(comment.text)) { | 240 if (_shouldMoveCommentBeforeSplit(comment.text)) { |
| 238 _chunks.last.allowText(); | 241 _chunks.last.allowText(); |
| 239 } | 242 } |
| 240 | 243 |
| 241 // The comment follows other text, so we need to decide if it gets a | 244 // The comment follows other text, so we need to decide if it gets a |
| 242 // space before it or not. | 245 // space before it or not. |
| 243 if (_needsSpaceBeforeComment(isLineComment: comment.isLineComment)) { | 246 if (_needsSpaceBeforeComment(comment)) _writeText(" "); |
| 244 _writeText(" "); | |
| 245 } | |
| 246 } else { | 247 } else { |
| 247 // 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. |
| 248 _writeHardSplit( | 249 _writeHardSplit( |
| 249 flushLeft: comment.flushLeft, | 250 flushLeft: comment.flushLeft, |
| 250 isDouble: comment.linesBefore > 1, | 251 isDouble: comment.linesBefore > 1, |
| 251 nest: true); | 252 nest: true); |
| 252 } | 253 } |
| 253 | 254 |
| 254 _writeText(comment.text); | 255 _writeText(comment.text); |
| 255 | 256 |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 | 608 |
| 608 // Multi-line comments are always pushed to the next line. | 609 // Multi-line comments are always pushed to the next line. |
| 609 if (comment.contains("\n")) return false; | 610 if (comment.contains("\n")) return false; |
| 610 | 611 |
| 611 // If the text before the split is an open grouping character, we don't | 612 // If the text before the split is an open grouping character, we don't |
| 612 // want to adhere the comment to that. | 613 // want to adhere the comment to that. |
| 613 var text = _chunks.last.text; | 614 var text = _chunks.last.text; |
| 614 return !text.endsWith("(") && !text.endsWith("[") && !text.endsWith("{"); | 615 return !text.endsWith("(") && !text.endsWith("[") && !text.endsWith("{"); |
| 615 } | 616 } |
| 616 | 617 |
| 618 /// Returns `true` if [comment] appears to be a magic generic method comment. |
| 619 /// |
| 620 /// Those get spaced a little differently to look more like real syntax: |
| 621 /// |
| 622 /// int f/*<S, T>*/(int x) => 3; |
| 623 bool _isGenericMethodComment(SourceComment comment) { |
| 624 return comment.text.startsWith("/*<") || comment.text.startsWith("/*="); |
| 625 } |
| 626 |
| 617 /// Returns `true` if a space should be output between the end of the current | 627 /// Returns `true` if a space should be output between the end of the current |
| 618 /// output and the subsequent comment which is about to be written. | 628 /// output and the subsequent comment which is about to be written. |
| 619 /// | 629 /// |
| 620 /// This is only called if the comment is trailing text in the unformatted | 630 /// This is only called if the comment is trailing text in the unformatted |
| 621 /// source. In most cases, a space will be output to separate the comment | 631 /// source. In most cases, a space will be output to separate the comment |
| 622 /// from what precedes it. This returns false if: | 632 /// from what precedes it. This returns false if: |
| 623 /// | 633 /// |
| 624 /// * This comment does begin the line in the output even if it didn't in | 634 /// * This comment does begin the line in the output even if it didn't in |
| 625 /// the source. | 635 /// the source. |
| 626 /// * The comment is a block comment immediately following a grouping | 636 /// * The comment is a block comment immediately following a grouping |
| 627 /// character (`(`, `[`, or `{`). This is to allow `foo(/* comment */)`, | 637 /// character (`(`, `[`, or `{`). This is to allow `foo(/* comment */)`, |
| 628 /// et. al. | 638 /// et. al. |
| 629 bool _needsSpaceBeforeComment({bool isLineComment}) { | 639 bool _needsSpaceBeforeComment(SourceComment comment) { |
| 630 // Not at the start of the file. | 640 // Not at the start of the file. |
| 631 if (_chunks.isEmpty) return false; | 641 if (_chunks.isEmpty) return false; |
| 632 | 642 |
| 633 // Not at the start of a line. | 643 // Not at the start of a line. |
| 634 if (!_chunks.last.canAddText) return false; | 644 if (!_chunks.last.canAddText) return false; |
| 635 | 645 |
| 636 var text = _chunks.last.text; | 646 var text = _chunks.last.text; |
| 637 if (text.endsWith("\n")) return false; | 647 if (text.endsWith("\n")) return false; |
| 638 | 648 |
| 639 // Always put a space before line comments. | 649 // Always put a space before line comments. |
| 640 if (isLineComment) return true; | 650 if (comment.isLineComment) return true; |
| 651 |
| 652 // Magic generic method comments like "Foo/*<T>*/" don't get spaces. |
| 653 if (_isGenericMethodComment(comment) && |
| 654 _trailingIdentifierChar.hasMatch(text)) { |
| 655 return false; |
| 656 } |
| 641 | 657 |
| 642 // Block comments do not get a space if following a grouping character. | 658 // Block comments do not get a space if following a grouping character. |
| 643 return !text.endsWith("(") && !text.endsWith("[") && !text.endsWith("{"); | 659 return !text.endsWith("(") && !text.endsWith("[") && !text.endsWith("{"); |
| 644 } | 660 } |
| 645 | 661 |
| 646 /// Returns `true` if a space should be output after the last comment which | 662 /// Returns `true` if a space should be output after the last comment which |
| 647 /// was just written and the token that will be written. | 663 /// was just written and the token that will be written. |
| 648 bool _needsSpaceAfterLastComment(List<SourceComment> comments, String token) { | 664 bool _needsSpaceAfterLastComment(List<SourceComment> comments, String token) { |
| 649 // Not if there are no comments. | 665 // Not if there are no comments. |
| 650 if (comments.isEmpty) return false; | 666 if (comments.isEmpty) return false; |
| 651 | 667 |
| 652 // Not at the beginning of a line. | 668 // Not at the beginning of a line. |
| 653 if (!_chunks.last.canAddText) return false; | 669 if (!_chunks.last.canAddText) return false; |
| 654 | 670 |
| 671 // Magic generic method comments like "Foo/*<T>*/" don't get spaces. |
| 672 if (_isGenericMethodComment(comments.last) && token == "(") { |
| 673 return false; |
| 674 } |
| 675 |
| 655 // Otherwise, it gets a space if the following token is not a delimiter or | 676 // Otherwise, it gets a space if the following token is not a delimiter or |
| 656 // the empty string, for EOF. | 677 // the empty string, for EOF. |
| 657 return token != ")" && | 678 return token != ")" && |
| 658 token != "]" && | 679 token != "]" && |
| 659 token != "}" && | 680 token != "}" && |
| 660 token != "," && | 681 token != "," && |
| 661 token != ";" && | 682 token != ";" && |
| 662 token != ""; | 683 token != ""; |
| 663 } | 684 } |
| 664 | 685 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 781 | 802 |
| 782 // Discard spans in hardened chunks since we know for certain they will | 803 // Discard spans in hardened chunks since we know for certain they will |
| 783 // split anyway. | 804 // split anyway. |
| 784 for (var chunk in _chunks) { | 805 for (var chunk in _chunks) { |
| 785 if (chunk.rule != null && chunk.rule.isHardened) { | 806 if (chunk.rule != null && chunk.rule.isHardened) { |
| 786 chunk.spans.clear(); | 807 chunk.spans.clear(); |
| 787 } | 808 } |
| 788 } | 809 } |
| 789 } | 810 } |
| 790 } | 811 } |
| OLD | NEW |