Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2013-09-07 20:59:48 +02:00
22 changed files with 388 additions and 241 deletions
@@ -35,7 +35,12 @@ public class RootFileReferenceSet extends FileReferenceSet {
}
public boolean isAbsolutePathReference() {
return FileUtil.isAbsolute(getPathString());
if (!ApplicationManager.getApplication().isUnitTestMode()) {
return FileUtil.isAbsolute(getPathString());
}
else {
return super.isAbsolutePathReference();
}
}
@NotNull
@@ -15,6 +15,7 @@
<lang.substitutor language="TEXT" implementationClass="com.jetbrains.rest.RestLanguageSubstitutor"/>
<languageInjector implementation="com.jetbrains.rest.PyRestDocstringLanguageInjector"/>
<completion.contributor language="ReST" implementationClass="com.jetbrains.rest.completion.SphinxDirectiveCompletionContributor"/>
</extensions>
<actions>
@@ -8,11 +8,13 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.SystemInfo;
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.sdk.PythonSdkType;
import org.jetbrains.annotations.Nullable;
/**
* User : catherine
@@ -36,7 +38,7 @@ public class RestPythonUtil {
PyPackageManagerImpl manager = (PyPackageManagerImpl)PyPackageManager.getInstance(sdk);
try {
final PyPackage sphinx = manager.findPackage("Sphinx");
String quickStart = RestUtil.findQuickStart(sdk.getHomePath());
String quickStart = findQuickStart(sdk);
presentation.setEnabled(sphinx != null && quickStart != null);
}
catch (PyExternalProcessException ignored) {
@@ -47,4 +49,9 @@ public class RestPythonUtil {
return presentation;
}
@Nullable
public static String findQuickStart(final Sdk sdkHome) {
final String runnerName = "sphinx-quickstart" + (SystemInfo.isWindows ? ".exe" : "");
return PythonSdkType.getExecutablePath(sdkHome, runnerName);
}
}
@@ -0,0 +1,47 @@
package com.jetbrains.rest.completion;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.psi.PsiElement;
import com.intellij.util.ProcessingContext;
import com.jetbrains.rest.RestPythonUtil;
import com.jetbrains.rest.RestTokenTypes;
import com.jetbrains.rest.RestUtil;
import com.jetbrains.rest.psi.RestReferenceTarget;
import org.jetbrains.annotations.NotNull;
import static com.intellij.patterns.PlatformPatterns.psiElement;
import static com.intellij.patterns.StandardPatterns.or;
/**
* User : ktisha
*/
public class SphinxDirectiveCompletionContributor extends CompletionContributor {
public static final PsiElementPattern.Capture<PsiElement> DIRECTIVE_PATTERN = psiElement().afterSibling(or(psiElement().
withElementType(RestTokenTypes.WHITESPACE).afterSibling(psiElement(RestReferenceTarget.class)),
psiElement().withElementType(RestTokenTypes.EXPLISIT_MARKUP_START)));
public SphinxDirectiveCompletionContributor() {
extend(CompletionType.BASIC, DIRECTIVE_PATTERN,
new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull CompletionResultSet result) {
Sdk sdk = ProjectRootManager.getInstance(parameters.getPosition().getProject()).getProjectSdk();
if (sdk != null) {
String sphinx = RestPythonUtil.findQuickStart(sdk);
if (sphinx != null) {
for (String tag : RestUtil.SPHINX_DIRECTIVES) {
result.addElement(LookupElementBuilder.create(tag));
}
}
}
}
}
);
}
}
@@ -19,10 +19,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.HashSet;
import com.jetbrains.python.ReSTService;
import com.jetbrains.python.psi.*;
import com.jetbrains.rest.RestBundle;
import com.jetbrains.rest.RestFile;
import com.jetbrains.rest.RestTokenTypes;
import com.jetbrains.rest.RestUtil;
import com.jetbrains.rest.*;
import com.jetbrains.rest.psi.RestDirectiveBlock;
import com.jetbrains.rest.psi.RestRole;
import com.jetbrains.rest.quickfixes.AddIgnoredRoleFix;
@@ -114,7 +111,7 @@ public class RestRoleInspection extends RestInspection {
Sdk sdk = ProjectRootManager.getInstance(node.getProject()).getProjectSdk();
if (sdk != null) {
String sphinx = RestUtil.findQuickStart(sdk.getHomePath());
String sphinx = RestPythonUtil.findQuickStart(sdk);
if (sphinx != null) {
if (RestUtil.SPHINX_ROLES.contains(node.getText()) || RestUtil.SPHINX_ROLES.contains(":py"+node.getText())
|| mySphinxRoles.contains(node.getRoleName())) return;
@@ -22,7 +22,7 @@ import com.jetbrains.python.run.PythonCommandLineState;
import com.jetbrains.python.run.PythonProcessRunner;
import com.jetbrains.python.run.PythonTracebackFilter;
import com.jetbrains.python.sdk.PythonSdkType;
import com.jetbrains.rest.RestUtil;
import com.jetbrains.rest.RestPythonUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -169,6 +169,6 @@ public class SphinxBaseCommand {
@Nullable
private static String getCommandPath(Sdk sdk) {
return RestUtil.findQuickStart(sdk.getHomePath());
return RestPythonUtil.findQuickStart(sdk);
}
}
@@ -0,0 +1,5 @@
<html>
<body>
This inspection detects shadowing built-in names, such as 'len' or 'list'.
</body>
</html>
@@ -1,5 +1,5 @@
<html>
<body>
This inspection detects shadowing names defined in outer scopes, including built-in names.
This inspection detects shadowing names defined in outer scopes.
</body>
</html>
@@ -2,11 +2,7 @@ package com.jetbrains.rest;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.LocalFileSystem;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.Map;
import java.util.Set;
@@ -16,32 +12,6 @@ import java.util.Set;
public class RestUtil {
private RestUtil() {}
@Nullable
public static String findQuickStart(final String sdkHome) {
final String runnerName = "sphinx-quickstart" + (SystemInfo.isWindows ? ".exe" : "");
File binPath = new File(sdkHome);
File binDir = binPath.getParentFile();
if (binDir == null) return null;
File runner = new File(binDir, runnerName);
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
runner = new File(new File(binDir, "scripts"), runnerName);
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
runner = new File(new File(binDir.getParentFile(), "scripts"), runnerName);
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
runner = new File(new File(binDir.getParentFile(), "local"), runnerName);
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
runner = new File(new File (new File(binDir.getParentFile(), "local"), "bin"), runnerName);
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
// Search in standard unix path
runner = new File(new File("/usr", "bin"), runnerName);
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
runner = new File(new File (new File("/usr", "local"), "bin"), runnerName);
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
return null;
}
public static String[] SPHINX_DIRECTIVES = new String[] {
"module::" , "automodule::" , "autoclass::" , "toctree::" , "glossary::" , "code-block::", "versionadded::",
"versionchanged::", "deprecated::", "seealso::", "centered::", "hlist::", "index::", "productionlist::", "highlight::",
@@ -2,8 +2,6 @@ package com.jetbrains.rest.completion;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.psi.PsiElement;
import com.intellij.util.ProcessingContext;
@@ -33,15 +31,6 @@ public class DirectiveCompletionContributor extends CompletionContributor {
for (String tag : RestUtil.getDirectives()) {
result.addElement(LookupElementBuilder.create(tag));
}
Sdk sdk = ProjectRootManager.getInstance(parameters.getPosition().getProject()).getProjectSdk();
if (sdk != null) {
String sphinx = RestUtil.findQuickStart(sdk.getHomePath());
if (sphinx != null) {
for (String tag : RestUtil.SPHINX_DIRECTIVES) {
result.addElement(LookupElementBuilder.create(tag));
}
}
}
}
}
);
+2 -1
View File
@@ -323,7 +323,8 @@
<localInspection language="Python" shortName="PyProtectedMemberInspection" displayName="Access to a protected member of a class" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyProtectedMemberInspection"/>
<localInspection language="Python" shortName="PyMethodMayBeStaticInspection" displayName="Method may be static" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyMethodMayBeStaticInspection"/>
<localInspection language="Python" shortName="PyDocstringTypesInspection" bundle="com.jetbrains.python.PyBundle" key="INSP.NAME.docstring.types" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyDocstringTypesInspection"/>
<localInspection language="Python" shortName="PyShadowingNamesInspection" displayName="Shadowing names" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyShadowingNamesInspection"/>
<localInspection language="Python" shortName="PyShadowingBuiltinsInspection" displayName="Shadowing built-ins" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyShadowingBuiltinsInspection"/>
<localInspection language="Python" shortName="PyShadowingNamesInspection" displayName="Shadowing names from outer scopes" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyShadowingNamesInspection"/>
<localInspection language="Python" shortName="PyAbstractClassInspection" displayName="Class must implement all abstract methods" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyAbstractClassInspection"/>
<localInspection language="Python" shortName="PyPep8NamingInspection" displayName="PEP 8 naming convention violation" groupKey="INSP.GROUP.python" enabledByDefault="true" level="INFO" implementationClass="com.jetbrains.python.inspections.PyPep8NamingInspection"/>
@@ -74,8 +74,7 @@ public class PyRedeclarationInspection extends PyInspection {
}
private static boolean isConditional(@NotNull PsiElement node) {
return PsiTreeUtil.getParentOfType(node, PyIfStatement.class, PyConditionalExpression.class, PyLoopStatement.class,
PyComprehensionElement.class, PyTryExceptStatement.class) != null;
return PsiTreeUtil.getParentOfType(node, PyIfStatement.class, PyConditionalExpression.class, PyTryExceptStatement.class) != null;
}
private static boolean isDecorated(@NotNull PyDecoratable node) {
@@ -118,17 +117,20 @@ public class PyRedeclarationInspection extends PyInspection {
if (rwInstruction.getAccess().isWriteAccess()) {
final List<LocalQuickFix> quickFixes = new ArrayList<LocalQuickFix>();
final PsiElement originalElement = rwInstruction.getElement();
if (originalElement != null && suggestRename(element, originalElement)) {
quickFixes.add(new PyRenameElementQuickFix());
if (originalElement != null && originalElement != element) {
if (suggestRename(element, originalElement)) {
quickFixes.add(new PyRenameElementQuickFix());
}
final PsiElement identifier = element.getNameIdentifier();
registerProblem(identifier != null ? identifier : element,
PyBundle.message("INSP.redeclared.name", name),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
null,
quickFixes.toArray(new LocalQuickFix[quickFixes.size()]));
return ControlFlowUtil.Operation.BREAK;
}
final PsiElement identifier = element.getNameIdentifier();
registerProblem(identifier != null ? identifier : element,
PyBundle.message("INSP.redeclared.name", name),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
null,
quickFixes.toArray(new LocalQuickFix[quickFixes.size()]));
}
return ControlFlowUtil.Operation.BREAK;
return ControlFlowUtil.Operation.CONTINUE;
}
}
return ControlFlowUtil.Operation.NEXT;
@@ -0,0 +1,144 @@
package com.jetbrains.python.inspections;
import com.google.common.collect.ImmutableSet;
import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ui.ListEditForm;
import com.intellij.openapi.project.Project;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.util.Consumer;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Warns about shadowing built-in names.
*
* @author vlan
*/
public class PyShadowingBuiltinsInspection extends PyInspection {
// Persistent settings
public List<String> ignoredNames = new ArrayList<String>();
@NotNull
@Override
public String getDisplayName() {
return "Shadowing built-ins";
}
@Override
public JComponent createOptionsPanel() {
final ListEditForm form = new ListEditForm("Ignore built-ins", ignoredNames);
return form.getContentPanel();
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
boolean isOnTheFly,
@NotNull LocalInspectionToolSession session) {
return new Visitor(holder, session, ignoredNames);
}
private static class Visitor extends PyInspectionVisitor {
private final Set<String> myIgnoredNames;
public Visitor(@Nullable ProblemsHolder holder, @NotNull LocalInspectionToolSession session, @NotNull Collection<String> ignoredNames) {
super(holder, session);
myIgnoredNames = ImmutableSet.copyOf(ignoredNames);
}
@Override
public void visitPyClass(@NotNull PyClass node) {
processElement(node);
}
@Override
public void visitPyFunction(@NotNull PyFunction node) {
processElement(node);
}
@Override
public void visitPyNamedParameter(@NotNull PyNamedParameter node) {
processElement(node);
}
@Override
public void visitPyTargetExpression(@NotNull PyTargetExpression node) {
if (node.getQualifier() == null) {
processElement(node);
}
}
private void processElement(@NotNull PsiNameIdentifierOwner element) {
final ScopeOwner owner = ScopeUtil.getScopeOwner(element);
if (owner instanceof PyClass) {
return;
}
final String name = element.getName();
if (name != null && !myIgnoredNames.contains(name)) {
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(element);
final PsiElement builtin = builtinCache.getByName(name);
if (builtin != null && !PyUtil.inSameFile(builtin, element)) {
final PsiElement identifier = element.getNameIdentifier();
final PsiElement problemElement = identifier != null ? identifier : element;
registerProblem(problemElement, String.format("Shadows built-in name '%s'", name),
ProblemHighlightType.WEAK_WARNING, null, new PyRenameElementQuickFix(), new PyIgnoreBuiltinQuickFix(name));
}
}
}
private static class PyIgnoreBuiltinQuickFix implements LocalQuickFix, LowPriorityAction {
@NotNull private final String myName;
private PyIgnoreBuiltinQuickFix(@NotNull String name) {
myName = name;
}
@NotNull
@Override
public String getName() {
return getFamilyName() + " \"" + myName + "\"";
}
@NotNull
@Override
public String getFamilyName() {
return "Ignore shadowed built-in name";
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
if (element != null) {
final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
profile.modifyProfile(new Consumer<ModifiableModel>() {
@Override
public void consume(ModifiableModel model) {
final String toolName = PyShadowingBuiltinsInspection.class.getSimpleName();
final PyShadowingBuiltinsInspection inspection = (PyShadowingBuiltinsInspection)model.getUnwrappedTool(toolName, element);
if (inspection != null) {
if (!inspection.ignoredNames.contains(myName)) {
inspection.ignoredNames.add(myName);
}
}
}
});
}
}
}
}
}
@@ -1,52 +1,32 @@
package com.jetbrains.python.inspections;
import com.google.common.collect.ImmutableSet;
import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ui.ListEditForm;
import com.intellij.openapi.project.Project;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Consumer;
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.resolve.PyResolveUtil;
import com.jetbrains.python.psi.resolve.ResolveProcessor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Warns about shadowing names defined in outer scopes.
*
* @author vlan
*/
public class PyShadowingNamesInspection extends PyInspection {
// Persistent settings
public List<String> ignoredNames = new ArrayList<String>();
@NotNull
@Override
public String getDisplayName() {
return "Shadowing names";
}
@Override
public JComponent createOptionsPanel() {
final ListEditForm form = new ListEditForm("Ignore built-ins", ignoredNames);
return form.getContentPanel();
return "Shadowing names from outer scopes";
}
@NotNull
@@ -54,15 +34,12 @@ public class PyShadowingNamesInspection extends PyInspection {
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
boolean isOnTheFly,
@NotNull LocalInspectionToolSession session) {
return new Visitor(holder, session, ignoredNames);
return new Visitor(holder, session);
}
private static class Visitor extends PyInspectionVisitor {
private final Set<String> myIgnoredNames;
public Visitor(@Nullable ProblemsHolder holder, @NotNull LocalInspectionToolSession session, @NotNull Collection<String> ignoredNames) {
public Visitor(@Nullable ProblemsHolder holder, @NotNull LocalInspectionToolSession session) {
super(holder, session);
myIgnoredNames = ImmutableSet.copyOf(ignoredNames);
}
@Override
@@ -92,99 +69,35 @@ public class PyShadowingNamesInspection extends PyInspection {
private void processElement(@NotNull PsiNameIdentifierOwner element) {
final ScopeOwner owner = ScopeUtil.getScopeOwner(element);
// Class-level names are rarely accessed inside at the class level, usually they are accessed as attributes
if (owner instanceof PyClass) {
return;
}
final String name = element.getName();
if (name != null && !myIgnoredNames.contains(name)) {
if (name != null) {
final PsiElement identifier = element.getNameIdentifier();
final PsiElement problemElement = identifier != null ? identifier : element;
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(element);
final PsiElement builtin = builtinCache.getByName(name);
if (builtin != null) {
processBuiltin(element, name, problemElement, builtin);
if ("_".equals(name)) {
return;
}
else {
processOuterScope(element, name, problemElement);
}
}
}
private void processBuiltin(@NotNull PsiNameIdentifierOwner element,
@NotNull String name,
@NotNull PsiElement problemElement,
@NotNull PsiElement builtin) {
if (!PyUtil.inSameFile(builtin, element)) {
registerProblem(problemElement, String.format("Shadows built-in name '%s'", name),
ProblemHighlightType.WEAK_WARNING, null, new PyRenameElementQuickFix(),
new PyIgnoreBuiltinQuickFix(name));
}
}
private void processOuterScope(@NotNull PsiNameIdentifierOwner element, @NotNull String name, @NotNull PsiElement problemElement) {
if ("_".equals(name)) {
return;
}
final ScopeOwner owner = ScopeUtil.getScopeOwner(element);
if (owner != null) {
final ScopeOwner nextOwner = ScopeUtil.getScopeOwner(owner);
if (nextOwner != null) {
final ResolveProcessor processor = new ResolveProcessor(name);
PyResolveUtil.scopeCrawlUp(processor, nextOwner, null, name, null);
final PsiElement resolved = processor.getResult();
if (resolved != null) {
final PyComprehensionElement comprehension = PsiTreeUtil.getParentOfType(resolved, PyComprehensionElement.class);
if (comprehension != null && PyUtil.isOwnScopeComprehension(comprehension)) {
return;
}
final Scope scope = ControlFlowCache.getScope(owner);
if (scope.isGlobal(name) || scope.isNonlocal(name)) {
return;
}
registerProblem(problemElement, String.format("Shadows name '%s' from outer scope", name),
ProblemHighlightType.WEAK_WARNING, null, new PyRenameElementQuickFix());
}
}
}
}
private static class PyIgnoreBuiltinQuickFix implements LocalQuickFix, LowPriorityAction {
@NotNull private final String myName;
private PyIgnoreBuiltinQuickFix(@NotNull String name) {
myName = name;
}
@NotNull
@Override
public String getName() {
return getFamilyName() + " \"" + myName + "\"";
}
@NotNull
@Override
public String getFamilyName() {
return "Ignore shadowed built-in name";
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
if (element != null) {
final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
profile.modifyProfile(new Consumer<ModifiableModel>() {
@Override
public void consume(ModifiableModel model) {
final String toolName = PyShadowingNamesInspection.class.getSimpleName();
final PyShadowingNamesInspection inspection = (PyShadowingNamesInspection)model.getUnwrappedTool(toolName, element);
if (inspection != null) {
if (!inspection.ignoredNames.contains(myName)) {
inspection.ignoredNames.add(myName);
}
if (owner != null) {
final ScopeOwner nextOwner = ScopeUtil.getScopeOwner(owner);
if (nextOwner != null) {
final ResolveProcessor processor = new ResolveProcessor(name);
PyResolveUtil.scopeCrawlUp(processor, nextOwner, null, name, null);
final PsiElement resolved = processor.getResult();
if (resolved != null) {
final PyComprehensionElement comprehension = PsiTreeUtil.getParentOfType(resolved, PyComprehensionElement.class);
if (comprehension != null && PyUtil.isOwnScopeComprehension(comprehension)) {
return;
}
final Scope scope = ControlFlowCache.getScope(owner);
if (scope.isGlobal(name) || scope.isNonlocal(name)) {
return;
}
registerProblem(problemElement, String.format("Shadows name '%s' from outer scope", name),
ProblemHighlightType.WEAK_WARNING, null, new PyRenameElementQuickFix());
}
});
}
}
}
}
@@ -299,8 +299,12 @@ public abstract class PythonCommandLineState extends CommandLineState {
}
private static void addIfNeeded(@NotNull final VirtualFile file, @NotNull final Collection<String> pathList) {
addIfNeeded(pathList, file.getPath());
}
protected static void addIfNeeded(Collection<String> pathList, String path) {
final Set<String> vals = Sets.newHashSet(pathList);
final String filePath = FileUtil.toSystemDependentName(file.getPath());
final String filePath = FileUtil.toSystemDependentName(path);
if (!vals.contains(filePath)) {
pathList.add(filePath);
}
@@ -867,6 +867,37 @@ public class PythonSdkType extends SdkType {
return null;
}
@Nullable
public static String getExecutablePath(@NotNull final String homeDirectory, @NotNull String name) {
File binPath = new File(homeDirectory);
File binDir = binPath.getParentFile();
if (binDir == null) return null;
File runner = new File(binDir, name);
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
runner = new File(new File(binDir, "Scripts"), name);
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
runner = new File(new File(binDir.getParentFile(), "Scripts"), name);
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
runner = new File(new File(binDir.getParentFile(), "local"), name);
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
runner = new File(new File(new File(binDir.getParentFile(), "local"), "bin"), name);
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
// Search in standard unix path
runner = new File(new File("/usr", "bin"), name);
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
runner = new File(new File (new File("/usr", "local"), "bin"), name);
if (runner.exists()) return LocalFileSystem.getInstance().extractPresentableUrl(runner.getPath());
return null;
}
@Nullable
public static String getExecutablePath(@NotNull final Sdk sdk, @NotNull String name) {
final String homeDirectory = sdk.getHomePath();
if (homeDirectory == null) return null;
return getExecutablePath(homeDirectory, name);
}
private static String[] getBinaryNames() {
if (SystemInfo.isUnix) {
return UNIX_BINARY_NAMES;
@@ -4,6 +4,7 @@ import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.ParamsGroup;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.testing.AbstractPythonTestRunConfiguration;
@@ -37,15 +38,16 @@ public class PythonUnitTestCommandLineState extends
protected List<String> getTestSpecs() {
List<String> specs = new ArrayList<String>();
final String scriptName = FileUtil.toSystemDependentName(myConfig.getScriptName());
switch (myConfig.getTestType()) {
case TEST_SCRIPT:
specs.add(myConfig.getScriptName());
specs.add(scriptName);
break;
case TEST_CLASS:
specs.add(myConfig.getScriptName() + "::" + myConfig.getClassName());
specs.add(scriptName + "::" + myConfig.getClassName());
break;
case TEST_METHOD:
specs.add(myConfig.getScriptName() + "::" + myConfig.getClassName() + "::" + myConfig.getMethodName());
specs.add(scriptName + "::" + myConfig.getClassName() + "::" + myConfig.getMethodName());
break;
case TEST_FOLDER:
if (!StringUtil.isEmpty(myConfig.getPattern()) && myConfig.usePattern()) {
@@ -56,7 +58,7 @@ public class PythonUnitTestCommandLineState extends
}
break;
case TEST_FUNCTION:
specs.add(myConfig.getScriptName() + "::::" + myConfig.getMethodName());
specs.add(scriptName + "::::" + myConfig.getMethodName());
break;
default:
throw new IllegalArgumentException("Unknown test type: " + myConfig.getTestType());
@@ -43,7 +43,7 @@ def test_local_variable():
x = 2
def conditional(c):
def test_conditional(c):
def foo():
pass
@@ -51,12 +51,39 @@ def conditional(c):
def foo():
pass
while c:
def foo():
pass
try:
def foo():
pass
except:
pass
def test_while_loop(c):
def foo():
pass
while c:
def <warning descr="Redeclared 'foo' defined above without usage">foo</warning>():
pass
class TestForLoopNoRedeclaraion:
for foo in [1, 2, 3]:
x = 1
class TestForLoopTarget:
def foo():
pass
for <warning descr="Redeclared 'foo' defined above without usage">foo</warning> in [1, 2, 3]:
x = 1
class TestForLoopBody:
def foo():
pass
for _ in [1, 2, 3]:
def <warning descr="Redeclared 'foo' defined above without usage">foo</warning>():
pass
@@ -0,0 +1,50 @@
def test_import_builtin_names():
import float
from foo import float
from bar import baz as <weak_warning descr="Shadows built-in name 'float'">float</weak_warning>
def test_builtin_function_parameters():
def test1(x, _, <weak_warning descr="Shadows built-in name 'len'">len</weak_warning>, <weak_warning descr="Shadows built-in name 'file'">file</weak_warning>=None):
pass
def test_builtin_function_name():
def <weak_warning descr="Shadows built-in name 'list'">list</weak_warning>():
pass
def test_builtin_assignment_targets():
foo = 2
<weak_warning descr="Shadows built-in name 'list'">list</weak_warning> = []
for <weak_warning descr="Shadows built-in name 'int'">int</weak_warning> in range(10):
print(int)
<weak_warning descr="Shadows built-in name 'range'">range</weak_warning> = []
<weak_warning descr="Shadows built-in name 'list'">list</weak_warning>, _ = (1, 2)
return [int for <weak_warning descr="Shadows built-in name 'int'">int</weak_warning> in range(10)]
def test_builtin_class_name():
class <weak_warning descr="Shadows built-in name 'list'">list</weak_warning>(object):
pass
def test_builtin_method_name():
class C:
def list(self):
pass
# PY-8646
def test_builtin_qualified_name():
test1.range = float()
class C:
def foo(self):
self.list = []
# PY-10164
def test_builtin_class_attribute():
class C:
id = 1
@@ -1,58 +1,6 @@
global_foo = 1
def test_import_builtin_names():
import float
from foo import float
from bar import baz as <weak_warning descr="Shadows built-in name 'float'">float</weak_warning>
def test_builtin_function_parameters():
def test1(x, _, <weak_warning descr="Shadows built-in name 'len'">len</weak_warning>, <weak_warning descr="Shadows built-in name 'file'">file</weak_warning>=None):
pass
def test_builtin_function_name():
def <weak_warning descr="Shadows built-in name 'list'">list</weak_warning>():
pass
def test_builtin_assignment_targets():
foo = 2
<weak_warning descr="Shadows built-in name 'list'">list</weak_warning> = []
for <weak_warning descr="Shadows built-in name 'int'">int</weak_warning> in range(10):
print(int)
<weak_warning descr="Shadows built-in name 'range'">range</weak_warning> = []
<weak_warning descr="Shadows built-in name 'list'">list</weak_warning>, _ = (1, 2)
return [int for <weak_warning descr="Shadows built-in name 'int'">int</weak_warning> in range(10)]
def test_builtin_class_name():
class <weak_warning descr="Shadows built-in name 'list'">list</weak_warning>(object):
pass
def test_builtin_method_name():
class C:
def list(self):
pass
# PY-8646
def test_builtin_qualified_name():
test1.range = float()
class C:
def foo(self):
self.list = []
# PY-10164
def test_builtin_class_attribute():
class C:
id = 1
def test_outer_function():
foo = 1
def bar():
@@ -91,7 +39,7 @@ def test_outer_global():
global_foo = 2
def test_comprehensions():
def test_outer_comprehensions():
print(x for x in range(10))
print([y for y in range(10)])
def f(x, <weak_warning descr="Shadows name 'y' from outer scope">y</weak_warning>):
@@ -433,7 +433,7 @@ public class PyQuickFixTest extends PyTestCase {
public void testRenameShadowingBuiltins() {
final String fileName = "RenameShadowingBuiltins.py";
myFixture.configureByFile(fileName);
myFixture.enableInspections(PyShadowingNamesInspection.class);
myFixture.enableInspections(PyShadowingBuiltinsInspection.class);
myFixture.checkHighlighting(true, false, true);
final IntentionAction intentionAction = myFixture.getAvailableIntention("Rename element");
assertNotNull(intentionAction);
@@ -445,7 +445,7 @@ public class PyQuickFixTest extends PyTestCase {
public void testRenameFunctionShadowingBuiltins() {
final String fileName = "RenameFunctionShadowingBuiltins.py";
myFixture.configureByFile(fileName);
myFixture.enableInspections(PyShadowingNamesInspection.class);
myFixture.enableInspections(PyShadowingBuiltinsInspection.class);
myFixture.checkHighlighting(true, false, true);
final IntentionAction intentionAction = myFixture.getAvailableIntention("Rename element");
assertNotNull(intentionAction);
@@ -295,6 +295,10 @@ public class PythonInspectionsTest extends PyTestCase {
}
// PY-5807
public void testPyShadowingBuiltinsInspection() {
doHighlightingTest(PyShadowingBuiltinsInspection.class);
}
public void testPyShadowingNamesInspection() {
doHighlightingTest(PyShadowingNamesInspection.class);
}