diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/KotlinCodeStyleSettings.java b/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/KotlinCodeStyleSettings.java index 449d2c3d707..5e03ef5422a 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/KotlinCodeStyleSettings.java +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/KotlinCodeStyleSettings.java @@ -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 boolean IMPORT_NESTED_CLASSES = false; public boolean CONTINUATION_INDENT_IN_PARAMETER_LISTS = true; + public boolean CONTINUATION_INDENT_FOR_EXPRESSION_BODIES = true; public KotlinCodeStyleSettings(CodeStyleSettings container) { super("JetCodeStyleSettings", container); 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 d9c3c16343e..3e7fdeed873 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt @@ -30,7 +30,9 @@ import org.jetbrains.kotlin.kdoc.lexer.KDocTokens import org.jetbrains.kotlin.kdoc.parser.KDocElementTypes 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.KtExpression import java.util.* private val QUALIFIED_OPERATION = TokenSet.create(DOT, SAFE_ACCESS) @@ -361,6 +363,18 @@ private val INDENT_RULES = arrayOf( .within(KtNodeTypes.THEN, KtNodeTypes.ELSE).notForType(KtNodeTypes.BLOCK) .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") .within(KtNodeTypes.PROPERTY, KtNodeTypes.FUN, KtNodeTypes.DESTRUCTURING_DECLARATION, KtNodeTypes.SECONDARY_CONSTRUCTOR) .notForType(KtNodeTypes.BLOCK, FUN_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, CONSTRUCTOR_KEYWORD) @@ -406,7 +420,7 @@ private val INDENT_RULES = arrayOf( .notForType(KtNodeTypes.BLOCK, KtNodeTypes.WHEN_CONDITION_EXPRESSION, KtNodeTypes.WHEN_CONDITION_IN_RANGE, KtNodeTypes.WHEN_CONDITION_IS_PATTERN, ELSE_KEYWORD, ARROW) .set(Indent.getNormalIndent()), - strategy("Parameter list") + strategy("Parameter list") .within(KtNodeTypes.VALUE_PARAMETER_LIST) .forElement { it.elementType == KtNodeTypes.VALUE_PARAMETER && it.psi.prevSibling != null } .set { settings -> @@ -416,6 +430,7 @@ private val INDENT_RULES = arrayOf( Indent.getNormalIndent() }) + private fun getOperationType(node: ASTNode): IElementType? = node.findChildByType(KtNodeTypes.OPERATION_REFERENCE)?.firstChildNode?.elementType private fun getAlignmentForChildInParenthesis( diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/NodeIndentStrategy.kt b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/NodeIndentStrategy.kt index 8079e0d9247..cd8ac958ec6 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/NodeIndentStrategy.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/NodeIndentStrategy.kt @@ -41,6 +41,7 @@ abstract class NodeIndentStrategy { private val notIn = ArrayList() private val forElement = ArrayList() private val notForElement = ArrayList() + private var forElementCallback: ((ASTNode) -> Boolean)? = null override fun toString(): String { return "PositionStrategy " + (debugInfo ?: "No debug info") @@ -98,17 +99,25 @@ abstract class NodeIndentStrategy { return this } + fun forElement(callback: (ASTNode) -> Boolean): PositionStrategy { + forElementCallback = callback + return this + } + override fun getIndent(node: ASTNode, settings: CodeStyleSettings): Indent? { if (!forElement.isEmpty()) { if (!forElement.contains(node.elementType)) { return null } } - if (notForElement.contains(node.elementType)) { return null } + if (forElementCallback?.invoke(node) == false) { + return null + } + val parent = node.treeParent if (parent != null) { if (!within.isEmpty()) { diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinIndentOptionsEditor.kt b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinIndentOptionsEditor.kt index 1302ede3594..2155df598f2 100644 --- a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinIndentOptionsEditor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinIndentOptionsEditor.kt @@ -25,10 +25,12 @@ import javax.swing.JCheckBox class KotlinIndentOptionsEditor : SmartIndentOptionsEditor() { private val useContinuationIndentInParameterList = JCheckBox("Use continuation indent in parameter lists") + private val useContinuationIndentForExpressionBodies = JCheckBox("Use continuation indent for expression bodies") override fun addComponents() { super.addComponents() add(useContinuationIndentInParameterList) + add(useContinuationIndentForExpressionBodies) } override fun isModified(settings: CodeStyleSettings, options: CommonCodeStyleSettings.IndentOptions): Boolean { @@ -36,6 +38,8 @@ class KotlinIndentOptionsEditor : SmartIndentOptionsEditor() { val kotlinSettings = settings.getCustomSettings(KotlinCodeStyleSettings::class.java) isModified = isModified || IndentOptionsEditor.isFieldModified(useContinuationIndentInParameterList, kotlinSettings.CONTINUATION_INDENT_IN_PARAMETER_LISTS) + isModified = isModified || IndentOptionsEditor.isFieldModified(useContinuationIndentForExpressionBodies, + kotlinSettings.CONTINUATION_INDENT_FOR_EXPRESSION_BODIES) return isModified } @@ -43,16 +47,19 @@ class KotlinIndentOptionsEditor : SmartIndentOptionsEditor() { super.apply(settings, options) val kotlinSettings = settings.getCustomSettings(KotlinCodeStyleSettings::class.java) kotlinSettings.CONTINUATION_INDENT_IN_PARAMETER_LISTS = useContinuationIndentInParameterList.isSelected + kotlinSettings.CONTINUATION_INDENT_FOR_EXPRESSION_BODIES = useContinuationIndentForExpressionBodies.isSelected } override fun reset(settings: CodeStyleSettings, options: CommonCodeStyleSettings.IndentOptions) { super.reset(settings, options) val kotlinSettings = settings.getCustomSettings(KotlinCodeStyleSettings::class.java) useContinuationIndentInParameterList.isSelected = kotlinSettings.CONTINUATION_INDENT_IN_PARAMETER_LISTS + useContinuationIndentForExpressionBodies.isSelected = kotlinSettings.CONTINUATION_INDENT_FOR_EXPRESSION_BODIES } override fun setEnabled(enabled: Boolean) { super.setEnabled(enabled) useContinuationIndentInParameterList.isEnabled = enabled + useContinuationIndentForExpressionBodies.isEnabled = enabled } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt index fd743036a5c..dbf4c9bb810 100644 --- a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt @@ -126,6 +126,9 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide bar: String ) { } + + fun expressionBodyMethod() = + "abc" } class AnotherClass : Some() """.trimIndent() diff --git a/idea/testData/formatter/ContinuationIndentForExpressionBodies.after.inv.kt b/idea/testData/formatter/ContinuationIndentForExpressionBodies.after.inv.kt new file mode 100644 index 00000000000..a5a7b62e338 --- /dev/null +++ b/idea/testData/formatter/ContinuationIndentForExpressionBodies.after.inv.kt @@ -0,0 +1,4 @@ +fun foo() = + 2 + +// SET_TRUE: CONTINUATION_INDENT_FOR_EXPRESSION_BODIES diff --git a/idea/testData/formatter/ContinuationIndentForExpressionBodies.kt b/idea/testData/formatter/ContinuationIndentForExpressionBodies.kt new file mode 100644 index 00000000000..2230fd6912f --- /dev/null +++ b/idea/testData/formatter/ContinuationIndentForExpressionBodies.kt @@ -0,0 +1,4 @@ +fun foo() = + 2 + +// SET_TRUE: CONTINUATION_INDENT_FOR_EXPRESSION_BODIES diff --git a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java index 64219e012da..1550b3b331a 100644 --- a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java @@ -1040,6 +1040,12 @@ public class FormatterTestGenerated extends AbstractFormatterTest { 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") public void testDelegationList() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/DelegationList.after.inv.kt");