diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index d8ef0840583..16a8122895b 100644 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -72,6 +72,7 @@ import org.jetbrains.kotlin.idea.highlighter.AbstractHighlightExitPointsTest import org.jetbrains.kotlin.idea.highlighter.AbstractHighlightingTest import org.jetbrains.kotlin.idea.imports.AbstractOptimizeImportsTest import org.jetbrains.kotlin.idea.intentions.AbstractIntentionTest +import org.jetbrains.kotlin.idea.intentions.AbstractMultiFileIntentionTest import org.jetbrains.kotlin.idea.intentions.declarations.AbstractJoinLinesTest import org.jetbrains.kotlin.idea.internal.AbstractBytecodeToolWindowTest import org.jetbrains.kotlin.idea.kdoc.AbstractKDocHighlightingTest @@ -497,6 +498,10 @@ fun main(args: Array) { model("refactoring/move", extension = "test", singleClass = true) } + testClass(javaClass()) { + model("multiFileIntentions", extension = "test", singleClass = true) + } + testClass(javaClass()) { model("configuration/android-gradle", pattern = """(\w+)_before\.gradle$""", testMethod = "doTestAndroidGradle") model("configuration/gradle", pattern = """(\w+)_before\.gradle$""", testMethod = "doTestGradle") diff --git a/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/KotlinMultiFileTestCase.kt b/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/KotlinMultiFileTestCase.kt index 1b637f226d7..9a4cbd4fa5d 100644 --- a/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/KotlinMultiFileTestCase.kt +++ b/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/KotlinMultiFileTestCase.kt @@ -16,11 +16,33 @@ package org.jetbrains.kotlin.idea.test +import com.intellij.openapi.editor.Document import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess +import com.intellij.psi.PsiDocumentManager import com.intellij.refactoring.MultiFileTestCase +import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.test.JetTestUtils public abstract class KotlinMultiFileTestCase : MultiFileTestCase() { + protected fun extractCaretOffset(doc: Document): Int { + val offset = runWriteAction { + val text = StringBuilder(doc.getText()) + val offset = text.indexOf("") + + if (offset >= 0) { + text.delete(offset, offset + "".length()) + doc.setText(text.toString()) + } + + offset + } + + PsiDocumentManager.getInstance(myProject).commitAllDocuments() + PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(doc) + + return offset + } + override fun setUp() { super.setUp() VfsRootAccess.allowRootAccess(JetTestUtils.getHomeDirectory()) diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/AbstractMultiFileIntentionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/intentions/AbstractMultiFileIntentionTest.kt new file mode 100644 index 00000000000..95b3e744e04 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/AbstractMultiFileIntentionTest.kt @@ -0,0 +1,102 @@ +/* + * Copyright 2010-2015 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.intentions + +import com.google.gson.JsonObject +import com.google.gson.JsonParser +import com.intellij.codeInsight.TargetElementUtilBase +import com.intellij.codeInsight.intention.IntentionAction +import com.intellij.openapi.editor.Document +import com.intellij.openapi.editor.EditorFactory +import com.intellij.openapi.fileEditor.FileDocumentManager +import com.intellij.openapi.util.io.FileUtil +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiManager +import com.intellij.refactoring.BaseRefactoringProcessor +import com.intellij.util.PathUtil +import junit.framework.TestCase +import org.jetbrains.kotlin.idea.refactoring.move.MoveAction +import org.jetbrains.kotlin.idea.refactoring.move.getNullableString +import org.jetbrains.kotlin.idea.refactoring.move.getString +import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil +import org.jetbrains.kotlin.idea.test.KotlinMultiFileTestCase +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase +import org.jetbrains.kotlin.idea.util.application.executeWriteCommand +import org.jetbrains.kotlin.idea.util.application.runWriteAction +import org.jetbrains.kotlin.test.JetTestUtils +import org.junit.Assert +import java.io.File + +public abstract class AbstractMultiFileIntentionTest : KotlinMultiFileTestCase() { + protected fun doTest(path: String) { + val config = JsonParser().parse(FileUtil.loadFile(File(path), true)) as JsonObject + val mainFilePath = config.getString("mainFile") + val intentionAction = Class.forName(config.getString("intentionClass")).newInstance() as IntentionAction + val isApplicableExpected = config["isApplicable"]?.getAsBoolean() ?: true + + val withRuntime = config["withRuntime"]?.getAsBoolean() ?: false + if (withRuntime) { + ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk()) + } + + doTest({ rootDir, rootAfter -> + val mainFile = rootDir.findFileByRelativePath(mainFilePath)!! + val document = FileDocumentManager.getInstance().getDocument(mainFile)!! + val editor = EditorFactory.getInstance()!!.createEditor(document, getProject()!!)!! + editor.getCaretModel().moveToOffset(extractCaretOffset(document)) + val mainPsiFile = PsiManager.getInstance(getProject()!!).findFile(mainFile)!! + + try { + Assert.assertTrue("isAvailable() for ${intentionAction.javaClass} should return $isApplicableExpected", + isApplicableExpected == intentionAction.isAvailable(getProject(), editor, mainPsiFile)) + config.getNullableString("intentionText")?.let { + TestCase.assertEquals("Intention text mismatch", it, intentionAction.getText()) + } + + if (isApplicableExpected) { + getProject().executeWriteCommand(intentionAction.getText()) { + intentionAction.invoke(getProject(), editor, mainPsiFile) + } + } + } + finally { + PsiDocumentManager.getInstance(getProject()!!).commitAllDocuments() + FileDocumentManager.getInstance().saveAllDocuments() + + EditorFactory.getInstance()!!.releaseEditor(editor) + + if (withRuntime) { + ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk()) + } + } + }, + getTestDirName(true)) + } + + protected fun getTestDirName(lowercaseFirstLetter : Boolean) : String { + val testName = getTestName(lowercaseFirstLetter) + return testName.substring(0, testName.lastIndexOf('_')).replace('_', '/') + } + + protected override fun getTestRoot() : String { + return "/multiFileIntentions/" + } + + protected override fun getTestDataPath() : String { + return PluginTestCaseBase.getTestDataPathBase() + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/MultiFileIntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/MultiFileIntentionTestGenerated.java new file mode 100644 index 00000000000..5f1983bce36 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/MultiFileIntentionTestGenerated.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2015 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.intentions; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.JetTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("idea/testData/multiFileIntentions") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class MultiFileIntentionTestGenerated extends AbstractMultiFileIntentionTest { + public void testAllFilesPresentInMultiFileIntentions() throws Exception { + JetTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("idea/testData/multiFileIntentions"), Pattern.compile("^(.+)\\.test$")); + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/AbstractJetMoveTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/AbstractJetMoveTest.kt index d631bee5be1..40bb6ee76dd 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/AbstractJetMoveTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/AbstractJetMoveTest.kt @@ -56,23 +56,8 @@ import java.io.File public abstract class AbstractJetMoveTest : KotlinMultiFileTestCase() { protected fun doTest(path: String) { - fun extractCaretOffset(doc: Document): Int { - return runWriteAction { - val text = StringBuilder(doc.getText()) - val offset = text.indexOf("") - - if (offset >= 0) { - text.delete(offset, offset + "".length()) - doc.setText(text.toString()) - } - - offset - } - } - val config = JsonParser().parse(FileUtil.loadFile(File(path), true)) as JsonObject - val action = MoveAction.valueOf(config.getString("type")) val testDir = path.substring(0, path.lastIndexOf("/"))