AbstractIntentionTest: J2K

This commit is contained in:
Dmitry Jemerov
2017-03-22 17:12:45 +01:00
parent 68ec8b3077
commit 24bdf994a9
@@ -14,246 +14,222 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.intentions; package org.jetbrains.kotlin.idea.intentions
import com.google.common.collect.Lists; import com.google.common.collect.Lists
import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.ide.startup.impl.StartupManagerImpl; import com.intellij.ide.startup.impl.StartupManagerImpl
import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.startup.StartupManager
import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Computable
import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.SystemInfo
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.psi.PsiFile; import com.intellij.psi.PsiFile
import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.BaseRefactoringProcessor
import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.refactoring.util.CommonRefactoringUtil
import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.PlatformTestUtil
import com.intellij.util.PathUtil; import com.intellij.util.PathUtil
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil
import com.intellij.util.containers.Convertor; import com.intellij.util.containers.Convertor
import junit.framework.ComparisonFailure; import junit.framework.ComparisonFailure
import kotlin.jvm.functions.Function0; import junit.framework.TestCase
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil; import org.jetbrains.kotlin.idea.test.DirectiveBasedActionUtils
import org.jetbrains.kotlin.idea.test.DirectiveBasedActionUtils; import org.jetbrains.kotlin.idea.test.KotlinCodeInsightTestCase
import org.jetbrains.kotlin.idea.test.KotlinCodeInsightTestCase; import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase; import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.idea.util.application.ApplicationUtilsKt; import org.jetbrains.kotlin.psi.KtFile
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 org.junit.Assert
import org.junit.Assert; import java.io.File
import java.util.*
import java.io.File; abstract class AbstractIntentionTest : KotlinCodeInsightTestCase() {
import java.util.ArrayList; protected open fun intentionFileName(): String {
import java.util.List; return ".intention"
import java.util.Map;
public abstract class AbstractIntentionTest extends KotlinCodeInsightTestCase {
@NotNull
protected String intentionFileName() {
return ".intention";
} }
@NotNull protected open fun afterFileNameSuffix(): String {
protected String afterFileNameSuffix() { return ".after"
return ".after";
} }
@NotNull protected open fun isApplicableDirectiveName(): String = "IS_APPLICABLE"
protected String isApplicableDirectiveName() {
return "IS_APPLICABLE"; protected open fun intentionTextDirectiveName(): String {
return "INTENTION_TEXT"
} }
@NotNull @Throws(Exception::class)
protected String intentionTextDirectiveName() { private fun createIntention(testDataFile: File): IntentionAction {
return "INTENTION_TEXT"; val candidateFiles = Lists.newArrayList<File>()
}
private IntentionAction createIntention(File testDataFile) throws Exception { var current: File? = testDataFile.parentFile
List<File> candidateFiles = Lists.newArrayList();
File current = testDataFile.getParentFile();
while (current != null) { while (current != null) {
File candidate = new File(current, intentionFileName()); val candidate = File(current, intentionFileName())
if (candidate.exists()) { if (candidate.exists()) {
candidateFiles.add(candidate); candidateFiles.add(candidate)
} }
current = current.getParentFile(); current = current.parentFile
} }
if (candidateFiles.isEmpty()) { if (candidateFiles.isEmpty()) {
throw new AssertionError(".intention file is not found for " + testDataFile + throw AssertionError(".intention file is not found for " + testDataFile +
"\nAdd it to base directory of test data. It should contain fully-qualified name of intention class."); "\nAdd it to base directory of test data. It should contain fully-qualified name of intention class.")
} }
if (candidateFiles.size() > 1) { if (candidateFiles.size > 1) {
throw new AssertionError("Several .intention files are available for " + testDataFile + throw AssertionError("Several .intention files are available for " + testDataFile +
"\nPlease remove some of them\n" + candidateFiles); "\nPlease remove some of them\n" + candidateFiles)
} }
String className = FileUtil.loadFile(candidateFiles.get(0)).trim(); val className = FileUtil.loadFile(candidateFiles[0]).trim { it <= ' ' }
return (IntentionAction) Class.forName(className).newInstance(); return Class.forName(className).newInstance() as IntentionAction
} }
private static final String[] EXTENSIONS = { ".kt", ".java", ".groovy" }; @Throws(Exception::class)
protected fun doTest(path: String) {
protected void doTest(@NotNull String path) throws Exception { val mainFile = File(path)
File mainFile = new File(path); val mainFileName = FileUtil.getNameWithoutExtension(mainFile)
String mainFileName = FileUtil.getNameWithoutExtension(mainFile); val intentionAction = createIntention(mainFile)
IntentionAction intentionAction = createIntention(mainFile); val sourceFilePaths = ArrayList<String>()
List<String> sourceFilePaths = new ArrayList<String>(); val parentDir = mainFile.parentFile
File parentDir = mainFile.getParentFile(); var i = 1
extraFileLoop: extraFileLoop@ while (true) {
//noinspection ForLoopThatDoesntUseLoopVariable for (extension in EXTENSIONS) {
for (int i = 1; true; i++) { val extraFile = File(parentDir, mainFileName + "." + i + extension)
for (String extension : EXTENSIONS) {
File extraFile = new File(parentDir, mainFileName + "." + i + extension);
if (extraFile.exists()) { if (extraFile.exists()) {
sourceFilePaths.add(extraFile.getPath()); sourceFilePaths.add(extraFile.path)
continue extraFileLoop; i++
continue@extraFileLoop
} }
} }
break; break
} }
sourceFilePaths.add(path); sourceFilePaths.add(path)
Map<String, PsiFile> pathToFiles = ContainerUtil.newMapFromKeys( val pathToFiles = ContainerUtil.newMapFromKeys(
sourceFilePaths.iterator(), sourceFilePaths.iterator(),
new Convertor<String, PsiFile>() { Convertor<String, PsiFile> { path ->
@Override try {
public PsiFile convert(String path) { configureByFile(path)
try {
configureByFile(path);
}
catch (Exception e) {
throw new RuntimeException(e);
}
return myFile;
} }
catch (e: Exception) {
throw RuntimeException(e)
}
myFile
} }
); )
String fileText = FileUtil.loadFile(mainFile, true); val fileText = FileUtil.loadFile(mainFile, true)
assertTrue("\"<caret>\" is missing in file \"" + mainFile + "\"", fileText.contains("<caret>")); TestCase.assertTrue("\"<caret>\" is missing in file \"$mainFile\"", fileText.contains("<caret>"))
String minJavaVersion = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// MIN_JAVA_VERSION: "); val minJavaVersion = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// MIN_JAVA_VERSION: ")
if (minJavaVersion != null && !SystemInfo.isJavaVersionAtLeast(minJavaVersion)) return; if (minJavaVersion != null && !SystemInfo.isJavaVersionAtLeast(minJavaVersion)) return
boolean isWithRuntime = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// WITH_RUNTIME") != null; val isWithRuntime = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// WITH_RUNTIME") != null
try { try {
if (isWithRuntime) { if (isWithRuntime) {
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(getModule(), PluginTestCaseBase.mockJdk()); ConfigLibraryUtil.configureKotlinRuntimeAndSdk(module, PluginTestCaseBase.mockJdk())
} }
ConfigLibraryUtil.configureLibrariesByDirective(getModule(), PlatformTestUtil.getCommunityPath(), fileText); ConfigLibraryUtil.configureLibrariesByDirective(module, PlatformTestUtil.getCommunityPath(), fileText)
if (getFile() instanceof KtFile && !InTextDirectivesUtils.isDirectiveDefined(fileText, "// SKIP_ERRORS_BEFORE")) { if (file is KtFile && !InTextDirectivesUtils.isDirectiveDefined(fileText, "// SKIP_ERRORS_BEFORE")) {
DirectiveBasedActionUtils.INSTANCE.checkForUnexpectedErrors((KtFile) getFile()); DirectiveBasedActionUtils.checkForUnexpectedErrors(file as KtFile)
} }
doTestFor(path, pathToFiles, intentionAction, fileText); doTestFor(path, pathToFiles, intentionAction, fileText)
if (getFile() instanceof KtFile && !InTextDirectivesUtils.isDirectiveDefined(fileText, "// SKIP_ERRORS_AFTER")) { if (file is KtFile && !InTextDirectivesUtils.isDirectiveDefined(fileText, "// SKIP_ERRORS_AFTER")) {
DirectiveBasedActionUtils.INSTANCE.checkForUnexpectedErrors((KtFile) getFile()); DirectiveBasedActionUtils.checkForUnexpectedErrors(file as KtFile)
} }
} }
finally { finally {
ConfigLibraryUtil.unconfigureLibrariesByDirective(myModule, fileText); ConfigLibraryUtil.unconfigureLibrariesByDirective(myModule, fileText)
if (isWithRuntime) { if (isWithRuntime) {
ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(getModule(), getTestProjectJdk()); ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(module, testProjectJdk)
} }
} }
} }
private void doTestFor(String mainFilePath, Map<String, PsiFile> pathToFiles, final IntentionAction intentionAction, String fileText) throws Exception { @Throws(Exception::class)
String isApplicableString = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// " + isApplicableDirectiveName() + ": "); private fun doTestFor(mainFilePath: String, pathToFiles: Map<String, PsiFile>, intentionAction: IntentionAction, fileText: String) {
boolean isApplicableExpected = isApplicableString == null || isApplicableString.equals("true"); val isApplicableString = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// ${isApplicableDirectiveName()}: ")
val isApplicableExpected = isApplicableString == null || isApplicableString == "true"
boolean isApplicableOnPooled = ApplicationManager.getApplication().executeOnPooledThread(new java.util.concurrent.Callable<Boolean>() { val isApplicableOnPooled = ApplicationManager.getApplication().executeOnPooledThread(java.util.concurrent.Callable { ApplicationManager.getApplication().runReadAction(Computable { intentionAction.isAvailable(project, editor, file) }) }).get()
@Override
public Boolean call() throws Exception {
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
@Override
public Boolean compute() {
return intentionAction.isAvailable(getProject(), getEditor(), getFile());
}
});
}
}).get();
boolean isApplicableOnEdt = intentionAction.isAvailable(getProject(), getEditor(), getFile()); val isApplicableOnEdt = intentionAction.isAvailable(project, editor, file)
Assert.assertEquals("There should not be any difference what thread isApplicable is called from", isApplicableOnPooled, isApplicableOnEdt); Assert.assertEquals("There should not be any difference what thread isApplicable is called from", isApplicableOnPooled, isApplicableOnEdt)
Assert.assertTrue( Assert.assertTrue(
"isAvailable() for " + intentionAction.getClass() + " should return " + isApplicableExpected, "isAvailable() for " + intentionAction.javaClass + " should return " + isApplicableExpected,
isApplicableExpected == isApplicableOnEdt); isApplicableExpected == isApplicableOnEdt)
String intentionTextString = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// " + intentionTextDirectiveName() + ": "); val intentionTextString = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// " + intentionTextDirectiveName() + ": ")
if (intentionTextString != null) { if (intentionTextString != null) {
assertEquals("Intention text mismatch.", intentionTextString, intentionAction.getText()); TestCase.assertEquals("Intention text mismatch.", intentionTextString, intentionAction.text)
} }
String shouldFailString = StringUtil.join(InTextDirectivesUtils.findListWithPrefixes(fileText, "// SHOULD_FAIL_WITH: "), ", "); val shouldFailString = StringUtil.join(InTextDirectivesUtils.findListWithPrefixes(fileText, "// SHOULD_FAIL_WITH: "), ", ")
try { try {
if (isApplicableExpected) { if (isApplicableExpected) {
ApplicationUtilsKt.executeWriteCommand( project.executeWriteCommand(
getProject(), intentionAction.text, null
intentionAction.getText(), ) {
null, intentionAction.invoke(project, editor, file)
new Function0<Object>() { null
@Override }
public Object invoke() {
intentionAction.invoke(getProject(), getEditor(), getFile());
return null;
}
}
);
// Don't bother checking if it should have failed. // Don't bother checking if it should have failed.
if (shouldFailString.isEmpty()) { if (shouldFailString.isEmpty()) {
for (Map.Entry<String, PsiFile> entry: pathToFiles.entrySet()) { for ((filePath, value) in pathToFiles) {
String filePath = entry.getKey(); val canonicalPathToExpectedFile = PathUtil.getCanonicalPath(filePath + afterFileNameSuffix())
String canonicalPathToExpectedFile = PathUtil.getCanonicalPath(filePath + afterFileNameSuffix()); if (filePath == mainFilePath) {
if (filePath.equals(mainFilePath)) {
try { try {
checkResultByFile(canonicalPathToExpectedFile); checkResultByFile(canonicalPathToExpectedFile)
} }
catch (ComparisonFailure e) { catch (e: ComparisonFailure) {
KotlinTestUtils KotlinTestUtils
.assertEqualsToFile(new File(canonicalPathToExpectedFile), getEditor().getDocument().getText()); .assertEqualsToFile(File(canonicalPathToExpectedFile), editor.document.text)
} }
} }
else { else {
KotlinTestUtils.assertEqualsToFile(new File(canonicalPathToExpectedFile), entry.getValue().getText()); KotlinTestUtils.assertEqualsToFile(File(canonicalPathToExpectedFile), value.text)
} }
} }
} }
} }
assertEquals("Expected test to fail.", "", shouldFailString); TestCase.assertEquals("Expected test to fail.", "", shouldFailString)
} }
catch (BaseRefactoringProcessor.ConflictsInTestsException e) { catch (e: BaseRefactoringProcessor.ConflictsInTestsException) {
assertEquals("Failure message mismatch.", shouldFailString, StringUtil.join(e.getMessages(), ", ")); TestCase.assertEquals("Failure message mismatch.", shouldFailString, StringUtil.join(e.messages, ", "))
} }
catch (CommonRefactoringUtil.RefactoringErrorHintException e) { catch (e: CommonRefactoringUtil.RefactoringErrorHintException) {
assertEquals("Failure message mismatch.", shouldFailString, e.getMessage().replace('\n', ' ')); TestCase.assertEquals("Failure message mismatch.", shouldFailString, e.message?.replace('\n', ' '))
} }
} }
@Override @Throws(Exception::class)
protected void setUp() throws Exception { override fun setUp() {
super.setUp(); super.setUp()
((StartupManagerImpl) StartupManager.getInstance(getProject())).runPostStartupActivities(); (StartupManager.getInstance(project) as StartupManagerImpl).runPostStartupActivities()
} }
@NotNull override fun getTestDataPath(): String {
@Override return ""
protected String getTestDataPath() { }
return "";
companion object {
private val EXTENSIONS = arrayOf(".kt", ".java", ".groovy")
} }
} }