From 6c62b60147f387bcdac398ec2746a46ee8a52a4f Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 22 Jun 2017 19:39:52 +0200 Subject: [PATCH] Implement option for wrapping parameter annotations --- .../idea/formatter/KotlinCommonBlock.kt | 46 +++++++++++++++++-- .../KotlinFormattingModelBuilder.java | 5 +- ...KotlinLanguageCodeStyleSettingsProvider.kt | 3 +- .../ParameterAnnotationWrap.after.kt | 7 +++ .../formatter/ParameterAnnotationWrap.kt | 3 ++ .../formatter/FormatterTestGenerated.java | 6 +++ 6 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 idea/testData/formatter/ParameterAnnotationWrap.after.kt create mode 100644 idea/testData/formatter/ParameterAnnotationWrap.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 d57bcd007cb..c1c57a973ce 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt @@ -332,7 +332,15 @@ abstract class KotlinCommonBlock( if (parentElementType === KtNodeTypes.FUN || parentElementType === KtNodeTypes.PRIMARY_CONSTRUCTOR || parentElementType === KtNodeTypes.SECONDARY_CONSTRUCTOR) { - return getWrappingStrategyForItemList(commonSettings.METHOD_PARAMETERS_WRAP, KtNodeTypes.VALUE_PARAMETER) + val wrap = Wrap.createWrap(commonSettings.METHOD_PARAMETERS_WRAP, false) + return object : WrappingStrategy { + override fun getWrap(childElement: ASTNode): Wrap? { + return if (childElement.elementType === KtNodeTypes.VALUE_PARAMETER && !childElement.startsWithAnnotation()) + wrap + else + null + } + } } } @@ -343,12 +351,44 @@ abstract class KotlinCommonBlock( if (childElement.psi is KtSuperTypeListEntry) wrap else null } } + + elementType === KtNodeTypes.MODIFIER_LIST -> + when (node.treeParent.elementType) { + KtNodeTypes.VALUE_PARAMETER -> + return getWrappingStrategyForItemList(commonSettings.PARAMETER_ANNOTATION_WRAP, + KtNodeTypes.ANNOTATION_ENTRY, + !node.treeParent.isFirstParameter()) + } + + elementType === KtNodeTypes.VALUE_PARAMETER -> + return wrapAfterAnnotation(commonSettings.PARAMETER_ANNOTATION_WRAP) } return WrappingStrategy.NoWrapping } } +private fun ASTNode.startsWithAnnotation() = firstChildNode?.firstChildNode?.elementType == KtNodeTypes.ANNOTATION_ENTRY + +private fun ASTNode.isFirstParameter(): Boolean = treePrev.elementType == KtTokens.LPAR + +private fun wrapAfterAnnotation(wrapType: Int): WrappingStrategy { + return object : WrappingStrategy { + override fun getWrap(childElement: ASTNode): Wrap? { + 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) { + return Wrap.createWrap(wrapType, true) + } + } + return null + } + } +} + private val INDENT_RULES = arrayOf( strategy("No indent for braces in blocks") .within(KtNodeTypes.BLOCK, KtNodeTypes.CLASS_BODY, KtNodeTypes.FUNCTION_LITERAL) @@ -502,8 +542,8 @@ private fun getPrevWithoutWhitespaceAndComments(pNode: ASTNode?): ASTNode? { return node } -private fun getWrappingStrategyForItemList(wrapType: Int, itemType: IElementType): WrappingStrategy { - val itemWrap = Wrap.createWrap(wrapType, false) +private fun getWrappingStrategyForItemList(wrapType: Int, itemType: IElementType, wrapFirstElement: Boolean = false): WrappingStrategy { + val itemWrap = Wrap.createWrap(wrapType, wrapFirstElement) return object : WrappingStrategy { override fun getWrap(childElement: ASTNode): Wrap? { return if (childElement.elementType === itemType) itemWrap else null diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinFormattingModelBuilder.java b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinFormattingModelBuilder.java index 67dc25bea63..7b95ab5b2fe 100644 --- a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinFormattingModelBuilder.java +++ b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinFormattingModelBuilder.java @@ -16,10 +16,7 @@ package org.jetbrains.kotlin.idea.formatter; -import com.intellij.formatting.FormattingModel; -import com.intellij.formatting.FormattingModelBuilder; -import com.intellij.formatting.FormattingModelProvider; -import com.intellij.formatting.Indent; +import com.intellij.formatting.*; import com.intellij.lang.ASTNode; import com.intellij.openapi.editor.impl.DocumentImpl; import com.intellij.openapi.util.TextRange; diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt index cd02a3d6dea..e7d1ac493f1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt @@ -47,7 +47,7 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide } catch (e: Exception) { return 0 } finally { if (true) { return 1 } else { return 2 } } } private val f = {(a: Int)->a*2} - fun longMethod(param1: Int, + fun longMethod(@Named("param1") param1: Int, param2: String) { } } @@ -236,6 +236,7 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide "CALL_PARAMETERS_WRAP", "METHOD_PARAMETERS_WRAP", "EXTENDS_LIST_WRAP", + "PARAMETER_ANNOTATION_WRAP", "METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE", "METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE", "CALL_PARAMETERS_LPAREN_ON_NEXT_LINE", diff --git a/idea/testData/formatter/ParameterAnnotationWrap.after.kt b/idea/testData/formatter/ParameterAnnotationWrap.after.kt new file mode 100644 index 00000000000..52c559b9c48 --- /dev/null +++ b/idea/testData/formatter/ParameterAnnotationWrap.after.kt @@ -0,0 +1,7 @@ +fun foo(@Deprecated("x") + x: Int, + @Deprecated("y") + @Deprecated("z") + y: Int) + +// SET_INT: PARAMETER_ANNOTATION_WRAP = 2 diff --git a/idea/testData/formatter/ParameterAnnotationWrap.kt b/idea/testData/formatter/ParameterAnnotationWrap.kt new file mode 100644 index 00000000000..6c4fc30e99b --- /dev/null +++ b/idea/testData/formatter/ParameterAnnotationWrap.kt @@ -0,0 +1,3 @@ +fun foo(@Deprecated("x") x: Int, @Deprecated("y") @Deprecated("z") y: Int) + +// SET_INT: PARAMETER_ANNOTATION_WRAP = 2 diff --git a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java index 7b5a6e0cbcc..4866a291371 100644 --- a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java @@ -554,6 +554,12 @@ public class FormatterTestGenerated extends AbstractFormatterTest { doTest(fileName); } + @TestMetadata("ParameterAnnotationWrap.after.kt") + public void testParameterAnnotationWrap() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/ParameterAnnotationWrap.after.kt"); + doTest(fileName); + } + @TestMetadata("ParameterDocComments.after.kt") public void testParameterDocComments() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/ParameterDocComments.after.kt");