Option to use continuation indent in expression bodies (KT-9818)
This commit is contained in:
+1
@@ -41,6 +41,7 @@ public class KotlinCodeStyleSettings extends CustomCodeStyleSettings {
|
|||||||
public int NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS = ApplicationManager.getApplication().isUnitTestMode() ? Integer.MAX_VALUE : 3;
|
public int NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS = ApplicationManager.getApplication().isUnitTestMode() ? Integer.MAX_VALUE : 3;
|
||||||
public boolean IMPORT_NESTED_CLASSES = false;
|
public boolean IMPORT_NESTED_CLASSES = false;
|
||||||
public boolean CONTINUATION_INDENT_IN_PARAMETER_LISTS = true;
|
public boolean CONTINUATION_INDENT_IN_PARAMETER_LISTS = true;
|
||||||
|
public boolean CONTINUATION_INDENT_FOR_EXPRESSION_BODIES = true;
|
||||||
|
|
||||||
public KotlinCodeStyleSettings(CodeStyleSettings container) {
|
public KotlinCodeStyleSettings(CodeStyleSettings container) {
|
||||||
super("JetCodeStyleSettings", container);
|
super("JetCodeStyleSettings", container);
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ import org.jetbrains.kotlin.kdoc.lexer.KDocTokens
|
|||||||
import org.jetbrains.kotlin.kdoc.parser.KDocElementTypes
|
import org.jetbrains.kotlin.kdoc.parser.KDocElementTypes
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens.*
|
import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||||
|
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
private val QUALIFIED_OPERATION = TokenSet.create(DOT, SAFE_ACCESS)
|
private val QUALIFIED_OPERATION = TokenSet.create(DOT, SAFE_ACCESS)
|
||||||
@@ -361,6 +363,18 @@ private val INDENT_RULES = arrayOf<NodeIndentStrategy>(
|
|||||||
.within(KtNodeTypes.THEN, KtNodeTypes.ELSE).notForType(KtNodeTypes.BLOCK)
|
.within(KtNodeTypes.THEN, KtNodeTypes.ELSE).notForType(KtNodeTypes.BLOCK)
|
||||||
.set(Indent.getNormalIndent()),
|
.set(Indent.getNormalIndent()),
|
||||||
|
|
||||||
|
strategy("Expression body")
|
||||||
|
.within(KtNodeTypes.FUN)
|
||||||
|
.forElement {
|
||||||
|
it.psi is KtExpression && it.psi !is KtBlockExpression
|
||||||
|
}
|
||||||
|
.set { settings ->
|
||||||
|
if (settings.kotlinSettings.CONTINUATION_INDENT_FOR_EXPRESSION_BODIES)
|
||||||
|
Indent.getContinuationIndent()
|
||||||
|
else
|
||||||
|
Indent.getNormalIndent()
|
||||||
|
},
|
||||||
|
|
||||||
strategy("Indent for parts")
|
strategy("Indent for parts")
|
||||||
.within(KtNodeTypes.PROPERTY, KtNodeTypes.FUN, KtNodeTypes.DESTRUCTURING_DECLARATION, KtNodeTypes.SECONDARY_CONSTRUCTOR)
|
.within(KtNodeTypes.PROPERTY, KtNodeTypes.FUN, KtNodeTypes.DESTRUCTURING_DECLARATION, KtNodeTypes.SECONDARY_CONSTRUCTOR)
|
||||||
.notForType(KtNodeTypes.BLOCK, FUN_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, CONSTRUCTOR_KEYWORD)
|
.notForType(KtNodeTypes.BLOCK, FUN_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, CONSTRUCTOR_KEYWORD)
|
||||||
@@ -406,7 +420,7 @@ private val INDENT_RULES = arrayOf<NodeIndentStrategy>(
|
|||||||
.notForType(KtNodeTypes.BLOCK, KtNodeTypes.WHEN_CONDITION_EXPRESSION, KtNodeTypes.WHEN_CONDITION_IN_RANGE, KtNodeTypes.WHEN_CONDITION_IS_PATTERN, ELSE_KEYWORD, ARROW)
|
.notForType(KtNodeTypes.BLOCK, KtNodeTypes.WHEN_CONDITION_EXPRESSION, KtNodeTypes.WHEN_CONDITION_IN_RANGE, KtNodeTypes.WHEN_CONDITION_IS_PATTERN, ELSE_KEYWORD, ARROW)
|
||||||
.set(Indent.getNormalIndent()),
|
.set(Indent.getNormalIndent()),
|
||||||
|
|
||||||
strategy("Parameter list")
|
strategy("Parameter list")
|
||||||
.within(KtNodeTypes.VALUE_PARAMETER_LIST)
|
.within(KtNodeTypes.VALUE_PARAMETER_LIST)
|
||||||
.forElement { it.elementType == KtNodeTypes.VALUE_PARAMETER && it.psi.prevSibling != null }
|
.forElement { it.elementType == KtNodeTypes.VALUE_PARAMETER && it.psi.prevSibling != null }
|
||||||
.set { settings ->
|
.set { settings ->
|
||||||
@@ -416,6 +430,7 @@ private val INDENT_RULES = arrayOf<NodeIndentStrategy>(
|
|||||||
Indent.getNormalIndent()
|
Indent.getNormalIndent()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
private fun getOperationType(node: ASTNode): IElementType? = node.findChildByType(KtNodeTypes.OPERATION_REFERENCE)?.firstChildNode?.elementType
|
private fun getOperationType(node: ASTNode): IElementType? = node.findChildByType(KtNodeTypes.OPERATION_REFERENCE)?.firstChildNode?.elementType
|
||||||
|
|
||||||
private fun getAlignmentForChildInParenthesis(
|
private fun getAlignmentForChildInParenthesis(
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ abstract class NodeIndentStrategy {
|
|||||||
private val notIn = ArrayList<IElementType>()
|
private val notIn = ArrayList<IElementType>()
|
||||||
private val forElement = ArrayList<IElementType>()
|
private val forElement = ArrayList<IElementType>()
|
||||||
private val notForElement = ArrayList<IElementType>()
|
private val notForElement = ArrayList<IElementType>()
|
||||||
|
private var forElementCallback: ((ASTNode) -> Boolean)? = null
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "PositionStrategy " + (debugInfo ?: "No debug info")
|
return "PositionStrategy " + (debugInfo ?: "No debug info")
|
||||||
@@ -98,17 +99,25 @@ abstract class NodeIndentStrategy {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun forElement(callback: (ASTNode) -> Boolean): PositionStrategy {
|
||||||
|
forElementCallback = callback
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
override fun getIndent(node: ASTNode, settings: CodeStyleSettings): Indent? {
|
override fun getIndent(node: ASTNode, settings: CodeStyleSettings): Indent? {
|
||||||
if (!forElement.isEmpty()) {
|
if (!forElement.isEmpty()) {
|
||||||
if (!forElement.contains(node.elementType)) {
|
if (!forElement.contains(node.elementType)) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notForElement.contains(node.elementType)) {
|
if (notForElement.contains(node.elementType)) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (forElementCallback?.invoke(node) == false) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
val parent = node.treeParent
|
val parent = node.treeParent
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
if (!within.isEmpty()) {
|
if (!within.isEmpty()) {
|
||||||
|
|||||||
@@ -25,10 +25,12 @@ import javax.swing.JCheckBox
|
|||||||
|
|
||||||
class KotlinIndentOptionsEditor : SmartIndentOptionsEditor() {
|
class KotlinIndentOptionsEditor : SmartIndentOptionsEditor() {
|
||||||
private val useContinuationIndentInParameterList = JCheckBox("Use continuation indent in parameter lists")
|
private val useContinuationIndentInParameterList = JCheckBox("Use continuation indent in parameter lists")
|
||||||
|
private val useContinuationIndentForExpressionBodies = JCheckBox("Use continuation indent for expression bodies")
|
||||||
|
|
||||||
override fun addComponents() {
|
override fun addComponents() {
|
||||||
super.addComponents()
|
super.addComponents()
|
||||||
add(useContinuationIndentInParameterList)
|
add(useContinuationIndentInParameterList)
|
||||||
|
add(useContinuationIndentForExpressionBodies)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isModified(settings: CodeStyleSettings, options: CommonCodeStyleSettings.IndentOptions): Boolean {
|
override fun isModified(settings: CodeStyleSettings, options: CommonCodeStyleSettings.IndentOptions): Boolean {
|
||||||
@@ -36,6 +38,8 @@ class KotlinIndentOptionsEditor : SmartIndentOptionsEditor() {
|
|||||||
val kotlinSettings = settings.getCustomSettings(KotlinCodeStyleSettings::class.java)
|
val kotlinSettings = settings.getCustomSettings(KotlinCodeStyleSettings::class.java)
|
||||||
isModified = isModified || IndentOptionsEditor.isFieldModified(useContinuationIndentInParameterList,
|
isModified = isModified || IndentOptionsEditor.isFieldModified(useContinuationIndentInParameterList,
|
||||||
kotlinSettings.CONTINUATION_INDENT_IN_PARAMETER_LISTS)
|
kotlinSettings.CONTINUATION_INDENT_IN_PARAMETER_LISTS)
|
||||||
|
isModified = isModified || IndentOptionsEditor.isFieldModified(useContinuationIndentForExpressionBodies,
|
||||||
|
kotlinSettings.CONTINUATION_INDENT_FOR_EXPRESSION_BODIES)
|
||||||
return isModified
|
return isModified
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,16 +47,19 @@ class KotlinIndentOptionsEditor : SmartIndentOptionsEditor() {
|
|||||||
super.apply(settings, options)
|
super.apply(settings, options)
|
||||||
val kotlinSettings = settings.getCustomSettings(KotlinCodeStyleSettings::class.java)
|
val kotlinSettings = settings.getCustomSettings(KotlinCodeStyleSettings::class.java)
|
||||||
kotlinSettings.CONTINUATION_INDENT_IN_PARAMETER_LISTS = useContinuationIndentInParameterList.isSelected
|
kotlinSettings.CONTINUATION_INDENT_IN_PARAMETER_LISTS = useContinuationIndentInParameterList.isSelected
|
||||||
|
kotlinSettings.CONTINUATION_INDENT_FOR_EXPRESSION_BODIES = useContinuationIndentForExpressionBodies.isSelected
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reset(settings: CodeStyleSettings, options: CommonCodeStyleSettings.IndentOptions) {
|
override fun reset(settings: CodeStyleSettings, options: CommonCodeStyleSettings.IndentOptions) {
|
||||||
super.reset(settings, options)
|
super.reset(settings, options)
|
||||||
val kotlinSettings = settings.getCustomSettings(KotlinCodeStyleSettings::class.java)
|
val kotlinSettings = settings.getCustomSettings(KotlinCodeStyleSettings::class.java)
|
||||||
useContinuationIndentInParameterList.isSelected = kotlinSettings.CONTINUATION_INDENT_IN_PARAMETER_LISTS
|
useContinuationIndentInParameterList.isSelected = kotlinSettings.CONTINUATION_INDENT_IN_PARAMETER_LISTS
|
||||||
|
useContinuationIndentForExpressionBodies.isSelected = kotlinSettings.CONTINUATION_INDENT_FOR_EXPRESSION_BODIES
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setEnabled(enabled: Boolean) {
|
override fun setEnabled(enabled: Boolean) {
|
||||||
super.setEnabled(enabled)
|
super.setEnabled(enabled)
|
||||||
useContinuationIndentInParameterList.isEnabled = enabled
|
useContinuationIndentInParameterList.isEnabled = enabled
|
||||||
|
useContinuationIndentForExpressionBodies.isEnabled = enabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
@@ -126,6 +126,9 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide
|
|||||||
bar: String
|
bar: String
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun expressionBodyMethod() =
|
||||||
|
"abc"
|
||||||
}
|
}
|
||||||
class AnotherClass<T : Any> : Some()
|
class AnotherClass<T : Any> : Some()
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun foo() =
|
||||||
|
2
|
||||||
|
|
||||||
|
// SET_TRUE: CONTINUATION_INDENT_FOR_EXPRESSION_BODIES
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun foo() =
|
||||||
|
2
|
||||||
|
|
||||||
|
// SET_TRUE: CONTINUATION_INDENT_FOR_EXPRESSION_BODIES
|
||||||
@@ -1040,6 +1040,12 @@ public class FormatterTestGenerated extends AbstractFormatterTest {
|
|||||||
doTestInverted(fileName);
|
doTestInverted(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ContinuationIndentForExpressionBodies.after.inv.kt")
|
||||||
|
public void testContinuationIndentForExpressionBodies() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/ContinuationIndentForExpressionBodies.after.inv.kt");
|
||||||
|
doTestInverted(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("DelegationList.after.inv.kt")
|
@TestMetadata("DelegationList.after.inv.kt")
|
||||||
public void testDelegationList() throws Exception {
|
public void testDelegationList() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/DelegationList.after.inv.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/DelegationList.after.inv.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user