From 408dd57e718c6265bfa7ddf1df97a3675c62b1b6 Mon Sep 17 00:00:00 2001
From: Xiang Rong Lin <41164160+xiangronglin@users.noreply.github.com>
Date: Tue, 23 Aug 2022 21:43:40 +0200
Subject: [PATCH] [kotlin] Restore "convert trimIndent() to trimMargin() and
vice versa" intentions
^KTIJ-1742 Fixed
Initially removed in:
https://github.com/JetBrains/kotlin/commit/0b9b49d7bc4c418e94b5b918c7ca3939e5a36eda
https://github.com/JetBrains/kotlin/commit/26478b1374fc96d45713108668336c5eb531bff1
closes https://github.com/JetBrains/intellij-community/pull/2119
GitOrigin-RevId: 408ec0f1c6f6bd6081edc695c3f16295eee3e7de
---
.../messages/KotlinBundle.properties | 2 +
.../after.kt.template | 7 ++
.../before.kt.template | 7 ++
.../description.html | 6 ++
.../after.kt.template | 7 ++
.../before.kt.template | 7 ++
.../description.html | 6 ++
.../ConvertTrimIndentToTrimMarginIntention.kt | 61 +++++++++++++
.../ConvertTrimMarginToTrimIndentIntention.kt | 65 ++++++++++++++
.../intentions/IntentionTestGenerated.java | 86 +++++++++++++++++++
.../convertTrimIndentToTrimMargin/.intention | 1 +
.../differentIndent.kt | 10 +++
.../differentIndent.kt.after | 10 +++
.../notBlankFirst.kt | 9 ++
.../notBlankLast.kt | 9 ++
.../notRawString.kt | 5 ++
.../convertTrimIndentToTrimMargin/simple.kt | 10 +++
.../simple.kt.after | 10 +++
.../convertTrimMarginToTrimIndent/.intention | 1 +
.../differentIndent.kt | 10 +++
.../differentIndent.kt.after | 10 +++
.../escapedMarginPrefixArgument.kt | 10 +++
.../noMarginPrefix.kt | 9 ++
.../notBlankFirst.kt | 9 ++
.../notBlankLast.kt | 9 ++
.../notRawString.kt | 5 ++
.../referenceMarginPrefixArgument.kt | 9 ++
.../convertTrimMarginToTrimIndent/simple.kt | 10 +++
.../simple.kt.after | 10 +++
.../convertTrimMarginToTrimIndent/simple2.kt | 9 ++
.../simple2.kt.after | 9 ++
.../resources/META-INF/inspections-fe10.xml | 14 +++
32 files changed, 442 insertions(+)
create mode 100644 plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimIndentToTrimMarginIntention/after.kt.template
create mode 100644 plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimIndentToTrimMarginIntention/before.kt.template
create mode 100644 plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimIndentToTrimMarginIntention/description.html
create mode 100644 plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimMarginToTrimIndentIntention/after.kt.template
create mode 100644 plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimMarginToTrimIndentIntention/before.kt.template
create mode 100644 plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimMarginToTrimIndentIntention/description.html
create mode 100644 plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTrimIndentToTrimMarginIntention.kt
create mode 100644 plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTrimMarginToTrimIndentIntention.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/.intention
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/differentIndent.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/differentIndent.kt.after
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/notBlankFirst.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/notBlankLast.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/notRawString.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/simple.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/simple.kt.after
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/.intention
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/differentIndent.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/differentIndent.kt.after
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/escapedMarginPrefixArgument.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/noMarginPrefix.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/notBlankFirst.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/notBlankLast.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/notRawString.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/referenceMarginPrefixArgument.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple.kt.after
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple2.kt
create mode 100644 plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple2.kt.after
diff --git a/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties b/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties
index e071f91b17f3..01e3f314b91e 100644
--- a/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties
+++ b/plugins/kotlin/base/resources/resources-en/messages/KotlinBundle.properties
@@ -1698,6 +1698,8 @@ convert.to.0.unsafecast.1=Convert to ''{0}.unsafeCast<{1}>()''
convert.to.unsafecast.call=Convert to unsafeCast() call
convert.to.array.parameter=Convert to array parameter
convert.to.assignment.expression=Converts the assignment statement to an expression
+convert.to.trim.indent=Convert to trimIndent() call
+convert.to.trim.margin=Convert to trimMargin() call
create.kotlin.subclass=Create Kotlin subclass
use.destructuring.declaration=Use destructuring declaration
implement.as.constructor.parameter=Implement as constructor parameter
diff --git a/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimIndentToTrimMarginIntention/after.kt.template b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimIndentToTrimMarginIntention/after.kt.template
new file mode 100644
index 000000000000..226bffdf47af
--- /dev/null
+++ b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimIndentToTrimMarginIntention/after.kt.template
@@ -0,0 +1,7 @@
+fun foo() {
+ val x =
+ """
+ a
+ b
+ """.trimIndent()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimIndentToTrimMarginIntention/before.kt.template b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimIndentToTrimMarginIntention/before.kt.template
new file mode 100644
index 000000000000..d58662bb1185
--- /dev/null
+++ b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimIndentToTrimMarginIntention/before.kt.template
@@ -0,0 +1,7 @@
+fun foo() {
+ val x =
+ """
+ |a
+ |b
+ """.trimMargin()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimIndentToTrimMarginIntention/description.html b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimIndentToTrimMarginIntention/description.html
new file mode 100644
index 000000000000..432854c90794
--- /dev/null
+++ b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimIndentToTrimMarginIntention/description.html
@@ -0,0 +1,6 @@
+
+
+
+Converts a trimIndent() call to a trimMargin() call.
+
+
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimMarginToTrimIndentIntention/after.kt.template b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimMarginToTrimIndentIntention/after.kt.template
new file mode 100644
index 000000000000..d58662bb1185
--- /dev/null
+++ b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimMarginToTrimIndentIntention/after.kt.template
@@ -0,0 +1,7 @@
+fun foo() {
+ val x =
+ """
+ |a
+ |b
+ """.trimMargin()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimMarginToTrimIndentIntention/before.kt.template b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimMarginToTrimIndentIntention/before.kt.template
new file mode 100644
index 000000000000..226bffdf47af
--- /dev/null
+++ b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimMarginToTrimIndentIntention/before.kt.template
@@ -0,0 +1,7 @@
+fun foo() {
+ val x =
+ """
+ a
+ b
+ """.trimIndent()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimMarginToTrimIndentIntention/description.html b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimMarginToTrimIndentIntention/description.html
new file mode 100644
index 000000000000..1e190ed452c0
--- /dev/null
+++ b/plugins/kotlin/code-insight/descriptions/resources-en/intentionDescriptions/ConvertTrimMarginToTrimIndentIntention/description.html
@@ -0,0 +1,6 @@
+
+
+
+Converts a trimMargin() call to a trimIndent() call.
+
+
\ No newline at end of file
diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTrimIndentToTrimMarginIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTrimIndentToTrimMarginIntention.kt
new file mode 100644
index 000000000000..125626307600
--- /dev/null
+++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTrimIndentToTrimMarginIntention.kt
@@ -0,0 +1,61 @@
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.kotlin.idea.intentions
+
+import com.intellij.openapi.editor.Editor
+import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
+import org.jetbrains.kotlin.idea.codeinsight.api.classic.intentions.SelfTargetingIntention
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.psi.KtCallExpression
+import org.jetbrains.kotlin.psi.KtPsiFactory
+import org.jetbrains.kotlin.psi.KtStringTemplateExpression
+import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
+
+class ConvertTrimIndentToTrimMarginIntention : SelfTargetingIntention(
+ KtCallExpression::class.java, KotlinBundle.lazyMessage("convert.to.trim.margin")
+) {
+ override fun isApplicableTo(element: KtCallExpression, caretOffset: Int): Boolean {
+ val template = (element.getQualifiedExpressionForSelector()?.receiverExpression as? KtStringTemplateExpression) ?: return false
+ if (!template.text.startsWith("\"\"\"")) return false
+
+ val callee = element.calleeExpression ?: return false
+ if (callee.text != "trimIndent" || callee.getCallableDescriptor()?.fqNameSafe != FqName("kotlin.text.trimIndent")) return false
+
+ return template.isSurroundedByLineBreaksOrBlanks()
+ }
+
+ override fun applyTo(element: KtCallExpression, editor: Editor?) {
+ val qualifiedExpression = element.getQualifiedExpressionForSelector()
+ val template = (qualifiedExpression?.receiverExpression as? KtStringTemplateExpression) ?: return
+ val indent = template.calculateIndent()
+ val newTemplate = buildString {
+ template.entries.forEach { entry ->
+ val text = entry.text
+ if (text.isLineBreakOrBlank()) {
+ append(text)
+ } else {
+ append(indent)
+ append("|")
+ append(text.drop(indent.length))
+ }
+ }
+ }
+ qualifiedExpression.replace(KtPsiFactory(element).createExpression("\"\"\"$newTemplate\"\"\".trimMargin()"))
+ }
+
+ companion object {
+ fun KtStringTemplateExpression.isSurroundedByLineBreaksOrBlanks(): Boolean {
+ val entries = entries
+ return listOfNotNull(entries.firstOrNull(), entries.lastOrNull()).all { it.text.isLineBreakOrBlank() }
+ }
+
+ fun String.isLineBreakOrBlank(): Boolean =
+ this == "\n" || this.isBlank()
+
+ fun KtStringTemplateExpression.calculateIndent(): String =
+ entries.asSequence().mapNotNull { stringTemplateEntry ->
+ val text = stringTemplateEntry.text
+ if (text.isLineBreakOrBlank()) null else text.takeWhile { it.isWhitespace() }
+ }.minByOrNull { it.length } ?: ""
+ }
+}
diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTrimMarginToTrimIndentIntention.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTrimMarginToTrimIndentIntention.kt
new file mode 100644
index 000000000000..7f006268720d
--- /dev/null
+++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertTrimMarginToTrimIndentIntention.kt
@@ -0,0 +1,65 @@
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.kotlin.idea.intentions
+
+import com.intellij.openapi.editor.Editor
+import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
+import org.jetbrains.kotlin.idea.codeinsight.api.classic.intentions.SelfTargetingIntention
+import org.jetbrains.kotlin.idea.intentions.ConvertTrimIndentToTrimMarginIntention.Companion.calculateIndent
+import org.jetbrains.kotlin.idea.intentions.ConvertTrimIndentToTrimMarginIntention.Companion.isLineBreakOrBlank
+import org.jetbrains.kotlin.idea.intentions.ConvertTrimIndentToTrimMarginIntention.Companion.isSurroundedByLineBreaksOrBlanks
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.psi.KtCallExpression
+import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry
+import org.jetbrains.kotlin.psi.KtPsiFactory
+import org.jetbrains.kotlin.psi.KtStringTemplateExpression
+import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
+
+class ConvertTrimMarginToTrimIndentIntention : SelfTargetingIntention(
+ KtCallExpression::class.java, KotlinBundle.lazyMessage("convert.to.trim.indent")
+) {
+ override fun isApplicableTo(element: KtCallExpression, caretOffset: Int): Boolean {
+ val template = (element.getQualifiedExpressionForSelector()?.receiverExpression as? KtStringTemplateExpression) ?: return false
+ if (!template.text.startsWith("\"\"\"")) return false
+
+ val callee = element.calleeExpression ?: return false
+ if (callee.text != "trimMargin" || callee.getCallableDescriptor()?.fqNameSafe != FqName("kotlin.text.trimMargin")) return false
+
+ if (!template.isSurroundedByLineBreaksOrBlanks()) return false
+
+ val marginPrefix = element.marginPrefix() ?: return false
+ return template.entries.drop(1).dropLast(1).all { stringTemplateEntry ->
+ val text = stringTemplateEntry.text
+ text.isLineBreakOrBlank() || text.dropWhile { it.isWhitespace() }.startsWith(marginPrefix)
+ }
+ }
+
+ override fun applyTo(element: KtCallExpression, editor: Editor?) {
+ val qualifiedExpression = element.getQualifiedExpressionForSelector()
+ val template = (qualifiedExpression?.receiverExpression as? KtStringTemplateExpression) ?: return
+ val marginPrefix = element.marginPrefix() ?: return
+ val indent = template.calculateIndent()
+ val newTemplate = buildString {
+ template.entries.forEach { entry ->
+ val text = entry.text
+ if (text.isLineBreakOrBlank()) {
+ append(text)
+ } else {
+ append(indent)
+ append(entry.text.dropWhile { it.isWhitespace() }.replaceFirst(marginPrefix, ""))
+ }
+ }
+ }
+ qualifiedExpression.replace(KtPsiFactory(element).createExpression("\"\"\"$newTemplate\"\"\".trimIndent()"))
+ }
+}
+
+private fun KtCallExpression.marginPrefix(): String? {
+ val argument = valueArguments.firstOrNull()?.getArgumentExpression()
+ if (argument != null) {
+ if (argument !is KtStringTemplateExpression) return null
+ val entry = argument.entries.toList().singleOrNull() as? KtLiteralStringTemplateEntry ?: return null
+ return entry.text.replace("\"", "")
+ }
+ return "|"
+}
diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
index 7775372bd23f..3e2d5c501599 100644
--- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
+++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java
@@ -9404,6 +9404,92 @@ public abstract class IntentionTestGenerated extends AbstractIntentionTest {
}
}
+ @RunWith(JUnit3RunnerWithInners.class)
+ @TestMetadata("testData/intentions/convertTrimIndentToTrimMargin")
+ public static class ConvertTrimIndentToTrimMargin extends AbstractIntentionTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
+ }
+
+ @TestMetadata("differentIndent.kt")
+ public void testDifferentIndent() throws Exception {
+ runTest("testData/intentions/convertTrimIndentToTrimMargin/differentIndent.kt");
+ }
+
+ @TestMetadata("notBlankFirst.kt")
+ public void testNotBlankFirst() throws Exception {
+ runTest("testData/intentions/convertTrimIndentToTrimMargin/notBlankFirst.kt");
+ }
+
+ @TestMetadata("notBlankLast.kt")
+ public void testNotBlankLast() throws Exception {
+ runTest("testData/intentions/convertTrimIndentToTrimMargin/notBlankLast.kt");
+ }
+
+ @TestMetadata("notRawString.kt")
+ public void testNotRawString() throws Exception {
+ runTest("testData/intentions/convertTrimIndentToTrimMargin/notRawString.kt");
+ }
+
+ @TestMetadata("simple.kt")
+ public void testSimple() throws Exception {
+ runTest("testData/intentions/convertTrimIndentToTrimMargin/simple.kt");
+ }
+ }
+
+ @RunWith(JUnit3RunnerWithInners.class)
+ @TestMetadata("testData/intentions/convertTrimMarginToTrimIndent")
+ public static class ConvertTrimMarginToTrimIndent extends AbstractIntentionTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
+ }
+
+ @TestMetadata("differentIndent.kt")
+ public void testDifferentIndent() throws Exception {
+ runTest("testData/intentions/convertTrimMarginToTrimIndent/differentIndent.kt");
+ }
+
+ @TestMetadata("escapedMarginPrefixArgument.kt")
+ public void testEscapedMarginPrefixArgument() throws Exception {
+ runTest("testData/intentions/convertTrimMarginToTrimIndent/escapedMarginPrefixArgument.kt");
+ }
+
+ @TestMetadata("noMarginPrefix.kt")
+ public void testNoMarginPrefix() throws Exception {
+ runTest("testData/intentions/convertTrimMarginToTrimIndent/noMarginPrefix.kt");
+ }
+
+ @TestMetadata("notBlankFirst.kt")
+ public void testNotBlankFirst() throws Exception {
+ runTest("testData/intentions/convertTrimMarginToTrimIndent/notBlankFirst.kt");
+ }
+
+ @TestMetadata("notBlankLast.kt")
+ public void testNotBlankLast() throws Exception {
+ runTest("testData/intentions/convertTrimMarginToTrimIndent/notBlankLast.kt");
+ }
+
+ @TestMetadata("notRawString.kt")
+ public void testNotRawString() throws Exception {
+ runTest("testData/intentions/convertTrimMarginToTrimIndent/notRawString.kt");
+ }
+
+ @TestMetadata("referenceMarginPrefixArgument.kt")
+ public void testReferenceMarginPrefixArgument() throws Exception {
+ runTest("testData/intentions/convertTrimMarginToTrimIndent/referenceMarginPrefixArgument.kt");
+ }
+
+ @TestMetadata("simple.kt")
+ public void testSimple() throws Exception {
+ runTest("testData/intentions/convertTrimMarginToTrimIndent/simple.kt");
+ }
+
+ @TestMetadata("simple2.kt")
+ public void testSimple2() throws Exception {
+ runTest("testData/intentions/convertTrimMarginToTrimIndent/simple2.kt");
+ }
+ }
+
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("testData/intentions/convertTryFinallyToUseCall")
public static class ConvertTryFinallyToUseCall extends AbstractIntentionTest {
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/.intention b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/.intention
new file mode 100644
index 000000000000..d8cd692c80c4
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/.intention
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.intentions.ConvertTrimIndentToTrimMarginIntention
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/differentIndent.kt b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/differentIndent.kt
new file mode 100644
index 000000000000..91c1549e9f9b
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/differentIndent.kt
@@ -0,0 +1,10 @@
+// AFTER-WARNING: Variable 'x' is never used
+// WITH_STDLIB
+fun test() {
+ val x =
+ """
+ a
+ b
+ c
+ """.trimIndent()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/differentIndent.kt.after b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/differentIndent.kt.after
new file mode 100644
index 000000000000..63382fd1ca58
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/differentIndent.kt.after
@@ -0,0 +1,10 @@
+// AFTER-WARNING: Variable 'x' is never used
+// WITH_STDLIB
+fun test() {
+ val x =
+ """
+ |a
+ | b
+ | c
+ """.trimMargin()
+}
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/notBlankFirst.kt b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/notBlankFirst.kt
new file mode 100644
index 000000000000..27682bc35e3f
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/notBlankFirst.kt
@@ -0,0 +1,9 @@
+// IS_APPLICABLE: false
+// WITH_STDLIB
+fun test() {
+ val x =
+ """1
+ a
+ b
+ """.trimIndent()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/notBlankLast.kt b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/notBlankLast.kt
new file mode 100644
index 000000000000..d137806ca53c
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/notBlankLast.kt
@@ -0,0 +1,9 @@
+// IS_APPLICABLE: false
+// WITH_STDLIB
+fun test() {
+ val x =
+ """
+ a
+ b
+ 1""".trimIndent()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/notRawString.kt b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/notRawString.kt
new file mode 100644
index 000000000000..a3dca9a52437
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/notRawString.kt
@@ -0,0 +1,5 @@
+// IS_APPLICABLE: false
+// WITH_STDLIB
+fun test() {
+ val x = " a".trimIndent()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/simple.kt b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/simple.kt
new file mode 100644
index 000000000000..71d65f1e4ce4
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/simple.kt
@@ -0,0 +1,10 @@
+// AFTER-WARNING: Variable 'x' is never used
+// INTENTION_TEXT: "Convert to trimMargin() call"
+// WITH_STDLIB
+fun test() {
+ val x =
+ """
+ a
+ b
+ """.trimIndent()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/simple.kt.after b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/simple.kt.after
new file mode 100644
index 000000000000..7330efcf7c42
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimIndentToTrimMargin/simple.kt.after
@@ -0,0 +1,10 @@
+// AFTER-WARNING: Variable 'x' is never used
+// INTENTION_TEXT: "Convert to trimMargin() call"
+// WITH_STDLIB
+fun test() {
+ val x =
+ """
+ |a
+ |b
+ """.trimMargin()
+}
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/.intention b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/.intention
new file mode 100644
index 000000000000..4ad0baeca704
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/.intention
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.intentions.ConvertTrimMarginToTrimIndentIntention
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/differentIndent.kt b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/differentIndent.kt
new file mode 100644
index 000000000000..b00a48b13fb5
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/differentIndent.kt
@@ -0,0 +1,10 @@
+// AFTER-WARNING: Variable 'x' is never used
+// WITH_STDLIB
+fun test() {
+ val x =
+ """
+ |a
+ | b
+ |c
+ """.trimMargin()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/differentIndent.kt.after b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/differentIndent.kt.after
new file mode 100644
index 000000000000..29cdbcb717cb
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/differentIndent.kt.after
@@ -0,0 +1,10 @@
+// AFTER-WARNING: Variable 'x' is never used
+// WITH_STDLIB
+fun test() {
+ val x =
+ """
+ a
+ b
+ c
+ """.trimIndent()
+}
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/escapedMarginPrefixArgument.kt b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/escapedMarginPrefixArgument.kt
new file mode 100644
index 000000000000..d77c64d17501
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/escapedMarginPrefixArgument.kt
@@ -0,0 +1,10 @@
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// IS_APPLICABLE: false
+// WITH_STDLIB
+fun test() {
+ val x =
+ """
+ \a
+ \b
+ """.trimMargin("\\")
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/noMarginPrefix.kt b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/noMarginPrefix.kt
new file mode 100644
index 000000000000..6cd380457b5b
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/noMarginPrefix.kt
@@ -0,0 +1,9 @@
+// IS_APPLICABLE: false
+// WITH_STDLIB
+fun test() {
+ val x =
+ """
+ |a
+ b
+ """.trimMargin()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/notBlankFirst.kt b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/notBlankFirst.kt
new file mode 100644
index 000000000000..415e58afd099
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/notBlankFirst.kt
@@ -0,0 +1,9 @@
+// IS_APPLICABLE: false
+// WITH_STDLIB
+fun test() {
+ val x =
+ """1
+ |a
+ |b
+ """.trimMargin()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/notBlankLast.kt b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/notBlankLast.kt
new file mode 100644
index 000000000000..0fe1c083cddf
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/notBlankLast.kt
@@ -0,0 +1,9 @@
+// IS_APPLICABLE: false
+// WITH_STDLIB
+fun test() {
+ val x =
+ """
+ |a
+ |b
+ 1""".trimMargin()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/notRawString.kt b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/notRawString.kt
new file mode 100644
index 000000000000..f4e181390479
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/notRawString.kt
@@ -0,0 +1,5 @@
+// IS_APPLICABLE: false
+// WITH_STDLIB
+fun test() {
+ val x = " |a".trimMargin()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/referenceMarginPrefixArgument.kt b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/referenceMarginPrefixArgument.kt
new file mode 100644
index 000000000000..03ce099fe6fb
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/referenceMarginPrefixArgument.kt
@@ -0,0 +1,9 @@
+// IS_APPLICABLE: false
+// WITH_STDLIB
+fun test(marginPrefix: String) {
+ val x =
+ """
+ |a
+ |b
+ """.trimMargin(marginPrefix)
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple.kt b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple.kt
new file mode 100644
index 000000000000..587d58387e77
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple.kt
@@ -0,0 +1,10 @@
+// AFTER-WARNING: Variable 'x' is never used
+// INTENTION_TEXT: "Convert to trimIndent() call"
+// WITH_STDLIB
+fun test() {
+ val x =
+ """
+ |a
+ |b
+ """.trimMargin()
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple.kt.after b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple.kt.after
new file mode 100644
index 000000000000..52f610cdaf99
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple.kt.after
@@ -0,0 +1,10 @@
+// AFTER-WARNING: Variable 'x' is never used
+// INTENTION_TEXT: "Convert to trimIndent() call"
+// WITH_STDLIB
+fun test() {
+ val x =
+ """
+ a
+ b
+ """.trimIndent()
+}
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple2.kt b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple2.kt
new file mode 100644
index 000000000000..1752e59ed718
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple2.kt
@@ -0,0 +1,9 @@
+// AFTER-WARNING: Variable 'x' is never used
+// WITH_STDLIB
+fun test() {
+ val x =
+ """
+ #a
+ #b
+ """.trimMargin("#")
+}
\ No newline at end of file
diff --git a/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple2.kt.after b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple2.kt.after
new file mode 100644
index 000000000000..65d3311c2f4a
--- /dev/null
+++ b/plugins/kotlin/idea/tests/testData/intentions/convertTrimMarginToTrimIndent/simple2.kt.after
@@ -0,0 +1,9 @@
+// AFTER-WARNING: Variable 'x' is never used
+// WITH_STDLIB
+fun test() {
+ val x =
+ """
+ a
+ b
+ """.trimIndent()
+}
diff --git a/plugins/kotlin/plugin/k1/resources/META-INF/inspections-fe10.xml b/plugins/kotlin/plugin/k1/resources/META-INF/inspections-fe10.xml
index b8b1fe2e1a64..dccbbf26418d 100644
--- a/plugins/kotlin/plugin/k1/resources/META-INF/inspections-fe10.xml
+++ b/plugins/kotlin/plugin/k1/resources/META-INF/inspections-fe10.xml
@@ -924,6 +924,20 @@
group.names.kotlin
+
+ kotlin
+ org.jetbrains.kotlin.idea.intentions.ConvertTrimMarginToTrimIndentIntention
+ messages.KotlinBundle
+ group.names.kotlin
+
+
+
+ kotlin
+ org.jetbrains.kotlin.idea.intentions.ConvertTrimIndentToTrimMarginIntention
+ messages.KotlinBundle
+ group.names.kotlin
+
+
kotlin
org.jetbrains.kotlin.idea.intentions.ConvertPropertyGetterToInitializerIntention