From 7f8d6b300883d54cd79d687aa5dd2fc52d4cffde Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Wed, 5 Jul 2017 20:17:54 +0300 Subject: [PATCH] Don't move line and /**/ comments during reformat (KT-18805) #KT-18805 Fixed --- .../idea/formatter/kotlinSpacingRules.kt | 55 +++++++++++-------- .../formatter/DanglingComments.after.kt | 13 +++++ idea/testData/formatter/DanglingComments.kt | 13 +++++ .../keepComments/2.kt.after | 2 +- .../keepComments/3.kt.after | 2 +- .../keepComments/4.kt.after | 2 +- .../useExpressionBody/if.kt.after | 2 +- .../formatter/FormatterTestGenerated.java | 6 ++ .../fileOrElement/comments/comments.kt | 2 +- .../fileOrElement/comments/comments2.kt | 4 +- 10 files changed, 70 insertions(+), 31 deletions(-) create mode 100644 idea/testData/formatter/DanglingComments.after.kt create mode 100644 idea/testData/formatter/DanglingComments.kt diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/kotlinSpacingRules.kt b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/kotlinSpacingRules.kt index 7722f7513e9..6c419b9f934 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/kotlinSpacingRules.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/kotlinSpacingRules.kt @@ -58,7 +58,36 @@ fun createSpacingBuilder(settings: CodeStyleSettings, builderUtil: KotlinSpacing val DECLARATIONS = TokenSet.create(PROPERTY, FUN, CLASS, OBJECT_DECLARATION, ENUM_ENTRY, SECONDARY_CONSTRUCTOR, CLASS_INITIALIZER) + simple { + before(FILE_ANNOTATION_LIST).lineBreakInCode() + after(FILE_ANNOTATION_LIST).blankLines(1) + + after(PACKAGE_DIRECTIVE).blankLines(1) + between(IMPORT_DIRECTIVE, IMPORT_DIRECTIVE).lineBreakInCode() + after(IMPORT_LIST).blankLines(1) + } + custom { + fun commentSpacing(minSpaces: Int): Spacing { + if (commonCodeStyleSettings.KEEP_FIRST_COLUMN_COMMENT) { + return Spacing.createKeepingFirstColumnSpacing(minSpaces, Int.MAX_VALUE, settings.KEEP_LINE_BREAKS, commonCodeStyleSettings.KEEP_BLANK_LINES_IN_CODE) + } + return Spacing.createSpacing(minSpaces, Int.MAX_VALUE, 0, settings.KEEP_LINE_BREAKS, commonCodeStyleSettings.KEEP_BLANK_LINES_IN_CODE) + } + + // Several line comments happened to be generated in one line + inPosition(parent = null, left = EOL_COMMENT, right = EOL_COMMENT).customRule { _, _, right -> + val nodeBeforeRight = right.node.treePrev + if (nodeBeforeRight is PsiWhiteSpace && !nodeBeforeRight.textContains('\n')) { + createSpacing(0, minLineFeeds = 1) + } + else { + null + } + } + inPosition(right = BLOCK_COMMENT).spacing(commentSpacing(0)) + inPosition(right = EOL_COMMENT).spacing(commentSpacing(1)) + inPosition(left = CLASS, right = CLASS).emptyLinesIfLineBreakInLeft(1) inPosition(left = CLASS, right = OBJECT_DECLARATION).emptyLinesIfLineBreakInLeft(1) inPosition(left = OBJECT_DECLARATION, right = OBJECT_DECLARATION).emptyLinesIfLineBreakInLeft(1) @@ -78,7 +107,8 @@ fun createSpacingBuilder(settings: CodeStyleSettings, builderUtil: KotlinSpacing val klass = parent.node.treeParent.psi as? KtClass ?: return@customRule null if (klass.isEnum() && right.node.elementType in DECLARATIONS) { createSpacing(0, minLineFeeds = 2, keepBlankLines = settings.KEEP_BLANK_LINES_IN_DECLARATIONS) - } else null + } + else null } inPosition(parent = CLASS_BODY, left = LBRACE).customRule { parent, left, right -> @@ -114,13 +144,6 @@ fun createSpacingBuilder(settings: CodeStyleSettings, builderUtil: KotlinSpacing simple { // ============ Line breaks ============== - before(FILE_ANNOTATION_LIST).lineBreakInCode() - after(FILE_ANNOTATION_LIST).blankLines(1) - - after(PACKAGE_DIRECTIVE).blankLines(1) - between(IMPORT_DIRECTIVE, IMPORT_DIRECTIVE).lineBreakInCode() - after(IMPORT_LIST).blankLines(1) - before(DOC_COMMENT).lineBreakInCode() between(PROPERTY, PROPERTY).lineBreakInCode() @@ -343,22 +366,6 @@ fun createSpacingBuilder(settings: CodeStyleSettings, builderUtil: KotlinSpacing spacingForLeftBrace(right.node!!.firstChildNode) } - if (kotlinCommonSettings.KEEP_FIRST_COLUMN_COMMENT) { - inPosition(parent = null, left = EOL_COMMENT, right = EOL_COMMENT).customRule { _, _, right -> - val nodeBeforeRight = right.node.treePrev - if (nodeBeforeRight is PsiWhiteSpace && !nodeBeforeRight.textContains('\n')) { - // Several line comments happened to be generated in one line - createSpacing(0, minLineFeeds = 1) - } - else { - null - } - } - - inPosition(rightSet = TokenSet.create(EOL_COMMENT, BLOCK_COMMENT)).spacing( - Spacing.createKeepingFirstColumnSpacing(0, Integer.MAX_VALUE, settings.KEEP_LINE_BREAKS, kotlinCommonSettings.KEEP_BLANK_LINES_IN_CODE)) - } - // Add space after a semicolon if there is another child at the same line inPosition(left = SEMICOLON).customRule { _, left, _ -> val nodeAfterLeft = left.node.treeNext diff --git a/idea/testData/formatter/DanglingComments.after.kt b/idea/testData/formatter/DanglingComments.after.kt new file mode 100644 index 00000000000..30aa7cf657a --- /dev/null +++ b/idea/testData/formatter/DanglingComments.after.kt @@ -0,0 +1,13 @@ +fun x1() = // cx1 + 42 + +fun x2() = /* cx2 */ + 42 + +fun x3() { + 1 + // cx4_1 + 2 + + 1 + /* cx4_2 */ + 2 +} \ No newline at end of file diff --git a/idea/testData/formatter/DanglingComments.kt b/idea/testData/formatter/DanglingComments.kt new file mode 100644 index 00000000000..089693098b6 --- /dev/null +++ b/idea/testData/formatter/DanglingComments.kt @@ -0,0 +1,13 @@ +fun x1() = // cx1 + 42 + +fun x2() = /* cx2 */ + 42 + +fun x3() { + 1 + // cx4_1 + 2 + + 1 + /* cx4_2 */ + 2 +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/useExpressionBody/convertToExpressionBody/keepComments/2.kt.after b/idea/testData/inspectionsLocal/useExpressionBody/convertToExpressionBody/keepComments/2.kt.after index 87ff51102a2..ffbe02a85ab 100644 --- a/idea/testData/inspectionsLocal/useExpressionBody/convertToExpressionBody/keepComments/2.kt.after +++ b/idea/testData/inspectionsLocal/useExpressionBody/convertToExpressionBody/keepComments/2.kt.after @@ -1,2 +1,2 @@ -fun getText(): String = // let's return xxx +fun getText(): String =// let's return xxx "xxx" //TODO diff --git a/idea/testData/inspectionsLocal/useExpressionBody/convertToExpressionBody/keepComments/3.kt.after b/idea/testData/inspectionsLocal/useExpressionBody/convertToExpressionBody/keepComments/3.kt.after index b1518de3dc8..e8dd7b52cab 100644 --- a/idea/testData/inspectionsLocal/useExpressionBody/convertToExpressionBody/keepComments/3.kt.after +++ b/idea/testData/inspectionsLocal/useExpressionBody/convertToExpressionBody/keepComments/3.kt.after @@ -1,2 +1,2 @@ -fun getText(): String = // let's return xxx +fun getText(): String =// let's return xxx "xxx" \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/useExpressionBody/convertToExpressionBody/keepComments/4.kt.after b/idea/testData/inspectionsLocal/useExpressionBody/convertToExpressionBody/keepComments/4.kt.after index 7a2b092320f..01cf2ef0bf2 100644 --- a/idea/testData/inspectionsLocal/useExpressionBody/convertToExpressionBody/keepComments/4.kt.after +++ b/idea/testData/inspectionsLocal/useExpressionBody/convertToExpressionBody/keepComments/4.kt.after @@ -1,2 +1,2 @@ -fun getText(): String = /* let's return xxx */ +fun getText(): String =/* let's return xxx */ "xxx" /* TODO */ \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/useExpressionBody/if.kt.after b/idea/testData/inspectionsLocal/useExpressionBody/if.kt.after index bb1db25e68c..7c1e59246d4 100644 --- a/idea/testData/inspectionsLocal/useExpressionBody/if.kt.after +++ b/idea/testData/inspectionsLocal/useExpressionBody/if.kt.after @@ -1,6 +1,6 @@ // HIGHLIGHT: INFORMATION -fun abs(x: Int): Int = // No highlighting here +fun abs(x: Int): Int =// No highlighting here if (x > 0) { x } diff --git a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java index 50c76e4f7a1..c0e71823d68 100644 --- a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java @@ -218,6 +218,12 @@ public class FormatterTestGenerated extends AbstractFormatterTest { doTest(fileName); } + @TestMetadata("DanglingComments.after.kt") + public void testDanglingComments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/DanglingComments.after.kt"); + doTest(fileName); + } + @TestMetadata("DelegationList.after.kt") public void testDelegationList() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/DelegationList.after.kt"); diff --git a/j2k/testData/fileOrElement/comments/comments.kt b/j2k/testData/fileOrElement/comments/comments.kt index 4796775a2b7..2309f20c103 100644 --- a/j2k/testData/fileOrElement/comments/comments.kt +++ b/j2k/testData/fileOrElement/comments/comments.kt @@ -8,7 +8,7 @@ import java.util.ArrayList // we need ArrayList // let's declare a class: internal class A /* just a sample name*/ : Runnable /* let's implement Runnable */ { - fun foo/* again a sample name */(p: Int /* parameter p */, c: Char /* parameter c */) { + fun foo /* again a sample name */(p: Int /* parameter p */, c: Char /* parameter c */) { // let's print something: println("1") // print 1 println("2") // print 2 diff --git a/j2k/testData/fileOrElement/comments/comments2.kt b/j2k/testData/fileOrElement/comments/comments2.kt index fb3cca64e4a..06270f6f244 100644 --- a/j2k/testData/fileOrElement/comments/comments2.kt +++ b/j2k/testData/fileOrElement/comments/comments2.kt @@ -12,11 +12,11 @@ internal class A { fun /* we return int*/ foo(/*int*/ p: Int/* parameter p */): Int { /* body is empty */ } - private /*it's private*/ val field = 0 + private/*it's private*/ val field = 0 /*it's public*/ fun foo(s: String): Char {} - protected /*it's protected*/ fun foo(c: Char) {} + protected/*it's protected*/ fun foo(c: Char) {} /** * Method description.