Deduplicate code in AbstractQuickFixMulti{File,Module}Test
This commit is contained in:
@@ -17,22 +17,23 @@
|
|||||||
package org.jetbrains.kotlin.idea.quickfix
|
package org.jetbrains.kotlin.idea.quickfix
|
||||||
|
|
||||||
import com.intellij.codeInsight.CodeInsightSettings
|
import com.intellij.codeInsight.CodeInsightSettings
|
||||||
|
import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
||||||
import com.intellij.codeInsight.daemon.quickFix.ActionHint
|
import com.intellij.codeInsight.daemon.quickFix.ActionHint
|
||||||
import com.intellij.codeInsight.intention.IntentionAction
|
import com.intellij.codeInsight.intention.IntentionAction
|
||||||
import com.intellij.codeInspection.InspectionEP
|
import com.intellij.codeInspection.InspectionEP
|
||||||
import com.intellij.codeInspection.LocalInspectionEP
|
import com.intellij.codeInspection.LocalInspectionEP
|
||||||
import com.intellij.ide.highlighter.JavaFileType
|
import com.intellij.ide.highlighter.JavaFileType
|
||||||
import com.intellij.openapi.command.CommandProcessor
|
import com.intellij.openapi.command.CommandProcessor
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.extensions.Extensions
|
import com.intellij.openapi.extensions.Extensions
|
||||||
import com.intellij.openapi.fileTypes.FileType
|
import com.intellij.openapi.fileTypes.FileType
|
||||||
import com.intellij.openapi.fileTypes.PlainTextFileType
|
import com.intellij.openapi.fileTypes.PlainTextFileType
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import com.intellij.openapi.vfs.CharsetToolkit
|
import com.intellij.openapi.vfs.CharsetToolkit
|
||||||
import com.intellij.openapi.vfs.LocalFileSystem
|
|
||||||
import com.intellij.openapi.vfs.VfsUtil
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.testFramework.VfsTestUtil
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
|
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
|
||||||
import com.intellij.util.ArrayUtil
|
import com.intellij.util.ArrayUtil
|
||||||
import com.intellij.util.containers.ContainerUtil
|
import com.intellij.util.containers.ContainerUtil
|
||||||
@@ -155,7 +156,7 @@ abstract class AbstractQuickFixMultiFileTest : KotlinLightCodeInsightFixtureTest
|
|||||||
DirectiveBasedActionUtils.checkForUnexpectedErrors(psiFile)
|
DirectiveBasedActionUtils.checkForUnexpectedErrors(psiFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
doAction(text, actionShouldBeAvailable, getTestName(false))
|
doAction(text, file, editor, actionShouldBeAvailable, getTestName(false), this::availableActions, myFixture::doHighlighting)
|
||||||
|
|
||||||
val actualText = file.text
|
val actualText = file.text
|
||||||
val afterText = StringBuilder(actualText).insert(editor.caretModel.offset, "<caret>").toString()
|
val afterText = StringBuilder(actualText).insert(editor.caretModel.offset, "<caret>").toString()
|
||||||
@@ -218,7 +219,7 @@ abstract class AbstractQuickFixMultiFileTest : KotlinLightCodeInsightFixtureTest
|
|||||||
DirectiveBasedActionUtils.checkForUnexpectedErrors(psiFile)
|
DirectiveBasedActionUtils.checkForUnexpectedErrors(psiFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
doAction(text, actionShouldBeAvailable, beforeFileName)
|
doAction(text, file, editor, actionShouldBeAvailable, beforeFileName, this::availableActions, myFixture::doHighlighting)
|
||||||
|
|
||||||
if (actionShouldBeAvailable) {
|
if (actionShouldBeAvailable) {
|
||||||
val afterFilePath = beforeFileName.replace(".before.Main.", ".after.")
|
val afterFilePath = beforeFileName.replace(".before.Main.", ".after.")
|
||||||
@@ -257,50 +258,6 @@ abstract class AbstractQuickFixMultiFileTest : KotlinLightCodeInsightFixtureTest
|
|||||||
}, "", "")
|
}, "", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(Exception::class)
|
|
||||||
fun doAction(text: String, actionShouldBeAvailable: Boolean, testFilePath: String) {
|
|
||||||
val pattern = if (text.startsWith("/"))
|
|
||||||
Pattern.compile(text.substring(1, text.length - 1))
|
|
||||||
else
|
|
||||||
Pattern.compile(StringUtil.escapeToRegexp(text))
|
|
||||||
|
|
||||||
val availableActions = availableActions
|
|
||||||
val action = findActionByPattern(pattern, availableActions)
|
|
||||||
|
|
||||||
if (action == null) {
|
|
||||||
if (actionShouldBeAvailable) {
|
|
||||||
val texts = getActionsTexts(availableActions)
|
|
||||||
val infos = myFixture.doHighlighting()
|
|
||||||
TestCase.fail("Action with text '" + text + "' is not available in test " + testFilePath + "\n" +
|
|
||||||
"Available actions (" + texts.size + "): \n" +
|
|
||||||
StringUtil.join(texts, "\n") +
|
|
||||||
"\nActions:\n" +
|
|
||||||
StringUtil.join(availableActions, "\n") +
|
|
||||||
"\nInfos:\n" +
|
|
||||||
StringUtil.join(infos, "\n"))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DirectiveBasedActionUtils.checkAvailableActionsAreExpected(file, availableActions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!actionShouldBeAvailable) {
|
|
||||||
TestCase.fail("Action '$text' is available (but must not) in test $testFilePath")
|
|
||||||
}
|
|
||||||
|
|
||||||
CodeInsightTestFixtureImpl.invokeIntention(action, file, editor, action.text)
|
|
||||||
|
|
||||||
if (!shouldBeAvailableAfterExecution()) {
|
|
||||||
val afterAction = findActionByPattern(pattern, this.availableActions)
|
|
||||||
|
|
||||||
if (afterAction != null) {
|
|
||||||
TestCase.fail("Action '$text' is still available after its invocation in test $testFilePath")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private val availableActions: List<IntentionAction>
|
private val availableActions: List<IntentionAction>
|
||||||
get() {
|
get() {
|
||||||
myFixture.doHighlighting()
|
myFixture.doHighlighting()
|
||||||
@@ -310,42 +267,70 @@ abstract class AbstractQuickFixMultiFileTest : KotlinLightCodeInsightFixtureTest
|
|||||||
class TestFile internal constructor(val path: String, val content: String)
|
class TestFile internal constructor(val path: String, val content: String)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private fun getActionsTexts(availableActions: List<IntentionAction>): List<String> =
|
||||||
|
availableActions.map(IntentionAction::getText)
|
||||||
|
|
||||||
protected fun shouldBeAvailableAfterExecution(): Boolean {
|
private fun extraFileNamePrefix(mainFileName: String): String =
|
||||||
return false
|
mainFileName.replace(".Main.kt", ".").replace(".Main.java", ".")
|
||||||
|
|
||||||
|
protected fun guessFileType(file: TestFile): FileType = when {
|
||||||
|
file.path.contains("." + KotlinFileType.EXTENSION) -> KotlinFileType.INSTANCE
|
||||||
|
file.path.contains("." + JavaFileType.DEFAULT_EXTENSION) -> JavaFileType.INSTANCE
|
||||||
|
else -> PlainTextFileType.INSTANCE
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getActionsTexts(availableActions: List<IntentionAction>): List<String> {
|
private fun findActionByPattern(pattern: Pattern, availableActions: List<IntentionAction>): IntentionAction? =
|
||||||
val texts = ArrayList<String>()
|
availableActions.firstOrNull { pattern.matcher(it.text).matches() }
|
||||||
for (intentionAction in availableActions) {
|
|
||||||
texts.add(intentionAction.text)
|
|
||||||
}
|
|
||||||
return texts
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun extraFileNamePrefix(mainFileName: String): String {
|
fun doAction(
|
||||||
return mainFileName.replace(".Main.kt", ".").replace(".Main.java", ".")
|
text: String,
|
||||||
}
|
file: PsiFile,
|
||||||
|
editor: Editor,
|
||||||
|
actionShouldBeAvailable: Boolean,
|
||||||
|
testFilePath: String,
|
||||||
|
getAvailableActions: () -> List<IntentionAction>,
|
||||||
|
doHighlighting: () -> List<HighlightInfo>,
|
||||||
|
shouldBeAvailableAfterExecution: Boolean = false
|
||||||
|
) {
|
||||||
|
val pattern = if (text.startsWith("/"))
|
||||||
|
Pattern.compile(text.substring(1, text.length - 1))
|
||||||
|
else
|
||||||
|
Pattern.compile(StringUtil.escapeToRegexp(text))
|
||||||
|
|
||||||
protected fun guessFileType(file: TestFile): FileType {
|
val availableActions = getAvailableActions()
|
||||||
if (file.path.contains("." + KotlinFileType.EXTENSION)) {
|
val action = findActionByPattern(pattern, availableActions)
|
||||||
return KotlinFileType.INSTANCE
|
|
||||||
}
|
|
||||||
else if (file.path.contains("." + JavaFileType.DEFAULT_EXTENSION)) {
|
|
||||||
return JavaFileType.INSTANCE
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return PlainTextFileType.INSTANCE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findActionByPattern(pattern: Pattern, availableActions: List<IntentionAction>): IntentionAction? {
|
if (action == null) {
|
||||||
for (availableAction in availableActions) {
|
if (actionShouldBeAvailable) {
|
||||||
if (pattern.matcher(availableAction.text).matches()) {
|
val texts = getActionsTexts(availableActions)
|
||||||
return availableAction
|
val infos = doHighlighting()
|
||||||
|
TestCase.fail("Action with text '" + text + "' is not available in test " + testFilePath + "\n" +
|
||||||
|
"Available actions (" + texts.size + "): \n" +
|
||||||
|
StringUtil.join(texts, "\n") +
|
||||||
|
"\nActions:\n" +
|
||||||
|
StringUtil.join(availableActions, "\n") +
|
||||||
|
"\nInfos:\n" +
|
||||||
|
StringUtil.join(infos, "\n"))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DirectiveBasedActionUtils.checkAvailableActionsAreExpected(file, availableActions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!actionShouldBeAvailable) {
|
||||||
|
TestCase.fail("Action '$text' is available (but must not) in test $testFilePath")
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeInsightTestFixtureImpl.invokeIntention(action, file, editor, action.text)
|
||||||
|
|
||||||
|
if (!shouldBeAvailableAfterExecution) {
|
||||||
|
val afterAction = findActionByPattern(pattern, getAvailableActions())
|
||||||
|
|
||||||
|
if (afterAction != null) {
|
||||||
|
TestCase.fail("Action '$text' is still available after its invocation in test $testFilePath")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,7 @@ package org.jetbrains.kotlin.idea.quickfix
|
|||||||
import com.intellij.codeInsight.daemon.quickFix.ActionHint
|
import com.intellij.codeInsight.daemon.quickFix.ActionHint
|
||||||
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase
|
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase
|
||||||
import com.intellij.codeInsight.intention.IntentionAction
|
import com.intellij.codeInsight.intention.IntentionAction
|
||||||
import com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler
|
|
||||||
import com.intellij.openapi.command.CommandProcessor
|
import com.intellij.openapi.command.CommandProcessor
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
|
||||||
import com.intellij.util.ui.UIUtil
|
|
||||||
import junit.framework.ComparisonFailure
|
import junit.framework.ComparisonFailure
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
import org.jetbrains.kotlin.idea.inspections.findExistingEditor
|
import org.jetbrains.kotlin.idea.inspections.findExistingEditor
|
||||||
@@ -34,17 +31,11 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.regex.Pattern
|
|
||||||
|
|
||||||
abstract class AbstractQuickFixMultiModuleTest : AbstractMultiModuleTest() {
|
abstract class AbstractQuickFixMultiModuleTest : AbstractMultiModuleTest() {
|
||||||
|
|
||||||
override fun getTestDataPath() = PluginTestCaseBase.getTestDataPathBase() + "/multiModuleQuickFix/"
|
override fun getTestDataPath() = PluginTestCaseBase.getTestDataPathBase() + "/multiModuleQuickFix/"
|
||||||
|
|
||||||
protected fun shouldBeAvailableAfterExecution(file: KtFile) =
|
|
||||||
InTextDirectivesUtils.isDirectiveDefined(file.text, "// SHOULD_BE_AVAILABLE_AFTER_EXECUTION")
|
|
||||||
|
|
||||||
private fun getActionsTexts(availableActions: List<IntentionAction>) = availableActions.map { it.text }
|
|
||||||
|
|
||||||
protected fun doQuickFixTest() {
|
protected fun doQuickFixTest() {
|
||||||
val allFilesInProject = PluginJetFilesProvider.allFilesInProject(myProject!!)
|
val allFilesInProject = PluginJetFilesProvider.allFilesInProject(myProject!!)
|
||||||
val actionFile = allFilesInProject.single { file ->
|
val actionFile = allFilesInProject.single { file ->
|
||||||
@@ -58,18 +49,19 @@ abstract class AbstractQuickFixMultiModuleTest : AbstractMultiModuleTest() {
|
|||||||
|
|
||||||
CommandProcessor.getInstance().executeCommand(project, {
|
CommandProcessor.getInstance().executeCommand(project, {
|
||||||
try {
|
try {
|
||||||
val psiFile = actionFile
|
val actionHint = ActionHint.parse(actionFile, actionFileText)
|
||||||
|
|
||||||
val actionHint = ActionHint.parse(psiFile, actionFileText)
|
|
||||||
val text = actionHint.expectedText
|
val text = actionHint.expectedText
|
||||||
|
|
||||||
val actionShouldBeAvailable = actionHint.shouldPresent()
|
val actionShouldBeAvailable = actionHint.shouldPresent()
|
||||||
|
|
||||||
if (psiFile is KtFile) {
|
if (actionFile is KtFile) {
|
||||||
DirectiveBasedActionUtils.checkForUnexpectedErrors(psiFile)
|
DirectiveBasedActionUtils.checkForUnexpectedErrors(actionFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
doAction(text, actionShouldBeAvailable, actionFileName, actionFile)
|
AbstractQuickFixMultiFileTest.doAction(
|
||||||
|
text, file, editor, actionShouldBeAvailable, actionFileName, this::availableActions, this::doHighlighting,
|
||||||
|
InTextDirectivesUtils.isDirectiveDefined(actionFile.text, "// SHOULD_BE_AVAILABLE_AFTER_EXECUTION")
|
||||||
|
)
|
||||||
|
|
||||||
if (actionShouldBeAvailable) {
|
if (actionShouldBeAvailable) {
|
||||||
val testDirectory = File(testDataPath)
|
val testDirectory = File(testDataPath)
|
||||||
@@ -106,66 +98,11 @@ abstract class AbstractQuickFixMultiModuleTest : AbstractMultiModuleTest() {
|
|||||||
}, "", "")
|
}, "", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: merge with AbstractQuickFixMultiFileTest
|
private val availableActions: List<IntentionAction>
|
||||||
|
get() {
|
||||||
fun doAction(text: String, actionShouldBeAvailable: Boolean, testFilePath: String, actionFile: KtFile) {
|
doHighlighting()
|
||||||
val pattern = if (text.startsWith("/"))
|
return LightQuickFixTestCase.getAvailableActions(editor, file)
|
||||||
Pattern.compile(text.substring(1, text.length - 1))
|
|
||||||
else
|
|
||||||
Pattern.compile(StringUtil.escapeToRegexp(text))
|
|
||||||
|
|
||||||
val availableActions = getAvailableActions()
|
|
||||||
val action = findActionByPattern(pattern, availableActions)
|
|
||||||
|
|
||||||
if (action == null) {
|
|
||||||
if (actionShouldBeAvailable) {
|
|
||||||
val texts = getActionsTexts(availableActions)
|
|
||||||
val infos = doHighlighting()
|
|
||||||
TestCase.fail("Action with text '" + text + "' is not available in test " + testFilePath + "\n" +
|
|
||||||
"Available actions (" + texts.size + "): \n" +
|
|
||||||
StringUtil.join(texts, "\n") +
|
|
||||||
"\nActions:\n" +
|
|
||||||
StringUtil.join(availableActions, "\n") +
|
|
||||||
"\nInfos:\n" +
|
|
||||||
StringUtil.join(infos, "\n"))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DirectiveBasedActionUtils.checkAvailableActionsAreExpected(file, availableActions)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (!actionShouldBeAvailable) {
|
|
||||||
TestCase.fail("Action '$text' is available (but must not) in test $testFilePath")
|
|
||||||
}
|
|
||||||
|
|
||||||
ShowIntentionActionsHandler.chooseActionAndInvoke(file, editor, action, action.text)
|
|
||||||
|
|
||||||
UIUtil.dispatchAllInvocationEvents()
|
|
||||||
|
|
||||||
|
|
||||||
if (!shouldBeAvailableAfterExecution(actionFile)) {
|
|
||||||
val afterAction = findActionByPattern(pattern, getAvailableActions())
|
|
||||||
|
|
||||||
if (afterAction != null) {
|
|
||||||
TestCase.fail("Action '$text' is still available after its invocation in test $testFilePath")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findActionByPattern(pattern: Pattern, availableActions: List<IntentionAction>): IntentionAction? {
|
|
||||||
for (availableAction in availableActions) {
|
|
||||||
if (pattern.matcher(availableAction.text).matches()) {
|
|
||||||
return availableAction
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getAvailableActions(): List<IntentionAction> {
|
|
||||||
doHighlighting()
|
|
||||||
return LightQuickFixTestCase.getAvailableActions(editor, file)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getTestProjectJdk() = PluginTestCaseBase.mockJdk()
|
override fun getTestProjectJdk() = PluginTestCaseBase.mockJdk()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user