diff --git a/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/PerformanceTypingIndentationTestGenerated.java b/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/PerformanceTypingIndentationTestGenerated.java
index d77564e6a32..a88fbfba9da 100644
--- a/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/PerformanceTypingIndentationTestGenerated.java
+++ b/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/PerformanceTypingIndentationTestGenerated.java
@@ -268,6 +268,16 @@ public class PerformanceTypingIndentationTestGenerated extends AbstractPerforman
runTest("idea/testData/indentationOnNewline/ReturnContinue.kt");
}
+ @TestMetadata("Semicolon.kt")
+ public void testSemicolon() throws Exception {
+ runTest("idea/testData/indentationOnNewline/Semicolon.kt");
+ }
+
+ @TestMetadata("Semicolon2.kt")
+ public void testSemicolon2() throws Exception {
+ runTest("idea/testData/indentationOnNewline/Semicolon2.kt");
+ }
+
@TestMetadata("SettingAlignMultilineParametersInCalls.kt")
public void testSettingAlignMultilineParametersInCalls() throws Exception {
runTest("idea/testData/indentationOnNewline/SettingAlignMultilineParametersInCalls.kt");
diff --git a/idea/resources/META-INF/idea.xml b/idea/resources/META-INF/idea.xml
index 2ba09b4fecf..fbec2d6780a 100644
--- a/idea/resources/META-INF/idea.xml
+++ b/idea/resources/META-INF/idea.xml
@@ -15,6 +15,7 @@
factoryClass="org.jetbrains.kotlin.idea.structureView.KtClsStructureViewBuilderProvider"/>
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLineIndentProvider.kt b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLineIndentProvider.kt
new file mode 100644
index 00000000000..8cad6b6cb56
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinLineIndentProvider.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.idea.formatter
+
+import com.intellij.lang.Language
+import com.intellij.openapi.editor.Editor
+import com.intellij.openapi.project.Project
+import com.intellij.psi.codeStyle.lineIndent.LineIndentProvider
+import com.intellij.psi.impl.source.codeStyle.lineIndent.FormatterBasedLineIndentProvider
+import org.jetbrains.annotations.TestOnly
+import org.jetbrains.kotlin.idea.KotlinLanguage
+
+class KotlinLineIndentProvider : LineIndentProvider {
+ private val formatterBasedProvider = FormatterBasedLineIndentProvider()
+
+ override fun getLineIndent(project: Project, editor: Editor, language: Language?, offset: Int): String? {
+ val lineIndent = formatterBasedProvider.getLineIndent(project, editor, language, offset)
+ return if (useFormatter) lineIndent else lineIndent
+ }
+
+ override fun isSuitableFor(language: Language?): Boolean = language?.isKindOf(KotlinLanguage.INSTANCE) == true
+
+ companion object {
+ @get:TestOnly
+ @set:TestOnly
+ internal var useFormatter: Boolean = false
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/indentationOnNewline/ArgumentListNormalIndent.after.inv.kt b/idea/testData/indentationOnNewline/ArgumentListNormalIndent.after.inv.kt
new file mode 100644
index 00000000000..1675648e32a
--- /dev/null
+++ b/idea/testData/indentationOnNewline/ArgumentListNormalIndent.after.inv.kt
@@ -0,0 +1,7 @@
+fun test(i: Int) {
+ test(
+
+ )
+}
+
+// SET_FALSE: CONTINUATION_INDENT_IN_ARGUMENT_LISTS
diff --git a/idea/testData/indentationOnNewline/Semicolon.after.kt b/idea/testData/indentationOnNewline/Semicolon.after.kt
new file mode 100644
index 00000000000..852f609c908
--- /dev/null
+++ b/idea/testData/indentationOnNewline/Semicolon.after.kt
@@ -0,0 +1,4 @@
+fun test() {
+ val a = 44;
+
+}
diff --git a/idea/testData/indentationOnNewline/Semicolon.kt b/idea/testData/indentationOnNewline/Semicolon.kt
new file mode 100644
index 00000000000..50a033d7c1e
--- /dev/null
+++ b/idea/testData/indentationOnNewline/Semicolon.kt
@@ -0,0 +1,3 @@
+fun test() {
+ val a = 44;
+}
diff --git a/idea/testData/indentationOnNewline/Semicolon2.after.kt b/idea/testData/indentationOnNewline/Semicolon2.after.kt
new file mode 100644
index 00000000000..7eeae566db9
--- /dev/null
+++ b/idea/testData/indentationOnNewline/Semicolon2.after.kt
@@ -0,0 +1,4 @@
+fun test() {
+ val a = 44;
+ val b = 42;
+}
diff --git a/idea/testData/indentationOnNewline/Semicolon2.kt b/idea/testData/indentationOnNewline/Semicolon2.kt
new file mode 100644
index 00000000000..6b13f087b93
--- /dev/null
+++ b/idea/testData/indentationOnNewline/Semicolon2.kt
@@ -0,0 +1,3 @@
+fun test() {
+ val a = 44; val b = 42;
+}
diff --git a/idea/tests/org/jetbrains/kotlin/formatter/AbstractTypingIndentationTestBase.kt b/idea/tests/org/jetbrains/kotlin/formatter/AbstractTypingIndentationTestBase.kt
index cbef735b5c5..d1718b880bb 100644
--- a/idea/tests/org/jetbrains/kotlin/formatter/AbstractTypingIndentationTestBase.kt
+++ b/idea/tests/org/jetbrains/kotlin/formatter/AbstractTypingIndentationTestBase.kt
@@ -5,13 +5,22 @@
package org.jetbrains.kotlin.formatter
import com.intellij.application.options.CodeStyle
+import com.intellij.openapi.actionSystem.IdeActions
import com.intellij.openapi.util.io.FileUtil
+import com.intellij.psi.codeStyle.lineIndent.LineIndentProvider
import com.intellij.testFramework.EditorTestUtil
+import org.jetbrains.kotlin.idea.KotlinLanguage
+import org.jetbrains.kotlin.idea.formatter.KotlinLineIndentProvider
import org.jetbrains.kotlin.idea.test.KotlinLightPlatformCodeInsightTestCase
+import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinTestUtils
+import org.jetbrains.kotlin.test.testFramework.runWriteAction
+import org.junit.Assert
import java.io.File
abstract class AbstractTypingIndentationTestBase : KotlinLightPlatformCodeInsightTestCase() {
+ private val customLineIndentProvider: LineIndentProvider = KotlinLineIndentProvider()
+
fun doNewlineTestWithInvert(afterInvFilePath: String) {
doNewlineTest(afterInvFilePath, true)
}
@@ -22,6 +31,11 @@ abstract class AbstractTypingIndentationTestBase : KotlinLightPlatformCodeInsigh
val testFileExtension = afterFilePath.substring(afterFilePath.lastIndexOf("."))
val originFilePath = testFileName + testFileExtension
val originalFileText = FileUtil.loadFile(File(originFilePath), true)
+ val withoutCustomLineIndentProvider = InTextDirectivesUtils.findStringWithPrefixes(
+ originalFileText,
+ "// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER"
+ ) != null
+
try {
val configurator = FormatSettingsUtil.createConfigurator(originalFileText, CodeStyle.getSettings(project))
if (!inverted) {
@@ -30,19 +44,48 @@ abstract class AbstractTypingIndentationTestBase : KotlinLightPlatformCodeInsigh
configurator.configureInvertedSettings()
}
- doNewlineTest(originFilePath, afterFilePath)
+ doNewlineTest(originFilePath, afterFilePath, withoutCustomLineIndentProvider)
} finally {
CodeStyle.getSettings(project).clearCodeStyleSettings()
}
}
- private fun doNewlineTest(beforeFilePath: String, afterFilePath: String) {
+ private fun doNewlineTest(beforeFilePath: String, afterFilePath: String, withoutCustomLineIndentProvider: Boolean) {
+ KotlinLineIndentProvider.useFormatter = true
+ typeAndCheck(beforeFilePath, afterFilePath, "with FormatterBasedLineIndentProvider")
+ KotlinLineIndentProvider.useFormatter = false
+
+ if (!withoutCustomLineIndentProvider) {
+ typeAndCheck(beforeFilePath, afterFilePath, "with ${customLineIndentProvider.javaClass.simpleName}")
+ }
+
configureByFile(beforeFilePath)
- type('\n')
- val caretModel = editor.caretModel
- val offset = caretModel.offset
- val actualTextWithCaret = StringBuilder(editor.document.text).insert(offset, EditorTestUtil.CARET_TAG).toString()
- KotlinTestUtils.assertEqualsToFile(File(afterFilePath), actualTextWithCaret)
+ assertCustomIndentExist(withoutCustomLineIndentProvider)
+ }
+
+ private fun assertCustomIndentExist(withoutCustomLineIndentProvider: Boolean) {
+ val offset = editor.caretModel.offset
+ runWriteAction {
+ editor.document.insertString(offset, "\n")
+ }
+
+ val customIndent = customLineIndentProvider.getLineIndent(project, editor, KotlinLanguage.INSTANCE, offset + 1)
+ val condition = customIndent == null
+ Assert.assertTrue(
+ "${if (withoutCustomLineIndentProvider) "Remove" else "Add"} \"// WITHOUT_CUSTOM_LINE_INDENT_PROVIDER\" or fix ${customLineIndentProvider.javaClass.simpleName}",
+ if (withoutCustomLineIndentProvider) condition else !condition
+ )
+ }
+
+ private fun typeAndCheck(beforeFilePath: String, afterFilePath: String, errorMessage: String) {
+ configureByFile(beforeFilePath)
+ executeAction(IdeActions.ACTION_EDITOR_ENTER)
+ val actualTextWithCaret = StringBuilder(editor.document.text).insert(
+ editor.caretModel.offset,
+ EditorTestUtil.CARET_TAG
+ ).toString()
+
+ KotlinTestUtils.assertEqualsToFile(errorMessage, File(afterFilePath), actualTextWithCaret)
}
override fun getTestDataPath(): String = ""
diff --git a/idea/tests/org/jetbrains/kotlin/formatter/TypingIndentationTestBaseGenerated.java b/idea/tests/org/jetbrains/kotlin/formatter/TypingIndentationTestBaseGenerated.java
index 99266749f9b..abed44fd278 100644
--- a/idea/tests/org/jetbrains/kotlin/formatter/TypingIndentationTestBaseGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/formatter/TypingIndentationTestBaseGenerated.java
@@ -270,6 +270,16 @@ public class TypingIndentationTestBaseGenerated extends AbstractTypingIndentatio
runTest("idea/testData/indentationOnNewline/ReturnContinue.after.kt");
}
+ @TestMetadata("Semicolon.after.kt")
+ public void testSemicolon() throws Exception {
+ runTest("idea/testData/indentationOnNewline/Semicolon.after.kt");
+ }
+
+ @TestMetadata("Semicolon2.after.kt")
+ public void testSemicolon2() throws Exception {
+ runTest("idea/testData/indentationOnNewline/Semicolon2.after.kt");
+ }
+
@TestMetadata("SettingAlignMultilineParametersInCalls.after.kt")
public void testSettingAlignMultilineParametersInCalls() throws Exception {
runTest("idea/testData/indentationOnNewline/SettingAlignMultilineParametersInCalls.after.kt");
@@ -336,6 +346,11 @@ public class TypingIndentationTestBaseGenerated extends AbstractTypingIndentatio
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/indentationOnNewline"), Pattern.compile("^([^\\.]+)\\.after\\.inv\\.kt.*$"), null, true);
}
+ @TestMetadata("ArgumentListNormalIndent.after.inv.kt")
+ public void testArgumentListNormalIndent() throws Exception {
+ runTest("idea/testData/indentationOnNewline/ArgumentListNormalIndent.after.inv.kt");
+ }
+
@TestMetadata("AssignmentAfterEq.after.inv.kt")
public void testAssignmentAfterEq() throws Exception {
runTest("idea/testData/indentationOnNewline/AssignmentAfterEq.after.inv.kt");