From 395a817ada8e909fcd62410587dafa0e155b007e Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Fri, 1 Dec 2017 17:32:17 +0300 Subject: [PATCH] 181: compilation fixes related to `BackspaceHandlerDelegate` and `DocumentWindowImpl` changes in IDEA 181 --- ...otlinStringTemplateBackspaceHandler.kt.181 | 44 ++++++ .../kotlin/psi/AbstractInjectionTest.kt.181 | 134 ++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 idea/src/org/jetbrains/kotlin/idea/editor/KotlinStringTemplateBackspaceHandler.kt.181 create mode 100644 idea/tests/org/jetbrains/kotlin/psi/AbstractInjectionTest.kt.181 diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/KotlinStringTemplateBackspaceHandler.kt.181 b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinStringTemplateBackspaceHandler.kt.181 new file mode 100644 index 00000000000..fd2bb4abada --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinStringTemplateBackspaceHandler.kt.181 @@ -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/tests/org/jetbrains/kotlin/psi/AbstractInjectionTest.kt.181 b/idea/tests/org/jetbrains/kotlin/psi/AbstractInjectionTest.kt.181 new file mode 100644 index 00000000000..a4b2cfc6a27 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/psi/AbstractInjectionTest.kt.181 @@ -0,0 +1,134 @@ +/* + * 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.psi + +import com.intellij.injected.editor.EditorWindow +import com.intellij.lang.injection.InjectedLanguageManager +import com.intellij.openapi.util.TextRange +import com.intellij.psi.injection.Injectable +import com.intellij.testFramework.LightProjectDescriptor +import junit.framework.TestCase +import org.intellij.lang.annotations.Language +import org.intellij.plugins.intelliLang.Configuration +import org.intellij.plugins.intelliLang.inject.InjectLanguageAction +import org.intellij.plugins.intelliLang.inject.UnInjectLanguageAction +import org.intellij.plugins.intelliLang.references.FileReferenceInjector +import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCaseBase +import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor +import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor +import org.jetbrains.kotlin.utils.SmartList + +abstract class AbstractInjectionTest : KotlinLightCodeInsightFixtureTestCase() { + override fun getProjectDescriptor(): LightProjectDescriptor { + val testName = getTestName(true) + return when { + testName.endsWith("WithAnnotation") -> KotlinLightProjectDescriptor.INSTANCE + testName.endsWith("WithRuntime") -> KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE + else -> KotlinLightCodeInsightFixtureTestCaseBase.JAVA_LATEST + } + } + + data class ShredInfo( + val range: TextRange, + val hostRange: TextRange, + val prefix: String = "", + val suffix: String = "") { + } + + protected fun doInjectionPresentTest( + @Language("kotlin") text: String, @Language("Java") javaText: String? = null, + languageId: String? = null, unInjectShouldBePresent: Boolean = true, + shreds: List? = null) { + if (javaText != null) { + myFixture.configureByText("${getTestName(true)}.java", javaText.trimIndent()) + } + + myFixture.configureByText("${getTestName(true)}.kt", text.trimIndent()) + + assertInjectionPresent(languageId, unInjectShouldBePresent) + + if (shreds != null) { + val actualShreds = SmartList().apply { + val host = InjectedLanguageManager.getInstance(project).getInjectionHost(file.viewProvider) + InjectedLanguageManager.getInstance(project).enumerate(host, { _, placesInFile -> + addAll(placesInFile.map { + ShredInfo(it.range, it.rangeInsideHost, it.prefix, it.suffix) + }) + }) + } + + assertOrderedEquals( + actualShreds.sortedBy { it.range.startOffset }, + shreds.sortedBy { it.range.startOffset }) + } + } + + protected fun assertInjectionPresent(languageId: String?, unInjectShouldBePresent: Boolean) { + TestCase.assertFalse("Injection action is available. There's probably no injection at caret place", + InjectLanguageAction().isAvailable(project, myFixture.editor, myFixture.file)) + + if (languageId != null) { + val injectedFile = (editor as? EditorWindow)?.injectedFile + assertEquals("Wrong injection language", languageId, injectedFile?.language?.id) + } + + if (unInjectShouldBePresent) { + TestCase.assertTrue("UnInjection action is not available. There's no injection at caret place or some other troubles.", + UnInjectLanguageAction().isAvailable(project, myFixture.editor, myFixture.file)) + } + } + + protected fun assertNoInjection(@Language("kotlin") text: String) { + myFixture.configureByText("${getTestName(true)}.kt", text.trimIndent()) + + TestCase.assertTrue("Injection action is not available. There's probably some injection but nothing was expected.", + InjectLanguageAction().isAvailable(project, myFixture.editor, myFixture.file)) + } + + protected fun doRemoveInjectionTest(@Language("kotlin") before: String, @Language("kotlin") after: String) { + myFixture.setCaresAboutInjection(false) + + myFixture.configureByText("${getTestName(true)}.kt", before.trimIndent()) + + TestCase.assertTrue(UnInjectLanguageAction().isAvailable(project, myFixture.editor, myFixture.file)) + UnInjectLanguageAction.invokeImpl(project, myFixture.editor, myFixture.file) + + myFixture.checkResult(after.trimIndent()) + } + + protected fun doFileReferenceInjectTest(@Language("kotlin") before: String, @Language("kotlin") after: String) { + doTest(FileReferenceInjector(), before, after) + } + + protected fun doTest(injectable: Injectable, @Language("kotlin") before: String, @Language("kotlin") after: String) { + val configuration = Configuration.getProjectInstance(project).advancedConfiguration + val allowed = configuration.isSourceModificationAllowed + + configuration.isSourceModificationAllowed = true + try { + myFixture.configureByText("${getTestName(true)}.kt", before.trimIndent()) + InjectLanguageAction.invokeImpl(project, myFixture.editor, myFixture.file, injectable) + myFixture.checkResult(after.trimIndent()) + } + finally { + configuration.isSourceModificationAllowed = allowed + } + } + + fun range(start: Int, end: Int) = TextRange.create(start, end) +} \ No newline at end of file