Add options for wrapping local variable and property annotations
#KT-14950 Fixed
This commit is contained in:
@@ -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<Block>, tokenSet: TokenSet): Int {
|
||||
return blocks.indexOfFirst { block ->
|
||||
if (block !is ASTBlock) return@indexOfFirst false
|
||||
|
||||
+6
@@ -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)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo() {
|
||||
@Deprecated
|
||||
@Named("foo")
|
||||
val bar = 1
|
||||
}
|
||||
|
||||
// SET_INT: VARIABLE_ANNOTATION_WRAP = 2
|
||||
@@ -0,0 +1,5 @@
|
||||
fun foo() {
|
||||
@Deprecated @Named("foo") val bar = 1
|
||||
}
|
||||
|
||||
// SET_INT: VARIABLE_ANNOTATION_WRAP = 2
|
||||
@@ -0,0 +1,5 @@
|
||||
@Deprecated
|
||||
@Named("foo")
|
||||
val bar = 1
|
||||
|
||||
// SET_INT: FIELD_ANNOTATION_WRAP = 2
|
||||
@@ -0,0 +1,3 @@
|
||||
@Deprecated @Named("foo") val bar = 1
|
||||
|
||||
// SET_INT: FIELD_ANNOTATION_WRAP = 2
|
||||
+15
-4
@@ -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
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -4,7 +4,8 @@ annotation class X(val s: String)
|
||||
|
||||
class A(val n: Int) {
|
||||
val t = 1
|
||||
internal @X("1") val <T : Number> T.foo: Boolean
|
||||
internal @X("1")
|
||||
val <T : Number> T.foo: Boolean
|
||||
get() = toInt() - n > 1
|
||||
val u = 2
|
||||
}
|
||||
|
||||
+2
-1
@@ -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
|
||||
}
|
||||
+2
-1
@@ -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
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user