diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 8acca2d6ba1..84d32d3bd3c 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -458,6 +458,7 @@ id="KotlinEnterHandler" order="before EnterBetweenBracesHandler"/> + diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/KotlinStringTemplateBackspaceHandler.kt b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinStringTemplateBackspaceHandler.kt new file mode 100644 index 00000000000..10fbd523476 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinStringTemplateBackspaceHandler.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2016 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.editor + +import com.intellij.codeInsight.CodeInsightSettings +import com.intellij.codeInsight.editorActions.BackspaceHandlerDelegate +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.editor.ex.EditorEx +import com.intellij.psi.PsiFile +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.KtFile + +class KotlinStringTemplateBackspaceHandler : BackspaceHandlerDelegate() { + override fun beforeCharDeleted(c: Char, file: PsiFile?, editor: Editor?) { + if (c != '{' || file !is KtFile || !CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET) return + + val offset = editor?.caretModel?.offset ?: return + + val highlighter = (editor as EditorEx).highlighter + val iterator = highlighter.createIterator(offset) + if (iterator.tokenType != KtTokens.LONG_TEMPLATE_ENTRY_END) return + iterator.retreat() + if (iterator.tokenType != KtTokens.LONG_TEMPLATE_ENTRY_START) return + editor.document.deleteString(offset, offset + 1) + } + + override fun charDeleted(c: Char, file: PsiFile?, editor: Editor?): Boolean { + return false + } +} \ No newline at end of file diff --git a/idea/testData/editor/stringTemplateBackspaceHandler/escapedStringTemplate.kt b/idea/testData/editor/stringTemplateBackspaceHandler/escapedStringTemplate.kt new file mode 100644 index 00000000000..cb91d36040a --- /dev/null +++ b/idea/testData/editor/stringTemplateBackspaceHandler/escapedStringTemplate.kt @@ -0,0 +1 @@ +"\${}" \ No newline at end of file diff --git a/idea/testData/editor/stringTemplateBackspaceHandler/escapedStringTemplate_after.kt b/idea/testData/editor/stringTemplateBackspaceHandler/escapedStringTemplate_after.kt new file mode 100644 index 00000000000..de27ab232de --- /dev/null +++ b/idea/testData/editor/stringTemplateBackspaceHandler/escapedStringTemplate_after.kt @@ -0,0 +1 @@ +"\$}" \ No newline at end of file diff --git a/idea/testData/editor/stringTemplateBackspaceHandler/stringTemplateBrackets.kt b/idea/testData/editor/stringTemplateBackspaceHandler/stringTemplateBrackets.kt new file mode 100644 index 00000000000..ace345d1e6f --- /dev/null +++ b/idea/testData/editor/stringTemplateBackspaceHandler/stringTemplateBrackets.kt @@ -0,0 +1 @@ +"${}" \ No newline at end of file diff --git a/idea/testData/editor/stringTemplateBackspaceHandler/stringTemplateBrackets_after.kt b/idea/testData/editor/stringTemplateBackspaceHandler/stringTemplateBrackets_after.kt new file mode 100644 index 00000000000..a7a0687106c --- /dev/null +++ b/idea/testData/editor/stringTemplateBackspaceHandler/stringTemplateBrackets_after.kt @@ -0,0 +1 @@ +"$" \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/editor/AbstractEditorTest.java b/idea/tests/org/jetbrains/kotlin/idea/editor/AbstractEditorTest.java new file mode 100644 index 00000000000..e02f0b67295 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/editor/AbstractEditorTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2016 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.editor; + +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.testFramework.EditorTestUtil; +import com.intellij.testFramework.LightCodeInsightTestCase; +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase; + +import java.io.File; + +public abstract class AbstractEditorTest extends LightCodeInsightTestCase { + protected abstract String getBasePath(); + + protected String loadFile(String name) throws Exception { + return FileUtil.loadFile(new File(getBasePath(), name), true); + } + + protected void configure() throws Exception { + configureFromFileText("a.kt", loadFile(getTestName(true) + ".kt")); + } + + protected void check() throws Exception { + checkResultByText(loadFile(getTestName(true) + "_after.kt")); + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/editor/KotlinCommenterTest.java b/idea/tests/org/jetbrains/kotlin/idea/editor/KotlinCommenterTest.java index bcaf0565bc5..ba22424790f 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/editor/KotlinCommenterTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/editor/KotlinCommenterTest.java @@ -23,7 +23,7 @@ import org.jetbrains.kotlin.idea.test.PluginTestCaseBase; import java.io.File; -public class KotlinCommenterTest extends LightCodeInsightTestCase { +public class KotlinCommenterTest extends AbstractEditorTest { private static final String BASE_PATH = new File(PluginTestCaseBase.getTestDataPathBase(), "/editor/commenter/").getAbsolutePath(); @@ -45,15 +45,8 @@ public class KotlinCommenterTest extends LightCodeInsightTestCase { check(); } - private void configure() throws Exception { - configureFromFileText("a.kt", loadFile(getTestName(true) + ".kt")); - } - - private void check() throws Exception { - checkResultByText(loadFile(getTestName(true) + "_after.kt")); - } - - protected static String loadFile(String name) throws Exception { - return FileUtil.loadFile(new File(BASE_PATH, name), true); + @Override + protected String getBasePath() { + return BASE_PATH; } } diff --git a/idea/tests/org/jetbrains/kotlin/idea/editor/StringTemplateBackspaceHandlerTest.kt b/idea/tests/org/jetbrains/kotlin/idea/editor/StringTemplateBackspaceHandlerTest.kt new file mode 100644 index 00000000000..a0a3f229a19 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/editor/StringTemplateBackspaceHandlerTest.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2016 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.editor + +import com.intellij.openapi.actionSystem.IdeActions +import com.intellij.testFramework.EditorTestUtil +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase +import java.io.File + +class StringTemplateBackspaceHandlerTest : AbstractEditorTest() { + val path = File(PluginTestCaseBase.getTestDataPathBase(), "/editor/stringTemplateBackspaceHandler/").getAbsolutePath() + + override fun getBasePath(): String? { + return path + } + + fun testStringTemplateBrackets() { + doTest() + } + + fun testEscapedStringTemplate() { + doTest() + } + + fun doTest() { + configure() + EditorTestUtil.executeAction(getEditor(), IdeActions.ACTION_EDITOR_BACKSPACE) + check() + } +}