diff --git a/detekt-core/src/main/resources/default-detekt-config.yml b/detekt-core/src/main/resources/default-detekt-config.yml
index 462058ca590..e1bff89c1fc 100644
--- a/detekt-core/src/main/resources/default-detekt-config.yml
+++ b/detekt-core/src/main/resources/default-detekt-config.yml
@@ -642,6 +642,8 @@ style:
excludeGuardClauses: false
TrailingWhitespace:
active: false
+ TrimMultilineRawString:
+ active: false
UnderscoresInNumericLiterals:
active: false
acceptableLength: 4
diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/StyleGuideProvider.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/StyleGuideProvider.kt
index 4591807eb81..834e95b2f7d 100644
--- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/StyleGuideProvider.kt
+++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/StyleGuideProvider.kt
@@ -30,6 +30,7 @@ class StyleGuideProvider : DefaultRuleSetProvider {
DestructuringDeclarationWithTooManyEntries(config),
ReturnCount(config),
ThrowsCount(config),
+ TrimMultilineRawString(config),
NewLineAtEndOfFile(config),
WildcardImport(config),
FileParsingRule(config),
diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/TrimMultilineRawString.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/TrimMultilineRawString.kt
new file mode 100644
index 00000000000..d2d215ee919
--- /dev/null
+++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/TrimMultilineRawString.kt
@@ -0,0 +1,74 @@
+package io.gitlab.arturbosch.detekt.rules.style
+
+import io.gitlab.arturbosch.detekt.api.CodeSmell
+import io.gitlab.arturbosch.detekt.api.Config
+import io.gitlab.arturbosch.detekt.api.Debt
+import io.gitlab.arturbosch.detekt.api.Entity
+import io.gitlab.arturbosch.detekt.api.Issue
+import io.gitlab.arturbosch.detekt.api.Rule
+import io.gitlab.arturbosch.detekt.api.Severity
+import org.jetbrains.kotlin.psi.KtCallExpression
+import org.jetbrains.kotlin.psi.KtExpression
+import org.jetbrains.kotlin.psi.KtStringTemplateExpression
+import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForReceiver
+import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
+
+/**
+ * All the Raw strings that have more than one line should be followed by `trimMargin()` or `trimIndent()`.
+ *
+ *
+ * """
+ * Hello World!
+ * How are you?
+ * """
+ *
+ *
+ *
+ * """
+ * | Hello World!
+ * | How are you?
+ * """.trimMargin()
+ *
+ * """
+ * Hello World!
+ * How are you?
+ * """.trimIndent()
+ *
+ * """Hello World! How are you?"""
+ *
+ */
+class TrimMultilineRawString(val config: Config) : Rule(config) {
+ override val issue = Issue(
+ javaClass.simpleName,
+ Severity.Style,
+ "Multiline raw strings should be followed by `trimMargin()` or `trimIndent()`.",
+ Debt.FIVE_MINS
+ )
+
+ override fun visitStringTemplateExpression(expression: KtStringTemplateExpression) {
+ super.visitStringTemplateExpression(expression)
+
+ if (expression.text.lines().count() <= 1) return
+
+ val nextCall = expression.getQualifiedExpressionForSelectorOrThis()
+ .getQualifiedExpressionForReceiver()
+ ?.selectorExpression
+ ?.asKtCallExpression()
+ ?.calleeExpression
+ ?.text
+
+ if (nextCall !in trimFunctions) {
+ report(
+ CodeSmell(
+ issue,
+ Entity.from(expression),
+ "Multiline raw strings should be followed by `trimMargin()` or `trimIndent()`",
+ )
+ )
+ }
+ }
+}
+
+private fun KtExpression.asKtCallExpression(): KtCallExpression? = this as? KtCallExpression
+
+private val trimFunctions = listOf("trimIndent", "trimMargin")
diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/TrimMultilineRawStringSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/TrimMultilineRawStringSpec.kt
new file mode 100644
index 00000000000..d09235756ac
--- /dev/null
+++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/TrimMultilineRawStringSpec.kt
@@ -0,0 +1,87 @@
+@file:Suppress("StringTemplate")
+
+package io.gitlab.arturbosch.detekt.rules.style
+
+import io.gitlab.arturbosch.detekt.api.Config
+import io.gitlab.arturbosch.detekt.test.compileAndLint
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.Test
+
+class TrimMultilineRawStringSpec {
+ val subject = TrimMultilineRawString(Config.empty)
+
+ @Test
+ fun `raises multiline raw strings without trim`() {
+ val code = """
+ val a = ${TQ}
+ Hello world!
+ ${TQ}
+ """
+ subject.compileAndLint(code)
+ assertThat(subject.findings).hasSize(1)
+ }
+
+ @Test
+ fun `raises multiline raw strings with lenght`() {
+ val code = """
+ val a = ${TQ}
+ Hello world!
+ ${TQ}.length
+ """
+ subject.compileAndLint(code)
+ assertThat(subject.findings).hasSize(1)
+ }
+
+ @Test
+ fun `doesn't raise multiline raw strings without trimIndent`() {
+ val code = """
+ val a = ${TQ}
+ Hello world!
+ ${TQ}.trimIndent()
+ """
+ subject.compileAndLint(code)
+ assertThat(subject.findings).isEmpty()
+ }
+
+ @Test
+ fun `doesn't raise multiline raw strings without trimMargin`() {
+ val code = """
+ val a = ${TQ}
+ |Hello world!
+ ${TQ}.trimMargin()
+ """
+ subject.compileAndLint(code)
+ assertThat(subject.findings).isEmpty()
+ }
+
+ @Test
+ fun `doesn't raise multiline raw strings without trimMargin with parameter`() {
+ val code = """
+ val a = ${TQ}
+ >Hello world!
+ ${TQ}.trimMargin(">")
+ """
+ subject.compileAndLint(code)
+ assertThat(subject.findings).isEmpty()
+ }
+
+ @Test
+ fun `don't raise one line raw strings`() {
+ val code = """
+ val a = ${TQ}Hello world!${TQ}
+ """
+ subject.compileAndLint(code)
+ assertThat(subject.findings).isEmpty()
+ }
+
+ @Test
+ fun `doesn't raise if it is not a raw string`() {
+ val code = """
+ val a = "Hello world!"
+ """
+ subject.compileAndLint(code)
+ assertThat(subject.findings).isEmpty()
+ }
+}
+
+private const val TQ = "\"\"\""