1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
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;
}
}
|