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 298be02f957..449d2c3d707 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 @@ -40,6 +40,7 @@ public class KotlinCodeStyleSettings extends CustomCodeStyleSettings { public int NAME_COUNT_TO_USE_STAR_IMPORT = ApplicationManager.getApplication().isUnitTestMode() ? Integer.MAX_VALUE : 5; 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 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 40fcb13daef..d9c3c16343e 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/KotlinCommonBlock.kt @@ -43,6 +43,9 @@ private val CODE_BLOCKS = TokenSet.create(KtNodeTypes.BLOCK, KtNodeTypes.CLASS_B private val ALIGN_FOR_BINARY_OPERATIONS = TokenSet.create(MUL, DIV, PERC, PLUS, MINUS, ELVIS, LT, GT, LTEQ, GTEQ, ANDAND, OROR) +val CodeStyleSettings.kotlinSettings + get() = getCustomSettings(KotlinCodeStyleSettings::class.java) + abstract class KotlinCommonBlock( private val node: ASTNode, private val settings: CodeStyleSettings, @@ -123,7 +126,7 @@ abstract class KotlinCommonBlock( } for (strategy in INDENT_RULES) { - val indent = strategy.getIndent(child) + val indent = strategy.getIndent(child, settings) if (indent != null) { return indent } @@ -178,7 +181,11 @@ abstract class KotlinCommonBlock( ChildAttributes(block.indent, block.alignment) } else { - ChildAttributes(Indent.getContinuationIndent(), null) + val indent = if (type == KtNodeTypes.VALUE_PARAMETER_LIST && !settings.kotlinSettings.CONTINUATION_INDENT_IN_PARAMETER_LISTS) + Indent.getNormalIndent() + else + Indent.getContinuationIndent() + ChildAttributes(indent, null) } } @@ -207,7 +214,7 @@ abstract class KotlinCommonBlock( private fun getChildrenAlignmentStrategy(): CommonAlignmentStrategy { val jetCommonSettings = settings.getCommonSettings(KotlinLanguage.INSTANCE) - val jetSettings = settings.getCustomSettings(KotlinCodeStyleSettings::class.java) + val kotlinSettings = settings.kotlinSettings val parentType = node.elementType return when { parentType === KtNodeTypes.VALUE_PARAMETER_LIST -> @@ -221,7 +228,7 @@ abstract class KotlinCommonBlock( jetCommonSettings.ALIGN_MULTILINE_METHOD_BRACKETS, LPAR, RPAR) parentType === KtNodeTypes.WHEN -> - getAlignmentForCaseBranch(jetSettings.ALIGN_IN_COLUMNS_CASE_BRANCH) + getAlignmentForCaseBranch(kotlinSettings.ALIGN_IN_COLUMNS_CASE_BRANCH) parentType === KtNodeTypes.WHEN_ENTRY -> alignmentStrategy @@ -397,7 +404,17 @@ private val INDENT_RULES = arrayOf( strategy("Block in when entry") .within(KtNodeTypes.WHEN_ENTRY) .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") + .within(KtNodeTypes.VALUE_PARAMETER_LIST) + .forElement { it.elementType == KtNodeTypes.VALUE_PARAMETER && it.psi.prevSibling != null } + .set { settings -> + if (settings.kotlinSettings.CONTINUATION_INDENT_IN_PARAMETER_LISTS) + Indent.getContinuationIndent() + else + Indent.getNormalIndent() + }) private fun getOperationType(node: ASTNode): IElementType? = node.findChildByType(KtNodeTypes.OPERATION_REFERENCE)?.firstChildNode?.elementType 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 53a34c43308..8079e0d9247 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/NodeIndentStrategy.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/NodeIndentStrategy.kt @@ -18,23 +18,24 @@ package org.jetbrains.kotlin.idea.formatter import com.intellij.formatting.Indent import com.intellij.lang.ASTNode +import com.intellij.psi.codeStyle.CodeStyleSettings import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.TokenSet import java.util.* abstract class NodeIndentStrategy { - abstract fun getIndent(node: ASTNode): Indent? + abstract fun getIndent(node: ASTNode, settings: CodeStyleSettings): Indent? class ConstIndentStrategy(private val indent: Indent) : NodeIndentStrategy() { - override fun getIndent(node: ASTNode): Indent? { + override fun getIndent(node: ASTNode, settings: CodeStyleSettings): Indent? { return indent } } class PositionStrategy(private val debugInfo: String?) : NodeIndentStrategy() { - private var defaultIndent = Indent.getNoneIndent() + private var indentCallback: (CodeStyleSettings) -> Indent = { Indent.getNoneIndent() } private val within = ArrayList() private val notIn = ArrayList() @@ -46,7 +47,12 @@ abstract class NodeIndentStrategy { } fun set(indent: Indent): PositionStrategy { - defaultIndent = indent + indentCallback = { indent } + return this + } + + fun set(indentCallback: (CodeStyleSettings) -> Indent): PositionStrategy { + this.indentCallback = indentCallback return this } @@ -92,7 +98,7 @@ abstract class NodeIndentStrategy { return this } - override fun getIndent(node: ASTNode): Indent? { + override fun getIndent(node: ASTNode, settings: CodeStyleSettings): Indent? { if (!forElement.isEmpty()) { if (!forElement.contains(node.elementType)) { return null @@ -121,7 +127,7 @@ abstract class NodeIndentStrategy { } } - return defaultIndent + return indentCallback(settings) } private fun fillTypes(resultCollection: MutableList, singleType: IElementType, otherTypes: Array) { diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinIndentOptionsEditor.kt b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinIndentOptionsEditor.kt new file mode 100644 index 00000000000..1302ede3594 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinIndentOptionsEditor.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.formatter + +import com.intellij.application.options.IndentOptionsEditor +import com.intellij.application.options.SmartIndentOptionsEditor +import com.intellij.psi.codeStyle.CodeStyleSettings +import com.intellij.psi.codeStyle.CommonCodeStyleSettings +import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings +import javax.swing.JCheckBox + +class KotlinIndentOptionsEditor : SmartIndentOptionsEditor() { + private val useContinuationIndentInParameterList = JCheckBox("Use continuation indent in parameter lists") + + override fun addComponents() { + super.addComponents() + add(useContinuationIndentInParameterList) + } + + override fun isModified(settings: CodeStyleSettings, options: CommonCodeStyleSettings.IndentOptions): Boolean { + var isModified = super.isModified(settings, options) + val kotlinSettings = settings.getCustomSettings(KotlinCodeStyleSettings::class.java) + isModified = isModified || IndentOptionsEditor.isFieldModified(useContinuationIndentInParameterList, + kotlinSettings.CONTINUATION_INDENT_IN_PARAMETER_LISTS) + return isModified + } + + override fun apply(settings: CodeStyleSettings, options: CommonCodeStyleSettings.IndentOptions) { + super.apply(settings, options) + val kotlinSettings = settings.getCustomSettings(KotlinCodeStyleSettings::class.java) + kotlinSettings.CONTINUATION_INDENT_IN_PARAMETER_LISTS = useContinuationIndentInParameterList.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 + } + + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) + useContinuationIndentInParameterList.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 3ceaff8cbd5..fd743036a5c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLanguageCodeStyleSettingsProvider.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.idea.formatter import com.intellij.application.options.IndentOptionsEditor -import com.intellij.application.options.SmartIndentOptionsEditor import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable import com.intellij.psi.codeStyle.CommonCodeStyleSettings import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider @@ -122,7 +121,11 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide return 0 } - + fun multilineMethod( + foo: String, + bar: String + ) { + } } class AnotherClass : Some() """.trimIndent() @@ -229,7 +232,7 @@ class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvide } } - override fun getIndentOptionsEditor(): IndentOptionsEditor = SmartIndentOptionsEditor() + override fun getIndentOptionsEditor(): IndentOptionsEditor = KotlinIndentOptionsEditor() override fun getDefaultCommonSettings(): CommonCodeStyleSettings = CommonCodeStyleSettings(language).apply { diff --git a/idea/testData/formatter/ContinuationIndentInParameterLists.after.kt b/idea/testData/formatter/ContinuationIndentInParameterLists.after.kt new file mode 100644 index 00000000000..2c836d4db20 --- /dev/null +++ b/idea/testData/formatter/ContinuationIndentInParameterLists.after.kt @@ -0,0 +1,6 @@ +fun foo( + x: Int +) { +} + +// SET_TRUE: CONTINUATION_INDENT_IN_PARAMETER_LISTS diff --git a/idea/testData/formatter/ContinuationIndentInParameterLists.inv.kt b/idea/testData/formatter/ContinuationIndentInParameterLists.inv.kt new file mode 100644 index 00000000000..9a1f29d2b55 --- /dev/null +++ b/idea/testData/formatter/ContinuationIndentInParameterLists.inv.kt @@ -0,0 +1,6 @@ +fun foo( + x: Int +) { +} + +// SET_TRUE: CONTINUATION_INDENT_IN_PARAMETER_LISTS diff --git a/idea/testData/formatter/ContinuationIndentInParameterLists.kt b/idea/testData/formatter/ContinuationIndentInParameterLists.kt new file mode 100644 index 00000000000..2c836d4db20 --- /dev/null +++ b/idea/testData/formatter/ContinuationIndentInParameterLists.kt @@ -0,0 +1,6 @@ +fun foo( + x: Int +) { +} + +// SET_TRUE: CONTINUATION_INDENT_IN_PARAMETER_LISTS diff --git a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java index 016deef778e..64219e012da 100644 --- a/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/formatter/FormatterTestGenerated.java @@ -164,6 +164,12 @@ public class FormatterTestGenerated extends AbstractFormatterTest { doTest(fileName); } + @TestMetadata("ContinuationIndentInParameterLists.after.kt") + public void testContinuationIndentInParameterLists() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/ContinuationIndentInParameterLists.after.kt"); + doTest(fileName); + } + @TestMetadata("CurlyBraceStringInterpolation.after.kt") public void testCurlyBraceStringInterpolation() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/CurlyBraceStringInterpolation.after.kt");