diff --git a/idea/src/META-INF/plugin.xml.172 b/idea/src/META-INF/plugin.xml.172
index 3dedcd701e4..a47e4c5e90e 100644
--- a/idea/src/META-INF/plugin.xml.172
+++ b/idea/src/META-INF/plugin.xml.172
@@ -586,6 +586,7 @@
+
+
diff --git a/idea/src/META-INF/plugin.xml.173 b/idea/src/META-INF/plugin.xml.173
index 92f44b0b6a6..a4194405983 100644
--- a/idea/src/META-INF/plugin.xml.173
+++ b/idea/src/META-INF/plugin.xml.173
@@ -587,6 +587,7 @@
+
+
diff --git a/idea/src/META-INF/plugin.xml.182 b/idea/src/META-INF/plugin.xml.182
index 31a0249849b..c698bbb2d4f 100644
--- a/idea/src/META-INF/plugin.xml.182
+++ b/idea/src/META-INF/plugin.xml.182
@@ -587,6 +587,7 @@
+
+
diff --git a/idea/src/META-INF/plugin.xml.as31 b/idea/src/META-INF/plugin.xml.as31
index 9fd9279a8df..9f20ef0f078 100644
--- a/idea/src/META-INF/plugin.xml.as31
+++ b/idea/src/META-INF/plugin.xml.as31
@@ -586,6 +586,7 @@
+
+
diff --git a/idea/src/META-INF/plugin.xml.as32 b/idea/src/META-INF/plugin.xml.as32
index 53a9f3d769d..baf4d8c654c 100644
--- a/idea/src/META-INF/plugin.xml.as32
+++ b/idea/src/META-INF/plugin.xml.as32
@@ -586,6 +586,7 @@
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/KotlinRawStringBackspaceHandler.kt b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinRawStringBackspaceHandler.kt
index 60bb29c0ca1..be22b87c2aa 100644
--- a/idea/src/org/jetbrains/kotlin/idea/editor/KotlinRawStringBackspaceHandler.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinRawStringBackspaceHandler.kt
@@ -21,7 +21,6 @@ import com.intellij.codeInsight.editorActions.BackspaceHandlerDelegate
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.RangeMarker
import com.intellij.psi.PsiFile
-import com.intellij.psi.util.parentOfType
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
@@ -39,8 +38,8 @@ class KotlinRawStringBackspaceHandler : BackspaceHandlerDelegate() {
val offset = editor.caretModel.offset
val psiElement = file.findElementAt(offset) ?: return
- psiElement.parentOfType(KtStringTemplateExpression::class)?.let {
- if (it.text == "\"\"\"\"\"\"") {
+ psiElement.parent?.let {
+ if (it is KtStringTemplateExpression && it.text == "\"\"\"\"\"\"") {
if (editor.caretModel.offset == it.textOffset + 3) {
rangeMarker = editor.document.createRangeMarker(it.textRange)
}
@@ -54,6 +53,7 @@ class KotlinRawStringBackspaceHandler : BackspaceHandlerDelegate() {
rangeMarker = null
return true
}
+
return false
}
}
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/KotlinRawStringTypedHandler.kt b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinRawStringTypedHandler.kt
index 5b0dcebda58..c9934dcd3e0 100644
--- a/idea/src/org/jetbrains/kotlin/idea/editor/KotlinRawStringTypedHandler.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinRawStringTypedHandler.kt
@@ -22,40 +22,46 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileTypes.FileType
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
-import com.intellij.psi.util.PsiTreeUtil
+import com.intellij.psi.impl.source.tree.LeafPsiElement
+import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtFile
-import org.jetbrains.kotlin.psi.KtStringTemplateExpression
class KotlinRawStringTypedHandler : TypedHandlerDelegate() {
override fun beforeCharTyped(c: Char, project: Project, editor: Editor, file: PsiFile, fileType: FileType): Result {
+ if (c != '"') {
+ return Result.CONTINUE
+ }
if (!CodeInsightSettings.getInstance().AUTOINSERT_PAIR_QUOTE) {
return Result.CONTINUE
}
if (file !is KtFile) {
return Result.CONTINUE
}
- if (c != '"') {
- return Result.CONTINUE
- }
+
// A quote is typed after 2 other quotes
val offset = editor.caretModel.offset
- // Check for caret at end of document
- if (offset < editor.document.textLength) {
- val psiElement = file.findElementAt(offset) ?: return Result.CONTINUE
- if (PsiTreeUtil.getParentOfType(psiElement, KtStringTemplateExpression::class.java) != null) {
- return Result.CONTINUE
- }
+ if (offset < 2) {
+ return Result.CONTINUE
}
- val text = editor.document.text
- if (offset >= 2)
- if (text[offset - 1] == '"')
- if (text[offset - 2] == '"') {
- editor.document.insertString(offset, "\"\"\"\"")
- editor.caretModel.currentCaret.moveToOffset(offset + 1)
- return Result.STOP
- }
+ val openQuote = file.findElementAt(offset - 2)
+ if (openQuote == null || openQuote !is LeafPsiElement || openQuote.elementType != KtTokens.OPEN_QUOTE) {
+ return Result.CONTINUE
+ }
- return Result.CONTINUE
+ val closeQuote = file.findElementAt(offset - 1)
+ if (closeQuote == null || closeQuote !is LeafPsiElement || closeQuote.elementType != KtTokens.CLOSING_QUOTE) {
+ return Result.CONTINUE
+ }
+
+ if (closeQuote.text != "\"") {
+ // Check it is not a multi-line quote
+ return Result.CONTINUE
+ }
+
+ editor.document.insertString(offset, "\"\"\"\"")
+ editor.caretModel.currentCaret.moveToOffset(offset + 1)
+
+ return Result.STOP
}
}
\ No newline at end of file
diff --git a/idea/testData/editor/backspaceHandler/rawStringDelete.kt b/idea/testData/editor/backspaceHandler/rawStringDelete.kt
index 389cf906644..119dda63202 100644
--- a/idea/testData/editor/backspaceHandler/rawStringDelete.kt
+++ b/idea/testData/editor/backspaceHandler/rawStringDelete.kt
@@ -1 +1 @@
-"\"\"\"\"\"\""
\ No newline at end of file
+val test = """"""
\ No newline at end of file
diff --git a/idea/testData/editor/backspaceHandler/rawStringDelete.kt.after b/idea/testData/editor/backspaceHandler/rawStringDelete.kt.after
index 81389d50841..141510fa632 100644
--- a/idea/testData/editor/backspaceHandler/rawStringDelete.kt.after
+++ b/idea/testData/editor/backspaceHandler/rawStringDelete.kt.after
@@ -1 +1 @@
-
\ No newline at end of file
+val test =
\ No newline at end of file
diff --git a/idea/testData/editor/backspaceHandler/rawStringInCloseQuote.kt b/idea/testData/editor/backspaceHandler/rawStringInCloseQuote.kt
new file mode 100644
index 00000000000..a4699fa6ee2
--- /dev/null
+++ b/idea/testData/editor/backspaceHandler/rawStringInCloseQuote.kt
@@ -0,0 +1 @@
+val test = """"""
\ No newline at end of file
diff --git a/idea/testData/editor/backspaceHandler/rawStringInCloseQuote.kt.after b/idea/testData/editor/backspaceHandler/rawStringInCloseQuote.kt.after
new file mode 100644
index 00000000000..dae3d449f22
--- /dev/null
+++ b/idea/testData/editor/backspaceHandler/rawStringInCloseQuote.kt.after
@@ -0,0 +1 @@
+val test = """""
\ No newline at end of file
diff --git a/idea/testData/editor/backspaceHandler/rawStringInOpenQuote.kt b/idea/testData/editor/backspaceHandler/rawStringInOpenQuote.kt
new file mode 100644
index 00000000000..7c950f4547b
--- /dev/null
+++ b/idea/testData/editor/backspaceHandler/rawStringInOpenQuote.kt
@@ -0,0 +1 @@
+val test = """"""
\ No newline at end of file
diff --git a/idea/testData/editor/backspaceHandler/rawStringInOpenQuote.kt.after b/idea/testData/editor/backspaceHandler/rawStringInOpenQuote.kt.after
new file mode 100644
index 00000000000..bfac88bd19f
--- /dev/null
+++ b/idea/testData/editor/backspaceHandler/rawStringInOpenQuote.kt.after
@@ -0,0 +1 @@
+val test = """""
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/kotlin/idea/editor/TypedHandlerTest.kt b/idea/tests/org/jetbrains/kotlin/idea/editor/TypedHandlerTest.kt
index 70d7d4d0025..3c10d5f3493 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/editor/TypedHandlerTest.kt
+++ b/idea/tests/org/jetbrains/kotlin/idea/editor/TypedHandlerTest.kt
@@ -74,10 +74,46 @@ class TypedHandlerTest : LightCodeInsightTestCase() {
"""val x = "$dollar{}]" """
)
- fun testAutoCloseRawString() = doCharTypeTest(
+ fun testAutoCloseRawStringInEnd() = doCharTypeTest(
'"',
"""val x = """"",
- """val x = ""${'"'}"""${'"'}"""
+ """val x = ""${'"'}""${'"'}"""
+ )
+
+ fun testNoAutoCloseRawStringInEnd() = doCharTypeTest(
+ '"',
+ """val x = ""${'"'}""",
+ """val x = ""${'"'}""""
+ )
+
+ fun testAutoCloseRawStringInMiddle() = doCharTypeTest(
+ '"',
+ """
+ val x = ""
+ val y = 12
+ """.trimIndent(),
+ """
+ val x = ""${'"'}""${'"'}
+ val y = 12
+ """.trimIndent()
+ )
+
+ fun testNoAutoCloseBetweenMultiQuotes() = doCharTypeTest(
+ '"',
+ """val x = ""${'"'}${'"'}""/**/""",
+ """val x = ""${'"'}${'"'}""/**/"""
+ )
+
+ fun testNoAutoCloseBetweenMultiQuotes1() = doCharTypeTest(
+ '"',
+ """val x = ""${'"'}""${'"'}/**/""",
+ """val x = ""${'"'}""${'"'}/**/"""
+ )
+
+ fun testNoAutoCloseAfterEscape() = doCharTypeTest(
+ '"',
+ """val x = "\""""",
+ """val x = "\""${'"'}""""
)
fun testAutoCloseBraceInFunctionDeclaration() = doCharTypeTest(
diff --git a/idea/tests/org/jetbrains/kotlin/idea/editor/backspaceHandler/BackspaceHandlerTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/editor/backspaceHandler/BackspaceHandlerTestGenerated.java
index 0f58efcd586..55ea96ae218 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/editor/backspaceHandler/BackspaceHandlerTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/editor/backspaceHandler/BackspaceHandlerTestGenerated.java
@@ -29,6 +29,21 @@ public class BackspaceHandlerTestGenerated extends AbstractBackspaceHandlerTest
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/editor/backspaceHandler"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
+ @TestMetadata("rawStringDelete.kt")
+ public void testRawStringDelete() throws Exception {
+ runTest("idea/testData/editor/backspaceHandler/rawStringDelete.kt");
+ }
+
+ @TestMetadata("rawStringInCloseQuote.kt")
+ public void testRawStringInCloseQuote() throws Exception {
+ runTest("idea/testData/editor/backspaceHandler/rawStringInCloseQuote.kt");
+ }
+
+ @TestMetadata("rawStringInOpenQuote.kt")
+ public void testRawStringInOpenQuote() throws Exception {
+ runTest("idea/testData/editor/backspaceHandler/rawStringInOpenQuote.kt");
+ }
+
@TestMetadata("typeArguments.kt")
public void testTypeArguments() throws Exception {
runTest("idea/testData/editor/backspaceHandler/typeArguments.kt");