| package com.jetbrains.env.python.dotNet; |
| |
| import com.google.common.collect.Sets; |
| import com.intellij.codeInsight.intention.IntentionAction; |
| import com.intellij.codeInspection.LocalQuickFix; |
| import com.intellij.codeInspection.ex.QuickFixWrapper; |
| import com.intellij.openapi.application.PathManager; |
| import com.intellij.openapi.progress.Task; |
| import com.intellij.openapi.progress.util.AbstractProgressIndicatorBase; |
| import com.intellij.openapi.projectRoots.Sdk; |
| import com.intellij.openapi.util.io.FileUtil; |
| import com.intellij.psi.PsiDocumentManager; |
| import com.intellij.util.ui.UIUtil; |
| import com.jetbrains.env.PyExecutionFixtureTestTask; |
| import com.jetbrains.python.PyBundle; |
| import com.jetbrains.python.PyNames; |
| import com.jetbrains.python.inspections.quickfix.GenerateBinaryStubsFix; |
| import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesInspection; |
| import com.jetbrains.python.psi.PyFile; |
| import com.jetbrains.python.sdk.InvalidSdkException; |
| import com.jetbrains.python.sdk.PythonSdkType; |
| import com.jetbrains.python.sdkTools.SdkCreationType; |
| import org.hamcrest.Matchers; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import org.junit.Assert; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.Collections; |
| import java.util.Set; |
| |
| /** |
| * Task for test that checks skeleton generation |
| * |
| * @author Ilya.Kazakevich |
| */ |
| class SkeletonTestTask extends PyExecutionFixtureTestTask { |
| |
| /** |
| * Tags for this task to run |
| */ |
| private static final Set<String> IRON_TAGS = Sets.newHashSet(PyIronPythonTest.IRON_TAG); |
| /** |
| * Number of seconds we wait for skeleton generation external process (should be enough) |
| */ |
| private static final int SECONDS_TO_WAIT_FOR_SKELETON_GENERATION = 20; |
| |
| @Nullable |
| private final String myExpectedSkeletonFile; |
| @NotNull |
| private final String myModuleNameToBeGenerated; |
| @NotNull |
| private final String mySourceFileToRunGenerationOn; |
| @NotNull |
| private final String myUseQuickFixWithThisModuleOnly; |
| private PyFile myGeneratedSkeleton; |
| |
| /** |
| * @param expectedSkeletonFile if you want test to compare generated result with some file, provide its name. |
| * Pass null if you do not want to compare result with anything (you may do it yourself with {@link #getGeneratedSkeleton()}) |
| * @param moduleNameToBeGenerated name of module you think we should generate in dotted notation (like "System.Web" or "com.myModule"). |
| * System will wait for skeleton file for this module to be generated |
| * @param sourceFileToRunGenerationOn Source file where we should run "generate stubs" on. Be sure to place "caret" on appropriate place! |
| * @param useQuickFixWithThisModuleOnly If there are several quick fixes in code, you may run fix only on this module. |
| * Pass null if you are sure there would be only one quickfix |
| */ |
| SkeletonTestTask(@Nullable final String expectedSkeletonFile, |
| @NotNull final String moduleNameToBeGenerated, |
| @NotNull final String sourceFileToRunGenerationOn, |
| @Nullable final String useQuickFixWithThisModuleOnly) { |
| myExpectedSkeletonFile = expectedSkeletonFile; |
| myModuleNameToBeGenerated = moduleNameToBeGenerated.replace('.', '/'); |
| mySourceFileToRunGenerationOn = sourceFileToRunGenerationOn; |
| myUseQuickFixWithThisModuleOnly = useQuickFixWithThisModuleOnly != null ? useQuickFixWithThisModuleOnly : ""; |
| } |
| |
| |
| @Override |
| public void runTestOn(@NotNull final String sdkHome) throws IOException, InvalidSdkException { |
| final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.SDK_PACKAGES_ONLY); |
| final File skeletonsPath = new File(PythonSdkType.getSkeletonsPath(PathManager.getSystemPath(), sdk.getHomePath())); |
| File skeletonFileOrDirectory = new File(skeletonsPath, myModuleNameToBeGenerated); // File with module skeleton |
| |
| // Module may be stored in "moduleName.py" or "moduleName/__init__.py" |
| if (skeletonFileOrDirectory.isDirectory()) { |
| skeletonFileOrDirectory = new File(skeletonFileOrDirectory, PyNames.INIT_DOT_PY); |
| } |
| else { |
| skeletonFileOrDirectory = new File(skeletonFileOrDirectory.getAbsolutePath() + PyNames.DOT_PY); |
| } |
| |
| final File skeletonFile = skeletonFileOrDirectory; |
| |
| if (skeletonFile.exists()) { // To make sure we do not reuse it |
| assert skeletonFile.delete() : "Failed to delete file " + skeletonFile; |
| } |
| |
| myFixture.copyFileToProject("dotNet/" + mySourceFileToRunGenerationOn, mySourceFileToRunGenerationOn); // File that uses CLR library |
| myFixture.copyFileToProject("dotNet/PythonLibs.dll", "PythonLibs.dll"); // Library itself |
| myFixture.copyFileToProject("dotNet/SingleNameSpace.dll", "SingleNameSpace.dll"); // Another library |
| myFixture.configureByFile(mySourceFileToRunGenerationOn); |
| myFixture.enableInspections(PyUnresolvedReferencesInspection.class); // This inspection should suggest us to generate stubs |
| |
| |
| UIUtil.invokeAndWaitIfNeeded(new Runnable() { |
| @Override |
| public void run() { |
| PsiDocumentManager.getInstance(myFixture.getProject()).commitAllDocuments(); |
| final String intentionName = PyBundle.message("sdk.gen.stubs.for.binary.modules", myUseQuickFixWithThisModuleOnly); |
| final IntentionAction intention = myFixture.findSingleIntention(intentionName); |
| Assert.assertNotNull("No intention found to generate skeletons!", intention); |
| Assert.assertThat("Intention should be quick fix to run", intention, Matchers.instanceOf(QuickFixWrapper.class)); |
| final LocalQuickFix quickFix = ((QuickFixWrapper)intention).getFix(); |
| Assert.assertThat("Quick fix should be 'generate binary skeletons' fix to run", quickFix, |
| Matchers.instanceOf(GenerateBinaryStubsFix.class)); |
| final Task fixTask = ((GenerateBinaryStubsFix)quickFix).getFixTask(myFixture.getFile()); |
| fixTask.run(new AbstractProgressIndicatorBase()); |
| } |
| }); |
| |
| FileUtil.copy(skeletonFile, new File(myFixture.getTempDirPath(), skeletonFile.getName())); |
| if (myExpectedSkeletonFile != null) { |
| myFixture.checkResultByFile(skeletonFile.getName(), myExpectedSkeletonFile, false); |
| } |
| myGeneratedSkeleton = (PyFile)myFixture.configureByFile(skeletonFile.getName()); |
| } |
| |
| |
| @Override |
| public Set<String> getTags() { |
| return Collections.unmodifiableSet(IRON_TAGS); |
| } |
| |
| /** |
| * @return File for generated skeleton. Call it after {@link #runTestOn(String)} only! |
| */ |
| @NotNull |
| PyFile getGeneratedSkeleton() { |
| return myGeneratedSkeleton; |
| } |
| } |