moved all configurations in Python Integrated Tools to module base

fixed PY-9018 Cannot create test run configuration from editor
This commit is contained in:
Ekaterina Tuzova
2013-06-06 18:32:44 +04:00
parent 367fef5dad
commit c97f24ee5f
32 changed files with 296 additions and 226 deletions
@@ -1,6 +1,8 @@
package com.jetbrains.rest;
import com.intellij.lang.Language;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.LanguageSubstitutor;
@@ -13,7 +15,9 @@ import org.jetbrains.annotations.NotNull;
public class RestLanguageSubstitutor extends LanguageSubstitutor {
@Override
public Language getLanguage(@NotNull final VirtualFile vFile, @NotNull final Project project) {
boolean txtIsRst = ReSTService.getInstance(project).txtIsRst();
final Module module = ModuleUtilCore.findModuleForFile(vFile, project);
if (module == null) return null;
boolean txtIsRst = ReSTService.getInstance(module).txtIsRst();
if (txtIsRst)
return RestLanguage.INSTANCE;
return null;
@@ -3,6 +3,8 @@ package com.jetbrains.rest.inspections;
import com.google.common.collect.ImmutableSet;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.ui.ListEditForm;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
@@ -62,7 +64,9 @@ public class RestRoleInspection extends RestInspection {
super(holder);
myIgnoredRoles = ImmutableSet.copyOf(ignoredRoles);
Project project = holder.getProject();
String dir = ReSTService.getInstance(project).getWorkdir();
final Module module = ModuleUtilCore.findModuleForPsiElement(holder.getFile());
if (module == null) return;
String dir = ReSTService.getInstance(module).getWorkdir();
if (!dir.isEmpty())
fillSphinxRoles(dir, project);
}
@@ -101,7 +105,8 @@ public class RestRoleInspection extends RestInspection {
RestFile file = (RestFile)node.getContainingFile();
if (PsiTreeUtil.getParentOfType(node, RestDirectiveBlock.class) != null) return;
if (node.getNextSibling() == null || node.getNextSibling().getNode().getElementType() != RestTokenTypes.INTERPRETED) return;
final PsiElement sibling = node.getNextSibling();
if (sibling == null || sibling.getNode().getElementType() != RestTokenTypes.INTERPRETED) return;
if (RestUtil.PREDEFINED_ROLES.contains(node.getText()) || myIgnoredRoles.contains(node.getRoleName()))
return;
@@ -43,7 +43,7 @@ import static com.jetbrains.python.sdk.PythonEnvUtil.setPythonUnbuffered;
public class SphinxBaseCommand {
protected boolean setWorkDir(Module module) {
ReSTService service = ReSTService.getInstance(module.getProject());
final ReSTService service = ReSTService.getInstance(module);
String workDir = service.getWorkdir();
if (workDir.isEmpty()) {
AskForWorkDir dialog = new AskForWorkDir(module.getProject());
@@ -62,7 +62,7 @@ public class SphinxBaseCommand {
private AskForWorkDir(Project project) {
super(project);
setTitle("Set sphinx working directory: ");
setTitle("Set Sphinx Working Directory: ");
init();
VirtualFile baseDir = project.getBaseDir();
String path = baseDir != null? baseDir.getPath() : "";
@@ -84,7 +84,7 @@ public class SphinxBaseCommand {
}
}
protected final String myCommand = "sphinx-quickstart"+ (SystemInfo.isWindows ? ".exe" : "");
protected static final String ourCommand = "sphinx-quickstart"+ (SystemInfo.isWindows ? ".exe" : "");
public void execute(@NotNull final Module module) {
final Project project = module.getProject();
@@ -105,7 +105,7 @@ public class SphinxBaseCommand {
.run();
}
catch (ExecutionException e) {
Messages.showErrorDialog(e.getMessage(), "Restructuredtext error");
Messages.showErrorDialog(e.getMessage(), "ReStructuredText Error");
}
}
@@ -113,7 +113,7 @@ public class SphinxBaseCommand {
protected Runnable getAfterTask(final Module module) {
return new Runnable() {
public void run() {
ReSTService service = ReSTService.getInstance(module.getProject());
final ReSTService service = ReSTService.getInstance(module);
LocalFileSystem.getInstance().refreshAndFindFileByPath(service.getWorkdir());
}
};
@@ -134,7 +134,7 @@ public class SphinxBaseCommand {
throw new ExecutionException("No sdk specified");
}
ReSTService service = ReSTService.getInstance(module.getProject());
ReSTService service = ReSTService.getInstance(module);
cmd.setWorkDirectory(service.getWorkdir().isEmpty()? module.getProject().getBaseDir().getPath(): service.getWorkdir());
PythonCommandLineState.createStandardGroupsIn(cmd);
ParamsGroup script_params = cmd.getParametersList().getParamsGroup(PythonCommandLineState.GROUP_SCRIPT);
@@ -170,7 +170,7 @@ public class SphinxBaseCommand {
}
@Nullable
private String getCommandPath(Sdk sdk) {
return RestUtil.findRunner(sdk.getHomePath(), myCommand);
private static String getCommandPath(Sdk sdk) {
return RestUtil.findRunner(sdk.getHomePath(), ourCommand);
}
}
+3 -3
View File
@@ -95,7 +95,7 @@
<targetElementEvaluator language="Python" implementationClass="com.jetbrains.python.codeInsight.PyTargetElementEvaluator"/>
<projectService serviceInterface="com.jetbrains.python.ReSTService"
<moduleService serviceInterface="com.jetbrains.python.ReSTService"
serviceImplementation="com.jetbrains.python.ReSTService"/>
<!-- Run/Debug -->
@@ -436,7 +436,7 @@
<projectConfigurable instance="com.jetbrains.python.templateLanguages.TemplateLanguageModulesConfigurable"
id="com.jetbrains.python.templateLanguages.TemplateLanguageModulesConfigurable"
displayName="Python Template Languages"/>
<projectService serviceInterface="com.jetbrains.python.documentation.PyDocumentationSettings"
<moduleService serviceInterface="com.jetbrains.python.documentation.PyDocumentationSettings"
serviceImplementation="com.jetbrains.python.documentation.PyDocumentationSettings"/>
<psi.referenceContributor implementation="com.jetbrains.python.documentation.DocStringReferenceContributor"/>
<completion.contributor language="Python" implementationClass="com.jetbrains.python.documentation.DocStringTagCompletionContributor"/>
@@ -721,7 +721,7 @@
implementationClass="com.jetbrains.python.buildout.config.inspection.BuildoutUnresolvedPartInspection"/>
<colorSettingsPage implementation="com.jetbrains.python.buildout.config.BuildoutCfgColorsPage"/>
<projectService serviceInterface="com.jetbrains.python.testing.TestRunnerService"
<moduleService serviceInterface="com.jetbrains.python.testing.TestRunnerService"
serviceImplementation="com.jetbrains.python.testing.TestRunnerService"/>
<problemFileHighlightFilter implementation="com.jetbrains.python.buildout.config.BuildoutCfgProblemFileHighlightFilter"/>
@@ -1,17 +1,18 @@
package com.jetbrains.python;
import com.intellij.openapi.components.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleServiceManager;
import com.intellij.util.xmlb.XmlSerializerUtil;
import org.jetbrains.annotations.NotNull;
/**
* User: catherine
*/
@State(name = "ReSTService",
storages = {
@Storage( file = StoragePathMacros.PROJECT_FILE),
@Storage( file = StoragePathMacros.PROJECT_CONFIG_DIR + "/rest.xml", scheme = StorageScheme.DIRECTORY_BASED)
}
storages = {@Storage(file = "$MODULE_FILE$")}
)
public class ReSTService implements PersistentStateComponent<ReSTService> {
public String DOC_DIR = "";
@@ -34,8 +35,8 @@ public class ReSTService implements PersistentStateComponent<ReSTService> {
DOC_DIR = workDir;
}
public static ReSTService getInstance(Project project) {
return ServiceManager.getService(project, ReSTService.class);
public static ReSTService getInstance(@NotNull Module module) {
return ModuleServiceManager.getService(module, ReSTService.class);
}
public String getWorkdir() {
@@ -64,12 +64,12 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable, No
public PyIntegratedToolsConfigurable(@NotNull Module module) {
myModule = module;
myProject = myModule.getProject();
myDocumentationSettings = PyDocumentationSettings.getInstance(myProject);
myDocumentationSettings = PyDocumentationSettings.getInstance(myModule);
myDocstringFormatComboBox.setModel(new CollectionComboBoxModel(DocStringFormat.ALL, myDocumentationSettings.myDocStringFormat));
final FileChooserDescriptor fileChooserDescriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
myWorkDir.addBrowseFolderListener("Please choose working directory:", null, myProject, fileChooserDescriptor);
ReSTService service = ReSTService.getInstance(myProject);
ReSTService service = ReSTService.getInstance(myModule);
myWorkDir.setText(service.getWorkdir());
txtIsRst.setSelected(service.txtIsRst());
analyzeDoctest.setSelected(myDocumentationSettings.analyzeDoctest);
@@ -84,7 +84,6 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable, No
@NotNull
private String getRequirementsPath() {
final String path = PyPackageRequirementsSettings.getInstance(myModule).getRequirementsPath();
final String text;
if (path.equals(PyPackageRequirementsSettings.DEFAULT_REQUIREMENTS_PATH) && PyPackageUtil.findRequirementsTxt(myModule) == null) {
return "";
}
@@ -166,9 +165,9 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable, No
@Override
public JComponent createComponent() {
List<String> configurations = TestRunnerService.getInstance(myProject).getConfigurations();
myModel = new PythonTestConfigurationsModel(configurations, TestRunnerService.getInstance(myProject).getProjectConfiguration(),
myProject);
List<String> configurations = TestRunnerService.getInstance(myModule).getConfigurations();
myModel = new PythonTestConfigurationsModel(configurations,
TestRunnerService.getInstance(myModule).getProjectConfiguration(), myModule);
updateConfigurations();
initErrorValidation();
@@ -190,10 +189,10 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable, No
if (analyzeDoctest.isSelected() != myDocumentationSettings.analyzeDoctest) {
return true;
}
if (!ReSTService.getInstance(myProject).getWorkdir().equals(myWorkDir.getText())) {
if (!ReSTService.getInstance(myModule).getWorkdir().equals(myWorkDir.getText())) {
return true;
}
if (!ReSTService.getInstance(myProject).txtIsRst() == txtIsRst.isSelected()) {
if (!ReSTService.getInstance(myModule).txtIsRst() == txtIsRst.isSelected()) {
return true;
}
if (!getRequirementsPath().equals(myRequirementsPathField.getText())) {
@@ -222,8 +221,8 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable, No
}
myModel.apply();
myDocumentationSettings.myDocStringFormat = (String) myDocstringFormatComboBox.getSelectedItem();
ReSTService.getInstance(myProject).setWorkdir(myWorkDir.getText());
ReSTService.getInstance(myProject).setTxtIsRst(txtIsRst.isSelected());
ReSTService.getInstance(myModule).setWorkdir(myWorkDir.getText());
ReSTService.getInstance(myModule).setTxtIsRst(txtIsRst.isSelected());
myDocumentationSettings.analyzeDoctest = analyzeDoctest.isSelected();
PyPackageRequirementsSettings.getInstance(myModule).setRequirementsPath(myRequirementsPathField.getText());
DaemonCodeAnalyzer.getInstance(myProject).restart();
@@ -235,8 +234,8 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable, No
myTestRunnerComboBox.repaint();
myModel.reset();
myDocstringFormatComboBox.setSelectedItem(myDocumentationSettings.myDocStringFormat);
myWorkDir.setText(ReSTService.getInstance(myProject).getWorkdir());
txtIsRst.setSelected(ReSTService.getInstance(myProject).txtIsRst());
myWorkDir.setText(ReSTService.getInstance(myModule).getWorkdir());
txtIsRst.setSelected(ReSTService.getInstance(myModule).txtIsRst());
analyzeDoctest.setSelected(myDocumentationSettings.analyzeDoctest);
myRequirementsPathField.setText(getRequirementsPath());
}
@@ -2,6 +2,8 @@ package com.jetbrains.python.documentation;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.psi.PsiFile;
import com.intellij.util.ProcessingContext;
@@ -26,7 +28,9 @@ public class DocStringTagCompletionContributor extends CompletionContributor {
protected void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull CompletionResultSet result) {
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(parameters.getPosition().getProject());
final Module module = ModuleUtilCore.findModuleForPsiElement(parameters.getPosition());
if (module == null) return;
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(module);
final PsiFile file = parameters.getOriginalFile();
if (settings.isEpydocFormat(file) || settings.isReSTFormat(file)) {
int offset = parameters.getOffset();
@@ -1,5 +1,7 @@
package com.jetbrains.python.documentation;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
@@ -16,7 +18,9 @@ public class EpydocUtil {
}
public static boolean isVariableDocString(PyStringLiteralExpression expr) {
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(expr.getProject());
final Module module = ModuleUtilCore.findModuleForPsiElement(expr);
if (module == null) return false;
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(module);
if (settings.isEpydocFormat(expr.getContainingFile()) || settings.isReSTFormat(expr.getContainingFile())) {
final PsiElement parent = expr.getParent();
if (!(parent instanceof PyExpressionStatement)) {
@@ -10,11 +10,14 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.LineTokenizer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -119,10 +122,10 @@ public class PyDocstringGenerator {
Template template = ((TemplateBuilderImpl)builder).buildInlineTemplate();
final VirtualFile virtualFile = myFile.getVirtualFile();
if (virtualFile == null) return;
OpenFileDescriptor descriptor = new OpenFileDescriptor(
myProject,
myFile.getVirtualFile(),
myDocStringOwner.getTextOffset() + myDocStringOwner.getTextLength()
myProject, virtualFile, myDocStringOwner.getTextOffset() + myDocStringOwner.getTextLength()
);
Editor targetEditor = FileEditorManager.getInstance(myProject).openTextEditor(descriptor, true);
if (targetEditor != null) {
@@ -224,7 +227,7 @@ public class PyDocstringGenerator {
if (myDocStringOwner instanceof PyFunction) {
final PyStatementList statementList = ((PyFunction)myDocStringOwner).getStatementList();
final Document document = PsiDocumentManager.getInstance(myProject).getDocument(getFile());
if (document != null && statementList != null && statementList.getStatements().length != 0
if (document != null && statementList != null && myFunction != null && statementList.getStatements().length != 0
&& document.getLineNumber(statementList.getTextOffset()) != document.getLineNumber(myFunction.getTextOffset())) {
whitespace = PsiTreeUtil.getPrevSiblingOfType(statementList, PsiWhiteSpace.class);
}
@@ -421,8 +424,11 @@ public class PyDocstringGenerator {
}
private String getPrefix() {
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myProject);
String prefix = ":";
final Module module = ModuleUtilCore.findModuleForPsiElement(myDocStringOwner);
if (module == null) return prefix;
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(module);
if (documentationSettings.isEpydocFormat(getFile())) {
prefix = "@";
}
@@ -1,15 +1,13 @@
package com.jetbrains.python.documentation;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.LineTokenizer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
@@ -40,7 +38,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.jetbrains.python.documentation.DocumentationBuilderKit.*;
import static com.jetbrains.python.documentation.DocumentationBuilderKit.combUp;
class PyDocumentationBuilder {
private final PsiElement myElement;
@@ -359,14 +356,15 @@ class PyDocumentationBuilder {
private static void addFormattedDocString(PsiElement element, @NotNull String docstring,
ChainIterable<String> formattedOutput, ChainIterable<String> unformattedOutput) {
Project project = element.getProject();
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(project);
final Project project = element.getProject();
final Module module = ModuleUtilCore.findModuleForPsiElement(element);
if (module == null) return;
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(module);
List<String> result = new ArrayList<String>();
String[] lines = removeCommonIndentation(docstring);
String preparedDocstring = StringUtil.join(lines, "\n");
if (documentationSettings.isEpydocFormat(element.getContainingFile()) ||
StructuredDocString.isEpydocDocstring(preparedDocstring)) {
Module module = ModuleUtil.findModuleForPsiElement(element);
final EpydocString epydocString = new EpydocString(preparedDocstring);
String formatted = epydocString.getDescription();
@@ -377,10 +375,8 @@ class PyDocumentationBuilder {
}
else if (documentationSettings.isReSTFormat(element.getContainingFile()) ||
StructuredDocString.isSphinxDocstring(preparedDocstring)) {
Module module = ModuleUtilCore.findModuleForPsiElement(element);
String formatted = null;
final ProjectRootManager projectRootManager = ProjectRootManager.getInstance(element.getProject());
Sdk pythonSdk = module != null ? PythonSdkType.findPython2Sdk(module) : projectRootManager.getProjectSdk();
Sdk pythonSdk = PythonSdkType.findPython2Sdk(module);
if (pythonSdk != null) {
formatted = ReSTRunner.formatDocstring(pythonSdk, docstring);
}
@@ -624,7 +620,7 @@ class PyDocumentationBuilder {
}
public boolean visitRoot(VirtualFile root, Module module, Sdk sdk, boolean isModuleSource) {
String vpath = VfsUtil.urlToPath(root.getUrl());
String vpath = VfsUtilCore.urlToPath(root.getUrl());
if (myPath.startsWith(vpath)) {
myResult = vpath;
return false;
@@ -1,7 +1,8 @@
package com.jetbrains.python.documentation;
import com.intellij.openapi.components.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleServiceManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile;
import com.intellij.util.xmlb.XmlSerializerUtil;
@@ -10,6 +11,7 @@ import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyTargetExpression;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -17,10 +19,7 @@ import java.util.List;
* @author yole
*/
@State(name = "PyDocumentationSettings",
storages = {
@Storage( file = StoragePathMacros.PROJECT_FILE),
@Storage( file = StoragePathMacros.PROJECT_CONFIG_DIR + "/other.xml", scheme = StorageScheme.DIRECTORY_BASED)
}
storages = {@Storage(file = "$MODULE_FILE$")}
)
public class PyDocumentationSettings implements PersistentStateComponent<PyDocumentationSettings> {
public String myDocStringFormat = "";
@@ -52,8 +51,8 @@ public class PyDocumentationSettings implements PersistentStateComponent<PyDocum
return format.equalsIgnoreCase(myDocStringFormat);
}
public static PyDocumentationSettings getInstance(Project project) {
return ServiceManager.getService(project, PyDocumentationSettings.class);
public static PyDocumentationSettings getInstance(@NotNull Module module) {
return ModuleServiceManager.getService(module, PyDocumentationSettings.class);
}
public void setFormat(String format) {
@@ -9,6 +9,8 @@ import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
@@ -493,8 +495,9 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
// link item to containing class
public static String generateDocumentationContentStub(PyFunction element, String offset, boolean checkReturn) {
Project project = element.getProject();
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(project);
final Module module = ModuleUtilCore.findModuleForPsiElement(element);
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(module);
String result = "";
if (documentationSettings.isEpydocFormat(element.getContainingFile())) {
result += generateContent(element, offset, EPYDOC_PREFIX, checkReturn);
@@ -1,5 +1,7 @@
package com.jetbrains.python.documentation.doctest;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.InjectedLanguagePlaces;
@@ -19,58 +21,62 @@ import java.util.List;
public class PyDocstringLanguageInjector implements LanguageInjector {
@Override
public void getLanguagesToInject(@NotNull final PsiLanguageInjectionHost host, @NotNull final InjectedLanguagePlaces injectionPlacesRegistrar) {
if (host instanceof PyStringLiteralExpression && PyDocumentationSettings.getInstance(host.getProject()).analyzeDoctest) {
final PyDocStringOwner
docStringOwner = PsiTreeUtil.getParentOfType(host, PyDocStringOwner.class);
if (docStringOwner != null && host.equals(docStringOwner.getDocStringExpression())) {
int start = 0;
int end = host.getTextLength() - 1;
final String text = host.getText();
final List<String> strings = StringUtil.split(text, "\n", false);
if (!(host instanceof PyStringLiteralExpression)) {
return;
}
final Module module = ModuleUtilCore.findModuleForPsiElement(host);
if (module == null || !PyDocumentationSettings.getInstance(module).analyzeDoctest) return;
boolean gotExample = false;
final PyDocStringOwner
docStringOwner = PsiTreeUtil.getParentOfType(host, PyDocStringOwner.class);
if (docStringOwner != null && host.equals(docStringOwner.getDocStringExpression())) {
int start = 0;
int end = host.getTextLength() - 1;
final String text = host.getText();
final List<String> strings = StringUtil.split(text, "\n", false);
int currentPosition = 0;
int maxPosition = text.length();
boolean endsWithSlash = false;
for (String string : strings) {
final String trimmedString = string.trim();
if (!trimmedString.startsWith(">>>") && !trimmedString.startsWith("...") && gotExample && start < end) {
gotExample = false;
if (!endsWithSlash)
injectionPlacesRegistrar.addPlace(PyDocstringLanguageDialect.getInstance(), TextRange.create(start, end), null, null);
}
if (endsWithSlash) {
endsWithSlash = false;
injectionPlacesRegistrar.addPlace(PyDocstringLanguageDialect.getInstance(),
TextRange.create(start, getEndOffset(currentPosition, string, maxPosition)), null, null);
}
boolean gotExample = false;
if (trimmedString.startsWith(">>>")) {
if (trimmedString.endsWith("\\"))
endsWithSlash = true;
if (!gotExample)
start = currentPosition;
gotExample = true;
end = getEndOffset(currentPosition, string, maxPosition);
}
else if (trimmedString.startsWith("...") && gotExample) {
if (trimmedString.endsWith("\\"))
endsWithSlash = true;
end = getEndOffset(currentPosition, string, maxPosition);
}
currentPosition += string.length();
int currentPosition = 0;
int maxPosition = text.length();
boolean endsWithSlash = false;
for (String string : strings) {
final String trimmedString = string.trim();
if (!trimmedString.startsWith(">>>") && !trimmedString.startsWith("...") && gotExample && start < end) {
gotExample = false;
if (!endsWithSlash)
injectionPlacesRegistrar.addPlace(PyDocstringLanguageDialect.getInstance(), TextRange.create(start, end), null, null);
}
if (gotExample && start < end)
injectionPlacesRegistrar.addPlace(PyDocstringLanguageDialect.getInstance(), TextRange.create(start, end), null, null);
if (endsWithSlash) {
endsWithSlash = false;
injectionPlacesRegistrar.addPlace(PyDocstringLanguageDialect.getInstance(),
TextRange.create(start, getEndOffset(currentPosition, string, maxPosition)), null, null);
}
if (trimmedString.startsWith(">>>")) {
if (trimmedString.endsWith("\\"))
endsWithSlash = true;
if (!gotExample)
start = currentPosition;
gotExample = true;
end = getEndOffset(currentPosition, string, maxPosition);
}
else if (trimmedString.startsWith("...") && gotExample) {
if (trimmedString.endsWith("\\"))
endsWithSlash = true;
end = getEndOffset(currentPosition, string, maxPosition);
}
currentPosition += string.length();
}
if (gotExample && start < end)
injectionPlacesRegistrar.addPlace(PyDocstringLanguageDialect.getInstance(), TextRange.create(start, end), null, null);
}
}
private int getEndOffset(int start, String s, int maxPosition) {
private static int getEndOffset(int start, String s, int maxPosition) {
int end;
int length = s.length();
if (s.trim().endsWith("\"\"\"") || s.trim().endsWith("'''"))
@@ -3,6 +3,8 @@ package com.jetbrains.python.editor;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.editorActions.TypedHandlerDelegate;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -28,16 +30,20 @@ public class PythonSpaceHandler extends TypedHandlerDelegate {
PsiElement element = file.findElementAt(offset);
if (element == null && offset > 1)
element = file.findElementAt(offset-2);
if (element == null) return Result.CONTINUE;
int expectedStringStart = editor.getCaretModel().getOffset()-4; // """ or ''' plus space char
if (PythonDocCommentUtil.atDocCommentStart(element, expectedStringStart)) {
PythonDocumentationProvider provider = new PythonDocumentationProvider();
PyFunction fun = PsiTreeUtil.getParentOfType(element, PyFunction.class);
final PsiElement parent = element.getParent();
if (fun != null) {
String docStub = provider.generateDocumentationContentStub(fun, false);
docStub += element.getParent().getText().substring(0,3);
if (docStub != null && docStub.length() != 0) {
docStub += parent.getText().substring(0,3);
if (docStub.length() != 0) {
editor.getDocument().insertString(editor.getCaretModel().getOffset(), docStub);
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(project);
Module module = ModuleUtilCore.findModuleForPsiElement(element);
if (module == null) return Result.CONTINUE;
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(module);
if (documentationSettings.myDocStringFormat != DocStringFormat.PLAIN)
editor.getCaretModel().moveCaretRelatively(100, 1, false, false, false);
return Result.STOP;
@@ -46,7 +52,7 @@ public class PythonSpaceHandler extends TypedHandlerDelegate {
PyElement klass = PsiTreeUtil.getParentOfType(element, PyClass.class, PyFile.class);
if (klass != null) {
editor.getDocument().insertString(editor.getCaretModel().getOffset(),
PythonDocCommentUtil.generateDocForClass(klass, element.getParent().getText().substring(0,3)));
PythonDocCommentUtil.generateDocForClass(klass, parent.getText().substring(0, 3)));
return Result.STOP;
}
}
@@ -5,6 +5,8 @@ import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDocumentManager;
@@ -94,7 +96,9 @@ public class DocstringQuickFix implements LocalQuickFix {
}
if (docStringExpression != null) {
PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(project);
final Module module = ModuleUtilCore.findModuleForPsiElement(docStringExpression);
if (module == null) return;
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(module);
if (documentationSettings.isEpydocFormat(docStringExpression.getContainingFile())) {
myPrefix = "@";
}
@@ -1,5 +1,7 @@
package com.jetbrains.python.refactoring.changeSignature;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
@@ -315,10 +317,12 @@ public class PyChangeSignatureUsageProcessor implements ChangeSignatureUsageProc
for (PyParameterInfo info : parameters) {
names.add(info.getName());
}
final Module module = ModuleUtilCore.findModuleForPsiElement(function);
if (module == null) return;
for (PyParameter p : function.getParameterList().getParameters()) {
final String paramName = p.getName();
if (!names.contains(paramName) && paramName != null) {
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(function.getProject());
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(module);
String prefix = documentationSettings.isEpydocFormat(docStringExpression.getContainingFile()) ? "@" : ":";
final String replacement = PythonDocCommentUtil.removeParamFromDocstring(docStringExpression.getText(), prefix,
paramName);
@@ -42,13 +42,13 @@ public class PyTestRunnerUpdater implements StartupActivity {
for (Module m: ModuleManager.getInstance(project).getModules()) {
if (ModuleType.get(m) instanceof PythonModuleTypeBase) {
updateIntegratedTools(project, 10000);
updateIntegratedTools(m, 10000);
break;
}
}
}
private static void updateIntegratedTools(final Project project, final int delay) {
private static void updateIntegratedTools(final Module module, final int delay) {
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
public void run() {
if (delay > 0) {
@@ -59,91 +59,83 @@ public class PyTestRunnerUpdater implements StartupActivity {
}
}
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
if (!TestRunnerService.getInstance(project).getProjectConfiguration().isEmpty())
if (!TestRunnerService.getInstance(module).getProjectConfiguration().isEmpty())
return;
//check setup.py
String testRunner = detectTestRunnerFromSetupPy(project);
String testRunner = detectTestRunnerFromSetupPy(module);
//try to find test_runner import
final Collection<VirtualFile> filenames = FilenameIndex.getAllFilesByExt(project, PythonFileType.INSTANCE.getDefaultExtension(),
GlobalSearchScope.projectScope(project));
final Collection<VirtualFile> filenames = FilenameIndex.getAllFilesByExt(module.getProject(), PythonFileType.INSTANCE.getDefaultExtension(),
GlobalSearchScope.moduleScope(module));
for (VirtualFile file : filenames){
for (VirtualFile file : filenames) {
if (file.getName().startsWith("test")) {
if (testRunner.isEmpty()) testRunner = checkImports(file, project); //find test runner import
if (testRunner.isEmpty()) testRunner = checkImports(file, module); //find test runner import
}
else {
if (PyDocumentationSettings.getInstance(project).getFormat().isEmpty()) {
checkDocstring(file, project); // detect docstring type
if (PyDocumentationSettings.getInstance(module).getFormat().isEmpty()) {
checkDocstring(file, module); // detect docstring type
}
}
if (!testRunner.isEmpty() && !PyDocumentationSettings.getInstance(project).getFormat().isEmpty()) {
if (!testRunner.isEmpty() && !PyDocumentationSettings.getInstance(module).getFormat().isEmpty()) {
break;
}
}
if (testRunner.isEmpty()) {
//check if installed in sdk
for (Module module : ModuleManager.getInstance(project).getModules()) {
final Sdk sdk = PythonSdkType.findPythonSdk(module);
if (sdk != null && sdk.getSdkType() instanceof PythonSdkType && testRunner.isEmpty()) {
String sdkHome = sdk.getHomePath();
if (VFSTestFrameworkListener.isTestFrameworkInstalled(sdk, PyNames.NOSE_TEST))
testRunner = PythonTestConfigurationsModel.PYTHONS_NOSETEST_NAME;
else if (VFSTestFrameworkListener.isTestFrameworkInstalled(sdk, PyNames.PY_TEST))
testRunner = PythonTestConfigurationsModel.PY_TEST_NAME;
else if (VFSTestFrameworkListener.isTestFrameworkInstalled(sdk, PyNames.AT_TEST))
testRunner = PythonTestConfigurationsModel.PYTHONS_ATTEST_NAME;
}
final Sdk sdk = PythonSdkType.findPythonSdk(module);
if (sdk != null && sdk.getSdkType() instanceof PythonSdkType && testRunner.isEmpty()) {
if (VFSTestFrameworkListener.isTestFrameworkInstalled(sdk, PyNames.NOSE_TEST))
testRunner = PythonTestConfigurationsModel.PYTHONS_NOSETEST_NAME;
else if (VFSTestFrameworkListener.isTestFrameworkInstalled(sdk, PyNames.PY_TEST))
testRunner = PythonTestConfigurationsModel.PY_TEST_NAME;
else if (VFSTestFrameworkListener.isTestFrameworkInstalled(sdk, PyNames.AT_TEST))
testRunner = PythonTestConfigurationsModel.PYTHONS_ATTEST_NAME;
}
}
if (testRunner.isEmpty()) testRunner = PythonTestConfigurationsModel.PYTHONS_UNITTEST_NAME;
TestRunnerService.getInstance(project).setProjectConfiguration(testRunner);
if (PyDocumentationSettings.getInstance(project).getFormat().isEmpty())
PyDocumentationSettings.getInstance(project).setFormat(DocStringFormat.PLAIN);
TestRunnerService.getInstance(module).setProjectConfiguration(testRunner);
if (PyDocumentationSettings.getInstance(module).getFormat().isEmpty())
PyDocumentationSettings.getInstance(module).setFormat(DocStringFormat.PLAIN);
}
}, ModalityState.any(), project.getDisposed());
}, ModalityState.any(), module.getDisposed());
}
});
}
private static String detectTestRunnerFromSetupPy(Project project) {
private static String detectTestRunnerFromSetupPy(Module module) {
String testRunner = "";
final Module[] modules = ModuleManager.getInstance(project).getModules();
for (Module module : modules) {
if (!testRunner.isEmpty()) break;
final PyFile setupPy = PyPackageUtil.findSetupPy(module);
if (setupPy == null)
continue;
final PyCallExpression setupCall = PyPackageUtil.findSetupCall(setupPy);
if (setupCall == null)
continue;
for (PyExpression arg : setupCall.getArguments()) {
if (arg instanceof PyKeywordArgument) {
final PyKeywordArgument kwarg = (PyKeywordArgument)arg;
if ("test_loader".equals(kwarg.getKeyword()) || "test_suite".equals(kwarg.getKeyword())) {
final PyExpression value = kwarg.getValueExpression();
if (value instanceof PyStringLiteralExpression) {
final String stringValue = ((PyStringLiteralExpression)value).getStringValue();
if (stringValue.contains(PyNames.NOSE_TEST)) {
testRunner = PythonTestConfigurationsModel.PYTHONS_NOSETEST_NAME;
break;
}
if (stringValue.contains(PyNames.PY_TEST)) {
testRunner = PythonTestConfigurationsModel.PY_TEST_NAME;
break;
}
if (stringValue.contains(PyNames.AT_TEST_IMPORT)) {
testRunner = PythonTestConfigurationsModel.PYTHONS_ATTEST_NAME;
break;
}
if (!testRunner.isEmpty()) return testRunner;
final PyFile setupPy = PyPackageUtil.findSetupPy(module);
if (setupPy == null)
return testRunner;
final PyCallExpression setupCall = PyPackageUtil.findSetupCall(setupPy);
if (setupCall == null)
return testRunner;
for (PyExpression arg : setupCall.getArguments()) {
if (arg instanceof PyKeywordArgument) {
final PyKeywordArgument kwarg = (PyKeywordArgument)arg;
if ("test_loader".equals(kwarg.getKeyword()) || "test_suite".equals(kwarg.getKeyword())) {
final PyExpression value = kwarg.getValueExpression();
if (value instanceof PyStringLiteralExpression) {
final String stringValue = ((PyStringLiteralExpression)value).getStringValue();
if (stringValue.contains(PyNames.NOSE_TEST)) {
testRunner = PythonTestConfigurationsModel.PYTHONS_NOSETEST_NAME;
break;
}
if (stringValue.contains(PyNames.PY_TEST)) {
testRunner = PythonTestConfigurationsModel.PY_TEST_NAME;
break;
}
if (stringValue.contains(PyNames.AT_TEST_IMPORT)) {
testRunner = PythonTestConfigurationsModel.PYTHONS_ATTEST_NAME;
break;
}
}
}
@@ -152,9 +144,9 @@ public class PyTestRunnerUpdater implements StartupActivity {
return testRunner;
}
private static void checkDocstring(VirtualFile file, Project project) {
final PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(project);
final PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
private static void checkDocstring(VirtualFile file, Module module) {
final PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(module);
final PsiFile psiFile = PsiManager.getInstance(module.getProject()).findFile(file);
if (psiFile instanceof PyFile) {
if (documentationSettings.isEpydocFormat(psiFile))
documentationSettings.setFormat(DocStringFormat.EPYTEXT);
@@ -186,8 +178,8 @@ public class PyTestRunnerUpdater implements StartupActivity {
}
}
private static String checkImports(VirtualFile file, Project project) {
final PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
private static String checkImports(VirtualFile file, Module module) {
final PsiFile psiFile = PsiManager.getInstance(module.getProject()).findFile(file);
if (psiFile instanceof PyFile) {
final List<PyImportElement> importTargets = ((PyFile)psiFile).getImportTargets();
for (PyImportElement importElement : importTargets) {
@@ -16,7 +16,7 @@
package com.jetbrains.python.testing;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.module.Module;
import com.intellij.ui.CollectionComboBoxModel;
import com.jetbrains.python.PyBundle;
@@ -33,12 +33,12 @@ public class PythonTestConfigurationsModel extends CollectionComboBoxModel {
public static final String PYTHONS_ATTEST_NAME = PyBundle.message("runcfg.attest.display_name");
private String myTestRunner;
private Project myProject;
private Module myModule;
public PythonTestConfigurationsModel(final List items, final Object selection, Project project) {
public PythonTestConfigurationsModel(final List items, final Object selection, Module module) {
super(items, selection);
myProject = project;
myTestRunner = TestRunnerService.getInstance(myProject).getProjectConfiguration();
myModule = module;
myTestRunner = TestRunnerService.getInstance(myModule).getProjectConfiguration();
}
public void reset() {
setSelectedItem(myTestRunner);
@@ -46,7 +46,7 @@ public class PythonTestConfigurationsModel extends CollectionComboBoxModel {
public void apply() {
myTestRunner = (String)getSelectedItem();
TestRunnerService.getInstance(myProject).setProjectConfiguration(myTestRunner);
TestRunnerService.getInstance(myModule).setProjectConfiguration(myTestRunner);
}
public Object getTestRunner() {
@@ -14,8 +14,8 @@ import org.jetbrains.annotations.NotNull;
*/
public class PythonUnitTestRunnableScriptFilter implements RunnableScriptFilter {
public boolean isRunnableScript(PsiFile script, @NotNull Module module, Location location) {
return script instanceof PyFile && PythonUnitTestUtil.getTestCaseClassesFromFile((PyFile) script).size() > 0
&& !isIfNameMain(location) && TestRunnerService.getInstance(script.getProject()).getProjectConfiguration().
return script instanceof PyFile && PythonUnitTestUtil.getTestCaseClassesFromFile(script).size() > 0
&& !isIfNameMain(location) && TestRunnerService.getInstance(module).getProjectConfiguration().
equals(PythonTestConfigurationsModel.PYTHONS_UNITTEST_NAME);
}
@@ -1,8 +1,12 @@
package com.jetbrains.python.testing;
import com.intellij.openapi.components.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleServiceManager;
import com.intellij.util.xmlb.XmlSerializerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
@@ -11,10 +15,7 @@ import java.util.List;
* User: catherine
*/
@State(name = "TestRunnerService",
storages = {
@Storage( file = StoragePathMacros.PROJECT_FILE),
@Storage( file = StoragePathMacros.PROJECT_CONFIG_DIR + "/testrunner.xml", scheme = StorageScheme.DIRECTORY_BASED)
}
storages = {@Storage(file = "$MODULE_FILE$")}
)
public class TestRunnerService implements PersistentStateComponent<TestRunnerService> {
private List<String> myConfigurations = new ArrayList<String>();
@@ -30,9 +31,7 @@ public class TestRunnerService implements PersistentStateComponent<TestRunnerSer
public List<String> getConfigurations() {
return myConfigurations;
}
public void registerConfiguration(final String newConfiguration) {
myConfigurations.add(newConfiguration);
}
@Override
public TestRunnerService getState() {
return this;
@@ -47,9 +46,10 @@ public class TestRunnerService implements PersistentStateComponent<TestRunnerSer
PROJECT_TEST_RUNNER = projectConfiguration;
}
public static TestRunnerService getInstance(Project project) {
return ServiceManager.getService(project, TestRunnerService.class);
public static TestRunnerService getInstance(@NotNull Module module) {
return ModuleServiceManager.getService(module, TestRunnerService.class);
}
public String getProjectConfiguration() {
return PROJECT_TEST_RUNNER;
}
@@ -2,6 +2,8 @@ package com.jetbrains.python.testing.attest;
import com.google.common.collect.Lists;
import com.intellij.execution.Location;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.psi.*;
@@ -22,9 +24,12 @@ public class PythonAtTestConfigurationProducer extends
protected boolean isAvailable(Location location) {
PsiElement element = location.getPsiElement();
final Sdk sdk = PythonSdkType.findPythonSdk(location.getModule());
return (TestRunnerService.getInstance(element.getProject()).getProjectConfiguration().equals(
PythonTestConfigurationsModel.PYTHONS_ATTEST_NAME) && sdk != null);
Module module = location.getModule();
if (module == null) module = ModuleUtilCore.findModuleForPsiElement(element);
final Sdk sdk = PythonSdkType.findPythonSdk(module);
return module != null && TestRunnerService.getInstance(module).getProjectConfiguration().equals(
PythonTestConfigurationsModel.PYTHONS_ATTEST_NAME) && sdk != null;
}
protected boolean isTestClass(PyClass pyClass) {
@@ -37,7 +42,7 @@ public class PythonAtTestConfigurationProducer extends
return false;
}
private boolean hasTestFunction(PyClass pyClass) {
private static boolean hasTestFunction(PyClass pyClass) {
PyFunction[] methods = pyClass.getMethods();
for (PyFunction function : methods) {
PyDecoratorList decorators = function.getDecoratorList();
@@ -1,6 +1,8 @@
package com.jetbrains.python.testing.nosetest;
import com.intellij.execution.Location;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.psi.PyFunction;
@@ -15,8 +17,10 @@ public class PythonNoseTestConfigurationProducer extends
protected boolean isAvailable(Location location) {
PsiElement element = location.getPsiElement();
final Sdk sdk = PythonSdkType.findPythonSdk(location.getModule());
return (TestRunnerService.getInstance(element.getProject()).getProjectConfiguration().equals(
Module module = location.getModule();
if (module == null) module = ModuleManager.getInstance(element.getProject()).getModules()[0];
final Sdk sdk = PythonSdkType.findPythonSdk(module);
return (TestRunnerService.getInstance(module).getProjectConfiguration().equals(
PythonTestConfigurationsModel.PYTHONS_NOSETEST_NAME) && sdk != null);
}
@@ -10,21 +10,28 @@ import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.junit.RuntimeConfigurationProducer;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.webcore.packaging.PackageVersionComparator;
import com.jetbrains.python.packaging.*;
import com.jetbrains.python.packaging.PyExternalProcessException;
import com.jetbrains.python.packaging.PyPackage;
import com.jetbrains.python.packaging.PyPackageManager;
import com.jetbrains.python.packaging.PyPackageManagerImpl;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyStatement;
import com.jetbrains.python.sdk.PythonSdkType;
import com.jetbrains.python.testing.*;
import com.jetbrains.python.testing.PythonTestConfigurationType;
import com.jetbrains.python.testing.PythonTestConfigurationsModel;
import com.jetbrains.python.testing.TestRunnerService;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -45,13 +52,17 @@ public class PyTestConfigurationProducer extends RuntimeConfigurationProducer {
@Override
protected RunnerAndConfigurationSettings createConfigurationByElement(Location location, ConfigurationContext context) {
PsiElement element = location.getPsiElement();
if (! (TestRunnerService.getInstance(element.getProject()).getProjectConfiguration().equals(
final Module module = ModuleUtilCore.findModuleForPsiElement(element);
if (module == null) return null;
if (! (TestRunnerService.getInstance(module).getProjectConfiguration().equals(
PythonTestConfigurationsModel.PY_TEST_NAME))) return null;
PsiFileSystemItem file = element instanceof PsiDirectory ? (PsiDirectory)element : element.getContainingFile();
if (file == null) return null;
myPsiElement = file;
String path = file.getVirtualFile().getPath();
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null) return null;
String path = virtualFile.getPath();
if (file instanceof PyFile || file instanceof PsiDirectory) {
final List<PyStatement> testCases = PyTestUtil.getPyTestCasesFromFile(file);
@@ -62,7 +73,7 @@ public class PyTestConfigurationProducer extends RuntimeConfigurationProducer {
RunManager.getInstance(location.getProject()).createRunConfiguration(file.getName(), getConfigurationFactory());
PyTestRunConfiguration configuration = (PyTestRunConfiguration)result.getConfiguration();
configuration.setUseModuleSdk(true);
configuration.setModule(ModuleUtil.findModuleForPsiElement(myPsiElement));
configuration.setModule(ModuleUtilCore.findModuleForPsiElement(myPsiElement));
final Sdk sdk = PythonSdkType.findPythonSdk(location.getModule());
if (sdk == null) return null;
@@ -124,7 +135,8 @@ public class PyTestConfigurationProducer extends RuntimeConfigurationProducer {
if (configuration instanceof PyTestRunConfiguration) {
final PsiElement element = location.getPsiElement();
PsiFileSystemItem file = element instanceof PsiDirectory ? (PsiDirectory)element : element.getContainingFile();
if (file == null || !((PyTestRunConfiguration)configuration).getTestToRun().equals(file.getVirtualFile().getPath())) {
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null || !((PyTestRunConfiguration)configuration).getTestToRun().equals(virtualFile.getPath())) {
continue;
}
PyFunction testFunction = findTestFunction(location);
@@ -137,7 +149,7 @@ public class PyTestConfigurationProducer extends RuntimeConfigurationProducer {
return null;
}
public int compareTo(Object o) {
public int compareTo(@NotNull Object o) {
return PREFERED;
}
}
@@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull;
public class PyTestRunnableScriptFilter implements RunnableScriptFilter {
public boolean isRunnableScript(PsiFile script, @NotNull Module module, Location location) {
return isPyTestInstalled(module) && isPyTestScript(script) &&
TestRunnerService.getInstance(script.getProject()).getProjectConfiguration().
TestRunnerService.getInstance(module).getProjectConfiguration().
equals(PythonTestConfigurationsModel.PY_TEST_NAME);
}
@@ -6,6 +6,8 @@ package com.jetbrains.python.testing.unittest;
import com.intellij.execution.Location;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
@@ -22,7 +24,9 @@ public class PythonUnitTestConfigurationProducer extends PythonTestConfiguration
protected boolean isAvailable(Location location) {
PsiElement element = location.getPsiElement();
if ((TestRunnerService.getInstance(element.getProject()).getProjectConfiguration().equals(
final Module module = ModuleUtilCore.findModuleForPsiElement(element);
if (module == null) return false;
if ((TestRunnerService.getInstance(module).getProjectConfiguration().equals(
PythonTestConfigurationsModel.PYTHONS_UNITTEST_NAME))) {
if (element instanceof PsiDirectory) {
final PyTestVisitor visitor = new PyTestVisitor();
@@ -1,6 +1,8 @@
package com.jetbrains.python.validation;
import com.intellij.lang.annotation.Annotation;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.util.TextRange;
import com.jetbrains.python.PythonDocStringFinder;
import com.jetbrains.python.documentation.*;
@@ -50,10 +52,10 @@ public class DocStringAnnotator extends PyAnnotator {
private void annotateDocStringStmt(final PyStringLiteralExpression stmt) {
if (stmt != null) {
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(stmt.getProject());
if (settings.isPlain(stmt.getContainingFile()))
return; // nothing to annotate if docstrings are plain
else {
final Module module = ModuleUtilCore.findModuleForPsiElement(stmt);
if (module == null) return;
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(module);
if (!settings.isPlain(stmt.getContainingFile())) {
String[] tags = settings.isEpydocFormat(stmt.getContainingFile()) ? EpydocString.ALL_TAGS : SphinxDocString.ALL_TAGS;
int pos = 0;
while(true) {
@@ -353,7 +353,7 @@ public class PyQuickFixTest extends PyTestCase {
}
public void testDocstringParams() { //PY-3394
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getProject());
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
documentationSettings.setFormat(DocStringFormat.EPYTEXT);
try {
doInspectionTest("DocstringParams.py", PyDocstringInspection.class,
@@ -365,7 +365,7 @@ public class PyQuickFixTest extends PyTestCase {
}
public void testDocstringParams1() {
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getProject());
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
documentationSettings.setFormat(DocStringFormat.EPYTEXT);
try {
doInspectionTest("DocstringParams1.py", PyDocstringInspection.class,
@@ -377,7 +377,7 @@ public class PyQuickFixTest extends PyTestCase {
}
public void testDocstringParams2() { //PY-4964
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getProject());
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
documentationSettings.setFormat(DocStringFormat.EPYTEXT);
try {
doInspectionTest("DocstringParams2.py", PyDocstringInspection.class,
@@ -394,6 +394,7 @@ public class PyQuickFixTest extends PyTestCase {
myFixture.configureByFiles(testFiles);
myFixture.checkHighlighting(true, false, true);
IntentionAction intentionAction = myFixture.getAvailableIntention(PyBundle.message("QFIX.remove.unnecessary.backslash"));
assertNotNull(intentionAction);
myFixture.launchAction(intentionAction);
myFixture.checkResultByFile(graftBeforeExt(testFiles[0], "_after"));
}
@@ -409,6 +410,7 @@ public class PyQuickFixTest extends PyTestCase {
myFixture.configureByFiles(testFiles);
myFixture.checkHighlighting(true, false, true);
IntentionAction intentionAction = myFixture.getAvailableIntention(PyBundle.message("QFIX.remove.unnecessary.backslash"));
assertNotNull(intentionAction);
myFixture.launchAction(intentionAction);
myFixture.checkResultByFile(graftBeforeExt(testFiles[0], "_after"));
}
@@ -109,7 +109,7 @@ public class PySmartEnterTest extends PyTestCase {
CodeInsightSettings codeInsightSettings = CodeInsightSettings.getInstance();
boolean oldStubOnEnter = codeInsightSettings.JAVADOC_STUB_ON_ENTER;
codeInsightSettings.JAVADOC_STUB_ON_ENTER = true;
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getProject());
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
documentationSettings.setFormat(DocStringFormat.REST);
try {
doTest();
@@ -124,7 +124,7 @@ public class PySmartEnterTest extends PyTestCase {
CodeInsightSettings codeInsightSettings = CodeInsightSettings.getInstance();
boolean oldStubOnEnter = codeInsightSettings.JAVADOC_STUB_ON_ENTER;
codeInsightSettings.JAVADOC_STUB_ON_ENTER = true;
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getProject());
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
documentationSettings.setFormat(DocStringFormat.EPYTEXT);
try {
doTest();
@@ -143,7 +143,7 @@ public class PySmartEnterTest extends PyTestCase {
PyCodeInsightSettings pyCodeInsightSettings = PyCodeInsightSettings.getInstance();
boolean oldInsertType = pyCodeInsightSettings.INSERT_TYPE_DOCSTUB;
pyCodeInsightSettings.INSERT_TYPE_DOCSTUB = true;
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getProject());
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
documentationSettings.setFormat(DocStringFormat.EPYTEXT);
try {
doTest();
@@ -144,6 +144,7 @@ public class PythonCompletionTest extends PyTestCase {
final String testName = "completion/" + getTestName(true);
myFixture.configureByFile(testName + ".py");
final LookupElement[] elements = myFixture.completeBasic();
assertNotNull(elements);
assertEquals(1, elements.length);
assertEquals("children", elements [0].getLookupString());
}
@@ -216,6 +217,7 @@ public class PythonCompletionTest extends PyTestCase {
myFixture.configureByText(PythonFileType.INSTANCE, "");
myFixture.completeBasic();
final List<String> elements = myFixture.getLookupElementStrings();
assertNotNull(elements);
assertTrue(elements.contains("import"));
}
@@ -320,7 +322,9 @@ public class PythonCompletionTest extends PyTestCase {
final String testName = "completion/" + getTestName(true);
myFixture.configureByFile(testName + ".py");
myFixture.completeBasic();
assertFalse(myFixture.getLookupElementStrings().contains("continue"));
final List<String> lookupElementStrings = myFixture.getLookupElementStrings();
assertNotNull(lookupElementStrings);
assertFalse(lookupElementStrings.contains("continue"));
}
public void testElseInCondExpr() { // PY-2397
@@ -406,12 +410,14 @@ public class PythonCompletionTest extends PyTestCase {
}
public void testEpydocTags() {
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(myFixture.getProject());
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(myFixture.getModule());
settings.setFormat(DocStringFormat.EPYTEXT);
try {
myFixture.configureByFile("completion/epydocTags.py");
myFixture.completeBasic();
assertTrue(myFixture.getLookupElementStrings().contains("@param"));
final List<String> lookupElementStrings = myFixture.getLookupElementStrings();
assertNotNull(lookupElementStrings);
assertTrue(lookupElementStrings.contains("@param"));
}
finally {
settings.setFormat(DocStringFormat.PLAIN);
@@ -419,7 +425,7 @@ public class PythonCompletionTest extends PyTestCase {
}
public void testEpydocTagsMiddle() {
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(myFixture.getProject());
final PyDocumentationSettings settings = PyDocumentationSettings.getInstance(myFixture.getModule());
settings.setFormat(DocStringFormat.EPYTEXT);
try {
myFixture.configureByFile("completion/epydocTagsMiddle.py");
@@ -556,7 +562,9 @@ public class PythonCompletionTest extends PyTestCase {
myFixture.copyDirectoryToProject("completion/relativeImportExcludeToplevel", "");
myFixture.configureByFile("pack/subpack/modX.py");
myFixture.completeBasic();
assertFalse(myFixture.getLookupElementStrings().contains("sys"));
final List<String> lookupElementStrings = myFixture.getLookupElementStrings();
assertNotNull(lookupElementStrings);
assertFalse(lookupElementStrings.contains("sys"));
}
finally {
setLanguageLevel(null);
@@ -173,7 +173,7 @@ public class PythonHighlightingTest extends PyTestCase {
}
public void testDocstring() { // PY-8025
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getProject());
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
documentationSettings.setFormat(DocStringFormat.REST);
try {
doTest(false, true);
@@ -129,7 +129,7 @@ public class PythonInspectionsTest extends PyTestCase {
}
public void testPyDocstringParametersInspection() { //PY-3373
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getProject());
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
documentationSettings.setFormat(DocStringFormat.EPYTEXT);
try {
doHighlightingTest(PyDocstringInspection.class);
@@ -420,7 +420,7 @@ public class PyIntentionTest extends PyTestCase {
private void doDocStubTest() {
CodeInsightSettings codeInsightSettings = CodeInsightSettings.getInstance();
codeInsightSettings.JAVADOC_STUB_ON_ENTER = true;
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getProject());
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
documentationSettings.setFormat(DocStringFormat.REST);
try {
doTest(PyBundle.message("INTN.doc.string.stub"), true);