From 951392005b3adc482c125f1a80dcbd2967732aed Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 18 Jul 2017 19:36:08 +0200 Subject: [PATCH] Add options for wrapping local variable and property annotations #KT-14950 Fixed --- .../idea/formatter/KotlinCommonBlock.kt | 43 +++++++++++++++---- ...KotlinLanguageCodeStyleSettingsProvider.kt | 6 +++ .../LocalVariableAnnotationWrap.after.kt | 7 +++ .../formatter/LocalVariableAnnotationWrap.kt | 5 +++ .../formatter/PropertyAnnotationWrap.after.kt | 5 +++ .../formatter/PropertyAnnotationWrap.kt | 3 ++ .../formatter/SpacesInDeclarations.after.kt | 19 ++++++-- .../unchangedElements.kt.after | 3 +- .../annotationWithUseSite.kt.after | 3 +- .../propertyAnnotation.kt.after | 3 +- .../formatter/FormatterTestGenerated.java | 12 ++++++ 11 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 idea/testData/formatter/LocalVariableAnnotationWrap.after.kt create mode 100644 idea/testData/formatter/LocalVariableAnnotationWrap.kt create mode 100644 idea/testData/formatter/PropertyAnnotationWrap.after.kt create mode 100644 idea/testData/formatter/PropertyAnnotationWrap.kt diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt index e5b8fe17413..ed8ab20b2b5 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt @@ -42,6 +42,7 @@ private val KDOC_CONTENT = TokenSet.create(KDocTokens.KDOC, KDocElementTypes.KDO private val CODE_BLOCKS = TokenSet.create(KtNodeTypes.BLOCK, KtNodeTypes.CLASS_BODY, KtNodeTypes.FUNCTION_LITERAL) private val ALIGN_FOR_BINARY_OPERATIONS = TokenSet.create(MUL, DIV, PERC, PLUS, MINUS, ELVIS, LT, GT, LTEQ, GTEQ, ANDAND, OROR) +private val ANNOTATIONS = TokenSet.create(KtNodeTypes.ANNOTATION_ENTRY, KtNodeTypes.ANNOTATION) val CodeStyleSettings.kotlinSettings get() = getCustomSettings(KotlinCodeStyleSettings::class.java) @@ -322,6 +323,7 @@ abstract class KotlinCommonBlock( private fun getWrappingStrategy(): WrappingStrategy { val commonSettings = settings.getCommonSettings(KotlinLanguage.INSTANCE) val elementType = node.elementType + val nodePsi = node.psi when { elementType === KtNodeTypes.VALUE_ARGUMENT_LIST -> @@ -355,29 +357,44 @@ abstract class KotlinCommonBlock( elementType === KtNodeTypes.CLASS_BODY -> return getWrappingStrategyForItemList(commonSettings.ENUM_CONSTANTS_WRAP, KtNodeTypes.ENUM_ENTRY) - elementType === KtNodeTypes.MODIFIER_LIST -> - when (node.treeParent.psi) { + elementType === KtNodeTypes.MODIFIER_LIST -> { + val parent = node.treeParent.psi + when (parent) { is KtParameter -> return getWrappingStrategyForItemList(commonSettings.PARAMETER_ANNOTATION_WRAP, - KtNodeTypes.ANNOTATION_ENTRY, + ANNOTATIONS, !node.treeParent.isFirstParameter()) is KtClassOrObject -> return getWrappingStrategyForItemList(commonSettings.CLASS_ANNOTATION_WRAP, - KtNodeTypes.ANNOTATION_ENTRY) + ANNOTATIONS) is KtNamedFunction -> return getWrappingStrategyForItemList(commonSettings.METHOD_ANNOTATION_WRAP, - KtNodeTypes.ANNOTATION_ENTRY) + ANNOTATIONS) + + is KtProperty -> + return getWrappingStrategyForItemList(if (parent.isLocal) + commonSettings.VARIABLE_ANNOTATION_WRAP + else + commonSettings.FIELD_ANNOTATION_WRAP, + ANNOTATIONS) } + } elementType === KtNodeTypes.VALUE_PARAMETER -> return wrapAfterAnnotation(commonSettings.PARAMETER_ANNOTATION_WRAP) - node.psi is KtClassOrObject -> + nodePsi is KtClassOrObject -> return wrapAfterAnnotation(commonSettings.CLASS_ANNOTATION_WRAP) - node.psi is KtNamedFunction -> + nodePsi is KtNamedFunction -> return wrapAfterAnnotation(commonSettings.METHOD_ANNOTATION_WRAP) + + nodePsi is KtProperty -> + return wrapAfterAnnotation(if (nodePsi.isLocal) + commonSettings.VARIABLE_ANNOTATION_WRAP + else + commonSettings.FIELD_ANNOTATION_WRAP) } return WrappingStrategy.NoWrapping @@ -391,12 +408,13 @@ private fun ASTNode.isFirstParameter(): Boolean = treePrev.elementType == KtToke private fun wrapAfterAnnotation(wrapType: Int): WrappingStrategy { return object : WrappingStrategy { override fun getWrap(childElement: ASTNode): Wrap? { + if (childElement.elementType in KtTokens.COMMENTS) return null var prevLeaf = childElement.treePrev while (prevLeaf?.elementType == TokenType.WHITE_SPACE) { prevLeaf = prevLeaf.treePrev } if (prevLeaf?.elementType == KtNodeTypes.MODIFIER_LIST) { - if (prevLeaf?.lastChildNode?.elementType == KtNodeTypes.ANNOTATION_ENTRY) { + if (prevLeaf?.lastChildNode?.elementType in ANNOTATIONS) { return Wrap.createWrap(wrapType, true) } } @@ -579,6 +597,15 @@ private fun getWrappingStrategyForItemList(wrapType: Int, itemType: IElementType } } +private fun getWrappingStrategyForItemList(wrapType: Int, itemTypes: TokenSet, wrapFirstElement: Boolean = false): WrappingStrategy { + val itemWrap = Wrap.createWrap(wrapType, wrapFirstElement) + return object : WrappingStrategy { + override fun getWrap(childElement: ASTNode): Wrap? { + return if (childElement.elementType in itemTypes) itemWrap else null + } + } +} + private fun findNodeBlockIndex(blocks: List, tokenSet: TokenSet): Int { return blocks.indexOfFirst { block -> if (block !is ASTBlock) return@indexOfFirst false diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt index ef203160d3b..3e69b397f4a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt @@ -49,9 +49,12 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide fun longMethod(@Named("param1") param1: Int, param2: String) { + @Deprecated val foo = 1 } } + @Deprecated val bar = 1 + enum class Enumeration { A, B } @@ -238,6 +241,8 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide "METHOD_ANNOTATION_WRAP", "CLASS_ANNOTATION_WRAP", "PARAMETER_ANNOTATION_WRAP", + "VARIABLE_ANNOTATION_WRAP", + "FIELD_ANNOTATION_WRAP", "METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE", "METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE", "CALL_PARAMETERS_LPAREN_ON_NEXT_LINE", @@ -245,6 +250,7 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide "ENUM_CONSTANTS_WRAP" ) consumer.renameStandardOption(CodeStyleSettingsCustomizable.WRAPPING_SWITCH_STATEMENT, "'when' statements") + consumer.renameStandardOption("FIELD_ANNOTATION_WRAP", "Property annotations") showCustomOption(KotlinCodeStyleSettings::ALIGN_IN_COLUMNS_CASE_BRANCH, "Align 'when' branches in columns", CodeStyleSettingsCustomizable.WRAPPING_SWITCH_STATEMENT) diff --git a/idea/testData/formatter/LocalVariableAnnotationWrap.after.kt b/idea/testData/formatter/LocalVariableAnnotationWrap.after.kt new file mode 100644 index 00000000000..b64e846ec56 --- /dev/null +++ b/idea/testData/formatter/LocalVariableAnnotationWrap.after.kt @@ -0,0 +1,7 @@ +fun foo() { + @Deprecated + @Named("foo") + val bar = 1 +} + +// SET_INT: VARIABLE_ANNOTATION_WRAP = 2 diff --git a/idea/testData/formatter/LocalVariableAnnotationWrap.kt b/idea/testData/formatter/LocalVariableAnnotationWrap.kt new file mode 100644 index 00000000000..11853fc0f30 --- /dev/null +++ b/idea/testData/formatter/LocalVariableAnnotationWrap.kt @@ -0,0 +1,5 @@ +fun foo() { + @Deprecated @Named("foo") val bar = 1 +} + +// SET_INT: VARIABLE_ANNOTATION_WRAP = 2 diff --git a/idea/testData/formatter/PropertyAnnotationWrap.after.kt b/idea/testData/formatter/PropertyAnnotationWrap.after.kt new file mode 100644 index 00000000000..940e25d2293 --- /dev/null +++ b/idea/testData/formatter/PropertyAnnotationWrap.after.kt @@ -0,0 +1,5 @@ +@Deprecated +@Named("foo") +val bar = 1 + +// SET_INT: FIELD_ANNOTATION_WRAP = 2 diff --git a/idea/testData/formatter/PropertyAnnotationWrap.kt b/idea/testData/formatter/PropertyAnnotationWrap.kt new file mode 100644 index 00000000000..4e72ba39cb0 --- /dev/null +++ b/idea/testData/formatter/PropertyAnnotationWrap.kt @@ -0,0 +1,3 @@ +@Deprecated @Named("foo") val bar = 1 + +// SET_INT: FIELD_ANNOTATION_WRAP = 2 diff --git a/idea/testData/formatter/SpacesInDeclarations.after.kt b/idea/testData/formatter/SpacesInDeclarations.after.kt index 19b12c610fc..ad72c4087d2 100644 --- a/idea/testData/formatter/SpacesInDeclarations.after.kt +++ b/idea/testData/formatter/SpacesInDeclarations.after.kt @@ -67,7 +67,12 @@ annotation class A1 annotation class A2 -private @[A1 A2 A1] @A1 @A2 @[A1 A2 A2] @[A1] val fooProp1 = 1 +private @[A1 A2 A1] +@A1 +@A2 +@[A1 A2 A2] +@[A1] +val fooProp1 = 1 private @[ @@ -75,17 +80,23 @@ private @[ A1 -A2 A1] @A1 @A2 @[A1 +A2 A1] +@A1 +@A2 +@[A1 A2 A2 -] @[A1] val fooProp1 = 1 +] +@[A1] +val fooProp1 = 1 private @A1 -@A2 val +@A2 +val fooProp2 = 1 diff --git a/idea/testData/intentions/convertFunctionToProperty/unchangedElements.kt.after b/idea/testData/intentions/convertFunctionToProperty/unchangedElements.kt.after index b30130646ea..39289e9d6c2 100644 --- a/idea/testData/intentions/convertFunctionToProperty/unchangedElements.kt.after +++ b/idea/testData/intentions/convertFunctionToProperty/unchangedElements.kt.after @@ -4,7 +4,8 @@ annotation class X(val s: String) class A(val n: Int) { val t = 1 - internal @X("1") val T.foo: Boolean + internal @X("1") + val T.foo: Boolean get() = toInt() - n > 1 val u = 2 } diff --git a/idea/testData/intentions/movePropertyToClassBody/annotationWithUseSite.kt.after b/idea/testData/intentions/movePropertyToClassBody/annotationWithUseSite.kt.after index 4e7e67384cc..4aeb626c208 100644 --- a/idea/testData/intentions/movePropertyToClassBody/annotationWithUseSite.kt.after +++ b/idea/testData/intentions/movePropertyToClassBody/annotationWithUseSite.kt.after @@ -4,5 +4,6 @@ annotation class Annotation3(val a: Int = 0) class TestClass(@Annotation1(42) @Annotation3(42) text: String = "LoremIpsum") { - private @Annotation1(42) @field:Annotation2(42) val text = text + private @Annotation1(42) @field:Annotation2(42) + val text = text } \ No newline at end of file diff --git a/idea/testData/intentions/movePropertyToClassBody/propertyAnnotation.kt.after b/idea/testData/intentions/movePropertyToClassBody/propertyAnnotation.kt.after index 69de4740fbe..2a986e0a172 100644 --- a/idea/testData/intentions/movePropertyToClassBody/propertyAnnotation.kt.after +++ b/idea/testData/intentions/movePropertyToClassBody/propertyAnnotation.kt.after @@ -3,5 +3,6 @@ annotation class PropertyAnnotation(val a: Int = 0) class TestClass(text: String = "LoremIpsum") { - private @PropertyAnnotation(42) val text = text + private @PropertyAnnotation(42) + val text = text } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java index cf36b34c81b..4af2983e2ad 100644 --- a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java @@ -500,6 +500,12 @@ public class FormatterTestGenerated extends AbstractFormatterTest { doTest(fileName); } + @TestMetadata("LocalVariableAnnotationWrap.after.kt") + public void testLocalVariableAnnotationWrap() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/LocalVariableAnnotationWrap.after.kt"); + doTest(fileName); + } + @TestMetadata("LoopParameterWithExplicitType.after.kt") public void testLoopParameterWithExplicitType() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/LoopParameterWithExplicitType.after.kt"); @@ -614,6 +620,12 @@ public class FormatterTestGenerated extends AbstractFormatterTest { doTest(fileName); } + @TestMetadata("PropertyAnnotationWrap.after.kt") + public void testPropertyAnnotationWrap() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/PropertyAnnotationWrap.after.kt"); + doTest(fileName); + } + @TestMetadata("PropertyTypeParameterList.after.kt") public void testPropertyTypeParameterList() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/PropertyTypeParameterList.after.kt");