Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2013-03-22 14:04:56 +01:00
59 changed files with 943 additions and 35 deletions
@@ -88,4 +88,5 @@ public abstract class PyElementGenerator {
public abstract PsiFile createDummyFile(LanguageLevel langLevel, String contents);
public abstract PyExpressionStatement createDocstring(String content);
public abstract PyPassStatement createPassStatement();
}
@@ -316,6 +316,11 @@
<localInspection language="Python" shortName="PyMandatoryEncodingInspection" displayName="No encoding specified for file" groupKey="INSP.GROUP.python" enabledByDefault="false" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyMandatoryEncodingInspection"/>
<localInspection language="Python" shortName="PyPackageRequirementsInspection" bundle="com.jetbrains.python.PyBundle" key="INSP.NAME.requirements" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyPackageRequirementsInspection"/>
<localInspection language="Python" shortName="PyPep8Inspection" displayName="PEP 8 coding style violation" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyPep8Inspection"/>
<localInspection language="Python" shortName="PyAttributeOutsideInitInspection" displayName="Instance attribute defined outside _init_" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyAttributeOutsideInitInspection"/>
<localInspection language="Python" shortName="PyClassHasNoInitInspection" displayName="Class has no __init__ method" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyClassHasNoInitInspection"/>
<localInspection language="Python" shortName="PyNoneFunctionAssignmentInspection" displayName="Assigning function call that doesn't return anything" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyNoneFunctionAssignmentInspection"/>
<localInspection language="Python" shortName="PyGlobalUndefinedInspection" displayName="Global variable is undefined at the module level" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyGlobalUndefinedInspection"/>
<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="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="PyShadowingBuiltinsInspection" displayName="Shadowing built-ins" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyShadowingBuiltinsInspection"/>
@@ -102,6 +102,9 @@ QFIX.remove.decorator=Remove decorator
#PyRenameUnresolvedRefQuickFix
QFIX.rename.unresolved.reference=Rename reference
#PyMoveAttributeToInitQuickFix
QFIX.move.attribute=Move attribute to __init__ method
# Intentions: INTN
INTN.Family.convert.import.unqualify=Convert 'import module' to 'from module import'
INTN.Family.convert.import.qualify=Convert 'from module import' to 'import module'
@@ -431,6 +434,14 @@ INSP.NAME.augment.assignment=Assignment can be replaced with augmented assignmen
# PyChainedComparsonsInspection
INSP.NAME.chained.comparisons=Chained comparisons can be simplified
# PyAttributeOutsideInitInspection
INSP.NAME.attribute.outside.init=Instance attribute defined outside __init__
INSP.attribute.$0.outside.init=Instance attribute {0} defined outside __init__
# PyProtectedMemberInspection
INSP.NAME.protected.member.access=Access to a protected member of a class
INSP.protected.member.$0.access=Access to a protected member {0} of a class
# PyArgumentEqualDefaultInspection
INSP.NAME.argument.equal.default=Argument passed to function is equal to default parameter value
INSP.argument.equals.to.default=Argument equals to default parameter value
@@ -460,6 +471,18 @@ INSP.NAME.decorator.outside.class=Class specific decorator on method outside cla
# PyPackageRequirementsInspection
INSP.NAME.requirements=Package requirements
# PyClassHasNoInitInspection
INSP.NAME.class.has.no.init=Class has no __init__ method
INSP.class.has.no.init=Class has no __init__ method
INSP.parent.$0.has.no.init=Parent ''{0}'' has no __init__ method
#PyNoneFunctionAssignmentInspection
INSP.NAME.none.function.assignment=Assigning function call that doesn't return anything (None)
INSP.none.function.assignment=Function ''{0}'' doesn''t return anything
#PyGlobalUndefinedInspection
INSP.NAME.global.undefined=Global variable is undefined at the module level
INSP.NAME.global.$0.undefined=Global variable ''{0}'' is undefined at the module level
# Refactoring
# introduce
@@ -0,0 +1,70 @@
package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.inspections.quickfix.PyMoveAttributeToInitQuickFix;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyTargetExpression;
import com.jetbrains.python.psi.impl.PyClassImpl;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
/**
* User: ktisha
*
* Inspection to detect situations, where instance attribute
* defined outside __init__ function
*/
public class PyAttributeOutsideInitInspection extends PyInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return PyBundle.message("INSP.NAME.attribute.outside.init");
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
boolean isOnTheFly,
@NotNull LocalInspectionToolSession session) {
return new Visitor(holder, session);
}
private static class Visitor extends PyInspectionVisitor {
public Visitor(@Nullable ProblemsHolder holder, @NotNull LocalInspectionToolSession session) {
super(holder, session);
}
@Override
public void visitPyFunction(PyFunction node) {
final PyClass containingClass = node.getContainingClass();
if (containingClass == null) return;
Map<String, PyTargetExpression> attributesInInit = new HashMap<String, PyTargetExpression>();
final PyFunction initMethod = containingClass.findMethodByName(PyNames.INIT, false);
if (initMethod != null)
PyClassImpl.collectInstanceAttributes(initMethod, attributesInInit);
Map<String, PyTargetExpression> attributes = new HashMap<String, PyTargetExpression>();
PyClassImpl.collectInstanceAttributes(node, attributes);
for (Map.Entry<String, PyTargetExpression> attribute : attributes.entrySet()) {
if (!attributesInInit.containsKey(attribute.getKey())) {
registerProblem(attribute.getValue(), PyBundle.message("INSP.attribute.$0.outside.init", attribute.getKey()),
new PyMoveAttributeToInitQuickFix());
}
}
}
}
}
@@ -0,0 +1,57 @@
package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.inspections.quickfix.AddMethodQuickFix;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.types.PyClassTypeImpl;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* User: ktisha
* See pylint W0232
*/
public class PyClassHasNoInitInspection extends PyInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return PyBundle.message("INSP.NAME.class.has.no.init");
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
boolean isOnTheFly,
@NotNull LocalInspectionToolSession session) {
return new Visitor(holder, session);
}
private static class Visitor extends PyInspectionVisitor {
public Visitor(@Nullable ProblemsHolder holder, @NotNull LocalInspectionToolSession session) {
super(holder, session);
}
@Override
public void visitPyClass(PyClass node) {
final PyFunction init = node.findMethodByName(PyNames.INIT, false);
if (init == null) {
registerProblem(node.getNameIdentifier(), PyBundle.message("INSP.class.has.no.init"),
new AddMethodQuickFix("__init__", new PyClassTypeImpl(node, false), false));
}
for (PyClass ancestor : node.iterateAncestorClasses()) {
final PyFunction ancestorInit = ancestor.findMethodByName(PyNames.INIT, false);
if (ancestorInit == null) {
registerProblem(node.getNameIdentifier(), PyBundle.message("INSP.parent.$0.has.no.init", ancestor.getName()),
new AddMethodQuickFix("__init__", new PyClassTypeImpl(ancestor, false), false));
}
}
}
}
}
@@ -0,0 +1,51 @@
package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.PyGlobalStatement;
import com.jetbrains.python.psi.PyTargetExpression;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* User: ktisha
*
* pylint W0601
*/
public class PyGlobalUndefinedInspection extends PyInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return PyBundle.message("INSP.NAME.global.undefined");
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
boolean isOnTheFly,
@NotNull LocalInspectionToolSession session) {
return new Visitor(holder, session);
}
private static class Visitor extends PyInspectionVisitor {
public Visitor(@Nullable ProblemsHolder holder, @NotNull LocalInspectionToolSession session) {
super(holder, session);
}
@Override
public void visitPyGlobalStatement(PyGlobalStatement node) {
final PyTargetExpression[] globals = node.getGlobals();
for (PyTargetExpression global : globals) {
if (global.getReference().resolve() == global) {
registerProblem(global, PyBundle.message("INSP.NAME.global.$0.undefined", global.getName()));
}
}
}
}
}
@@ -0,0 +1,57 @@
package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.PyAssignmentStatement;
import com.jetbrains.python.psi.PyCallExpression;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.types.PyNoneType;
import com.jetbrains.python.psi.types.PyType;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* User: ktisha
*
* pylint E1111
*
* Used when an assignment is done on a function call but the inferred function doesn't return anything.
*/
public class PyNoneFunctionAssignmentInspection extends PyInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return PyBundle.message("INSP.NAME.none.function.assignment");
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
boolean isOnTheFly,
@NotNull LocalInspectionToolSession session) {
return new Visitor(holder, session);
}
private static class Visitor extends PyInspectionVisitor {
public Visitor(@Nullable ProblemsHolder holder, @NotNull LocalInspectionToolSession session) {
super(holder, session);
}
@Override
public void visitPyAssignmentStatement(PyAssignmentStatement node) {
final PyExpression value = node.getAssignedValue();
if (value instanceof PyCallExpression) {
final PyType type = myTypeEvalContext.getType(value);
final PyExpression callee = ((PyCallExpression)value).getCallee();
if (type instanceof PyNoneType && callee != null) {
registerProblem(node, PyBundle.message("INSP.none.function.assignment", callee.getName()));
}
}
}
}
}
@@ -0,0 +1,65 @@
package com.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyReferenceExpression;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* User: ktisha
*
* Inspection to detect situations, where
* protected member (i.e. class member with a name beginning with an underscore)
* is access outside the class or a descendant of the class where it's defined.
*/
public class PyProtectedMemberInspection extends PyInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return PyBundle.message("INSP.NAME.protected.member.access");
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
boolean isOnTheFly,
@NotNull LocalInspectionToolSession session) {
return new Visitor(holder, session);
}
private static class Visitor extends PyInspectionVisitor {
public Visitor(@Nullable ProblemsHolder holder, @NotNull LocalInspectionToolSession session) {
super(holder, session);
}
@Override
public void visitPyReferenceExpression(PyReferenceExpression node) {
final PyExpression qualifier = node.getQualifier();
if (qualifier == null) return;
final String name = node.getName();
if (name != null && name.startsWith("_")) {
final PyClass parentClass = PsiTreeUtil.getParentOfType(node, PyClass.class);
if (parentClass != null) {
final PsiReference reference = node.getReference();
final PsiElement resolvedExpression = reference.resolve();
final PyClass resolvedClass = PsiTreeUtil.getParentOfType(resolvedExpression, PyClass.class);
if (parentClass.isSubclass(resolvedClass))
return;
}
registerProblem(node, PyBundle.message("INSP.protected.member.$0.access", name));
}
}
}
}
@@ -684,7 +684,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
return true;
}
final String docString = cls.getDocStringValue();
if (docString != null && docString.indexOf("@DynamicAttrs") != -1) {
if (docString != null && docString.contains("@DynamicAttrs")) {
return true;
}
}
@@ -697,7 +697,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
PyClass cls = ((PyClassType)qtype).getPyClass();
if (!PyBuiltinCache.getInstance(element).hasInBuiltins(cls)) {
if (element.getParent() instanceof PyCallExpression) {
actions.add(new AddMethodQuickFix(refText, (PyClassType)qtype));
actions.add(new AddMethodQuickFix(refText, (PyClassType)qtype, true));
}
else if (!(reference instanceof PyOperatorReference)) {
actions.add(new AddFieldQuickFix(refText, cls, "None"));
@@ -29,11 +29,14 @@ import static com.jetbrains.python.psi.PyUtil.sure;
public class AddMethodQuickFix implements LocalQuickFix {
private PyClassType myQualifierType;
private final boolean myReplaceUsage;
private String myIdentifier;
public AddMethodQuickFix(String identifier, PyClassType qualifierType) {
public AddMethodQuickFix(String identifier, PyClassType qualifierType,
boolean replaceUsage) {
myIdentifier = identifier;
myQualifierType = qualifierType;
myReplaceUsage = replaceUsage;
}
@NotNull
@@ -62,10 +65,12 @@ public class AddMethodQuickFix implements LocalQuickFix {
PyFunctionBuilder builder = new PyFunctionBuilder(item_name);
PsiElement pe = problem_elt.getParent();
String deco_name = null; // set to non-null to add a decorator
sure(pe instanceof PyCallExpression);
PyArgumentList arglist = ((PyCallExpression)pe).getArgumentList();
sure(arglist);
final PyExpression[] args = arglist.getArguments();
PyExpression[] args = new PyExpression[0];
if (pe instanceof PyCallExpression) {
PyArgumentList arglist = ((PyCallExpression)pe).getArgumentList();
sure(arglist);
args = arglist.getArguments();
}
boolean made_instance = false;
if (call_by_class) {
if (args.length > 0) {
@@ -107,17 +112,10 @@ public class AddMethodQuickFix implements LocalQuickFix {
PyDecoratorList deco_list = generator.createFromText(LanguageLevel.getDefault(), PyDecoratorList.class, "@" + deco_name + "\ndef foo(): pass", new int[]{0, 0});
meth.addBefore(deco_list, meth.getFirstChild()); // in the very beginning
}
final PsiElement first_stmt = cls_stmt_list.getFirstChild();
if (first_stmt == cls_stmt_list.getLastChild() && first_stmt instanceof PyPassStatement) {
// replace the lone 'pass'
meth = (PyFunction) first_stmt.replace(meth);
}
else {
// add ourselves to the bottom
meth = (PyFunction) cls_stmt_list.add(meth);
}
showTemplateBuilder(meth);
meth = (PyFunction)PyUtil.addElementToStatementList(meth, cls_stmt_list);
if (myReplaceUsage)
showTemplateBuilder(meth);
}
catch (IncorrectOperationException ignored) {
// we failed. tell about this
@@ -138,7 +136,9 @@ public class AddMethodQuickFix implements LocalQuickFix {
}
);
builder.replaceElement(method.getStatementList(), PyNames.PASS);
final PyStatementList statementList = method.getStatementList();
if (statementList == null) return;
builder.replaceElement(statementList, PyNames.PASS);
builder.run();
}
@@ -0,0 +1,78 @@
package com.jetbrains.python.inspections.quickfix;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
/**
* User: ktisha
*/
public class PyMoveAttributeToInitQuickFix implements LocalQuickFix {
public PyMoveAttributeToInitQuickFix() {
}
@NotNull
public String getName() {
return PyBundle.message("QFIX.move.attribute");
}
@NonNls
@NotNull
public String getFamilyName() {
return getName();
}
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
if (!(element instanceof PyTargetExpression)) return;
final PyTargetExpression targetExpression = (PyTargetExpression)element;
final PyClass containingClass = targetExpression.getContainingClass();
final PyAssignmentStatement assignment = PsiTreeUtil.getParentOfType(element, PyAssignmentStatement.class);
if (containingClass == null || assignment == null) return;
final PsiElement copy = assignment.copy();
if (!addDefinition(copy, containingClass)) return;
removeDefinition(assignment);
}
private static boolean addDefinition(PsiElement copy, PyClass containingClass) {
PyFunction init = containingClass.findMethodByName(PyNames.INIT, false);
if (init == null) {
final PyStatementList classStatementList = containingClass.getStatementList();
init = PyElementGenerator.getInstance(containingClass.getProject()).createFromText(LanguageLevel.forElement(containingClass),
PyFunction.class,
"def __init__(self):\n\t" +
copy.getText());
PyUtil.addElementToStatementList(init, classStatementList);
return true;
}
final PyStatementList statementList = init.getStatementList();
if (statementList == null) return false;
PyUtil.addElementToStatementList(copy, statementList);
return true;
}
private static boolean removeDefinition(PyAssignmentStatement assignment) {
final PyStatementList statementList = PsiTreeUtil.getParentOfType(assignment, PyStatementList.class);
if (statementList == null) return false;
if (statementList.getStatements().length == 1) {
final PyPassStatement passStatement = PyElementGenerator.getInstance(assignment.getProject()).createPassStatement();
statementList.addBefore(passStatement, assignment);
}
assignment.delete();
return true;
}
}
@@ -1202,5 +1202,30 @@ public class PyUtil {
return element instanceof PsiWhiteSpace ? null : element;
}
public static PsiElement addElementToStatementList(@NotNull PsiElement element, @NotNull PyStatementList statementList) {
final PsiElement firstChild = statementList.getFirstChild();
if (firstChild == statementList.getLastChild() && firstChild instanceof PyPassStatement) {
element = firstChild.replace(element);
}
else {
final PyStatement[] statements = statementList.getStatements();
String name = element instanceof PsiNamedElement ? ((PsiNamedElement)element).getName() : "";
if (PyNames.INIT.equals(name) && statements.length > 0) {
final PyDocStringOwner docStringOwner = PsiTreeUtil.getParentOfType(statementList, PyDocStringOwner.class);
final PyStatement firstStatement = statements[0];
if (docStringOwner != null && firstStatement instanceof PyExpressionStatement &&
((PyExpressionStatement)firstStatement).getExpression() == docStringOwner.getDocStringExpression()) {
element = statementList.addAfter(element, firstStatement);
}
else
element = statementList.addBefore(element, firstStatement);
}
else {
element = statementList.add(element);
}
}
return element;
}
}
@@ -929,7 +929,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
return new ArrayList<PyTargetExpression>(expressions);
}
private static void collectInstanceAttributes(@NotNull PyFunction method, @NotNull final Map<String, PyTargetExpression> result) {
public static void collectInstanceAttributes(@NotNull PyFunction method, @NotNull final Map<String, PyTargetExpression> result) {
final PyParameter[] params = method.getParameterList().getParameters();
if (params.length == 0) {
return;
@@ -304,6 +304,17 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
}
}
@Override
public PyPassStatement createPassStatement() {
final PyStatementList statementList = createPassStatementList();
return (PyPassStatement)statementList.getStatements()[0];
}
private PyStatementList createPassStatementList() {
final PyFunction function = createFromText(LanguageLevel.getDefault(), PyFunction.class, "def foo():\n\tpass");
return function.getStatementList();
}
public PyExpressionStatement createDocstring(String content) {
return createFromText(LanguageLevel.getDefault(),
PyExpressionStatement.class, content + "\n");
@@ -0,0 +1,9 @@
__author__ = 'ktisha'
class A:
def __init__(self):
self.a = 1
self.b = 1
def foo(self):
self.b = 1
@@ -0,0 +1,8 @@
__author__ = 'ktisha'
class A:
def __init__(self):
self.a = 1
def foo(self):
<weak_warning descr="Instance attribute b defined outside __init__">self.b</weak_warning>= 1
@@ -0,0 +1,4 @@
__author__ = 'ktisha'
class <weak_warning descr="Class has no __init__ method">A</weak_warning>:
def foo(self):
self.b = 1
@@ -0,0 +1,9 @@
__author__ = 'ktisha'
class <weak_warning descr="Class has no __init__ method">A</weak_warning>:
def foo(self):
self.b = 1
class <weak_warning descr="Parent 'A' has no __init__ method">B</weak_warning>(A):
def __init__(self):
self.b = 2
@@ -0,0 +1,7 @@
__author__ = 'ktisha'
class A:
def __init__(self):
self._a = 1
def foo(self):
self.b = 1
@@ -0,0 +1,8 @@
__author__ = 'ktisha'
bar = 1
def foo():
global bar
print bar
foo()
@@ -0,0 +1,6 @@
__author__ = 'ktisha'
def foo():
global <weak_warning descr="Global variable 'bar' is undefined at the module level">bar</weak_warning>
print bar
foo()
@@ -0,0 +1,6 @@
__author__ = 'ktisha'
def foo():
a = 1
<weak_warning descr="Function 'foo' doesn't return anything">b = foo()</weak_warning>
@@ -0,0 +1,6 @@
__author__ = 'ktisha'
def foo(x):
return x
b = foo()
@@ -0,0 +1,6 @@
__author__ = 'ktisha'
def foo():
pass
<weak_warning descr="Function 'foo' doesn't return anything">b = foo()</weak_warning>
@@ -0,0 +1,6 @@
__author__ = 'ktisha'
def foo():
return None
<weak_warning descr="Function 'foo' doesn't return anything">b = foo()</weak_warning>
@@ -0,0 +1,6 @@
__author__ = 'ktisha'
def foo():
return 3
b = foo()
@@ -0,0 +1,15 @@
__author__ = 'ktisha'
class A:
def __init__(self):
self._a = 1
def foo(self):
self.b= 1
class B(A):
def __init__(self):
A.__init__(self)
self.b = self._a
@@ -0,0 +1,11 @@
__author__ = 'ktisha'
class A:
def __init__(self):
self._a = 1
def foo(self):
self.b= 1
print <weak_warning descr="Access to a protected member _a of a class">A()._a</weak_warning>
@@ -0,0 +1,12 @@
__author__ = 'ktisha'
class A:
def __init__(self):
self._a = 1
def foo(self):
self.b= 1
class B:
def __init__(self):
<weak_warning descr="Access to a protected member _a of a class">A()._a</weak_warning>
@@ -0,0 +1,4 @@
__author__ = 'ktisha'
class <caret>A(object):
def foo(self):
self.b = 1
@@ -0,0 +1,5 @@
__author__ = 'ktisha'
class <caret>A(object):
""" class docstring"""
def foo(self):
self.b = 1
@@ -0,0 +1,9 @@
__author__ = 'ktisha'
class <caret>A(object):
""" class docstring"""
def __init__(self):
pass
def foo(self):
self.b = 1
@@ -0,0 +1,7 @@
__author__ = 'ktisha'
class A(object):
def __init__(self):
pass
def foo(self):
self.b = 1
@@ -0,0 +1,5 @@
class A:
pass
a = A()
a.<caret><warning descr="Unresolved attribute reference 'y' for class 'A'">y</warning>()
@@ -0,0 +1,6 @@
class A:
def y(self):
pass
a = A()
a.y()
@@ -0,0 +1,9 @@
__author__ = 'ktisha'
class A:
def __init__(self):
self._a = 1
def foo(self):
self.<caret>b = 1
@@ -0,0 +1,10 @@
__author__ = 'ktisha'
class A:
def __init__(self):
self._a = 1
self.b = 1
def foo(self):
pass
@@ -0,0 +1,7 @@
__author__ = 'ktisha'
class A:
def foo(self):
self.<caret>b = 1
c = 1
@@ -0,0 +1,9 @@
__author__ = 'ktisha'
class A:
def __init__(self):
self.b = 1
def foo(self):
c = 1
@@ -0,0 +1,10 @@
__author__ = 'ktisha'
class A:
def __init__(self):
self._a = 1
def foo(self):
self.<caret>b = 1
c = 1
@@ -0,0 +1,10 @@
__author__ = 'ktisha'
class A:
def __init__(self):
self._a = 1
self.b = 1
def foo(self):
c = 1
@@ -0,0 +1,9 @@
__author__ = 'ktisha'
class A:
def __init__(self):
pass
def foo(self):
self.<caret>b = 1
@@ -0,0 +1,9 @@
__author__ = 'ktisha'
class A:
def __init__(self):
self.b = 1
def foo(self):
pass
@@ -0,0 +1,10 @@
__author__ = 'ktisha'
class A:
"""
class docstring
"""
def foo(self):
self.<caret>b = 1
@@ -0,0 +1,13 @@
__author__ = 'ktisha'
class A:
"""
class docstring
"""
def __init__(self):
self.b = 1
def foo(self):
pass
@@ -115,16 +115,6 @@ public class PyQuickFixTest extends PyTestCase {
true, true);
}
public void testAddMethodFromInstance() {
doInspectionTest("AddMethodFromInstance.py", PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.method.$0.to.class.$1", "y", "A"),
true, true);
}
public void testAddMethodFromMethod() {
doInspectionTest("AddMethodFromMethod.py", PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.method.$0.to.class.$1", "y", "A"),
true, true);
}
public void testRemoveTrailingSemicolon() {
doInspectionTest("RemoveTrailingSemicolon.py", PyTrailingSemicolonInspection.class, PyBundle.message("QFIX.remove.trailing.semicolon"),
true, true);
@@ -0,0 +1,23 @@
package com.jetbrains.python.inspections;
import com.jetbrains.python.fixtures.PyTestCase;
/**
* User: ktisha
*/
public class PyAttributeOutsideInitInspectionTest extends PyTestCase {
public void testTruePositive() {
doTest();
}
public void testTrueNegative() {
doTest();
}
private void doTest() {
myFixture.configureByFile("inspections/PyAttributeOutsideInitInspection/" + getTestName(true) + ".py");
myFixture.enableInspections(PyAttributeOutsideInitInspection.class);
myFixture.checkHighlighting(false, false, true);
}
}
@@ -0,0 +1,27 @@
package com.jetbrains.python.inspections;
import com.jetbrains.python.fixtures.PyTestCase;
/**
* User: ktisha
*/
public class PyClassHasNoInitInspectionTest extends PyTestCase {
public void testClass() {
doTest();
}
public void testTrueNegative() {
doTest();
}
public void testParentClass() {
doTest();
}
private void doTest() {
myFixture.configureByFile("inspections/PyClassHasNoInitInspection/" + getTestName(true) + ".py");
myFixture.enableInspections(PyClassHasNoInitInspection.class);
myFixture.checkHighlighting(false, false, true);
}
}
@@ -0,0 +1,23 @@
package com.jetbrains.python.inspections;
import com.jetbrains.python.fixtures.PyTestCase;
/**
* User: ktisha
*/
public class PyGlobalUndefinedInspectionTest extends PyTestCase {
public void testTruePositive() {
doTest();
}
public void testTrueNegative() {
doTest();
}
private void doTest() {
myFixture.configureByFile("inspections/PyGlobalUndefinedInspection/" + getTestName(true) + ".py");
myFixture.enableInspections(PyGlobalUndefinedInspection.class);
myFixture.checkHighlighting(false, false, true);
}
}
@@ -0,0 +1,35 @@
package com.jetbrains.python.inspections;
import com.jetbrains.python.fixtures.PyTestCase;
/**
* User: ktisha
*/
public class PyNoneFunctionAssignmentInspectionTest extends PyTestCase {
public void testPass() {
doTest();
}
public void testReturnNone() {
doTest();
}
public void testNoReturn() {
doTest();
}
public void testTrueNegative() {
doTest();
}
public void testNoType() {
doTest();
}
private void doTest() {
myFixture.configureByFile("inspections/PyNoneFunctionAssignmentInspection/" + getTestName(true) + ".py");
myFixture.enableInspections(PyNoneFunctionAssignmentInspection.class);
myFixture.checkHighlighting(false, false, true);
}
}
@@ -0,0 +1,27 @@
package com.jetbrains.python.inspections;
import com.jetbrains.python.fixtures.PyTestCase;
/**
* User: ktisha
*/
public class PyProtectedMemberInspectionTest extends PyTestCase {
public void testTruePositive() {
doTest();
}
public void testTruePositiveInClass() {
doTest();
}
public void testTrueNegative() {
doTest();
}
private void doTest() {
myFixture.configureByFile("inspections/PyProtectedMemberInspection/" + getTestName(true) + ".py");
myFixture.enableInspections(PyProtectedMemberInspection.class);
myFixture.checkHighlighting(false, false, true);
}
}
@@ -0,0 +1,32 @@
package com.jetbrains.python.quickFixes;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.inspections.PyClassHasNoInitInspection;
import com.jetbrains.python.inspections.PyUnresolvedReferencesInspection;
/**
* User: ktisha
*/
public class AddMethodQuickFixTest extends PyQuickFixTestCase {
public void testAddInit() {
doInspectionTest(PyClassHasNoInitInspection.class, PyBundle.message("QFIX.NAME.add.method.$0.to.class.$1", "__init__", "A"));
}
public void testAddInitAfterDocstring() {
doInspectionTest(PyClassHasNoInitInspection.class, PyBundle.message("QFIX.NAME.add.method.$0.to.class.$1", "__init__", "A"));
}
public void testAddMethodReplacePass() {
doInspectionTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.method.$0.to.class.$1", "y", "A"));
}
public void testAddMethodFromInstance() {
doInspectionTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.method.$0.to.class.$1", "y", "A"));
}
public void testAddMethodFromMethod() {
doInspectionTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.method.$0.to.class.$1", "y", "A"));
}
}
@@ -0,0 +1,33 @@
package com.jetbrains.python.quickFixes;
import com.intellij.testFramework.TestDataPath;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.inspections.PyAttributeOutsideInitInspection;
/**
* User: ktisha
*/
@TestDataPath("$CONTENT_ROOT/../testData/quickFixes/PyMoveAttributeToInitQuickFixTest")
public class PyMoveAttributeToInitQuickFixTest extends PyQuickFixTestCase {
public void testMoveToInit() {
doInspectionTest(PyAttributeOutsideInitInspection.class, PyBundle.message("QFIX.move.attribute"));
}
public void testCreateInit() {
doInspectionTest(PyAttributeOutsideInitInspection.class, PyBundle.message("QFIX.move.attribute"));
}
public void testAddPass() {
doInspectionTest(PyAttributeOutsideInitInspection.class, PyBundle.message("QFIX.move.attribute"));
}
public void testRemovePass() {
doInspectionTest(PyAttributeOutsideInitInspection.class, PyBundle.message("QFIX.move.attribute"));
}
public void testSkipDocstring() {
doInspectionTest(PyAttributeOutsideInitInspection.class, PyBundle.message("QFIX.move.attribute"));
}
}
@@ -0,0 +1,28 @@
package com.jetbrains.python.quickFixes;
import com.intellij.codeInsight.intention.IntentionAction;
import com.jetbrains.python.PythonTestUtil;
import com.jetbrains.python.fixtures.PyTestCase;
import org.jetbrains.annotations.NonNls;
/**
* User: ktisha
*/
public abstract class PyQuickFixTestCase extends PyTestCase {
@Override
@NonNls
protected String getTestDataPath() {
return PythonTestUtil.getTestDataPath() + "/quickFixes/" + getClass().getSimpleName();
}
protected void doInspectionTest(final Class inspectionClass, final String hint) {
final String testFileName = getTestName(true);
myFixture.enableInspections(inspectionClass);
myFixture.configureByFile(testFileName + ".py");
myFixture.checkHighlighting(true, false, false);
final IntentionAction intentionAction = myFixture.findSingleIntention(hint);
assertNotNull(intentionAction);
myFixture.launchAction(intentionAction);
myFixture.checkResultByFile(testFileName + "_after.py", true);
}
}
@@ -1,11 +1,9 @@
package com.jetbrains.python.refactoring;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.LightPlatformTestCase;
import com.intellij.util.Consumer;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.PyExpression;
@@ -63,9 +61,8 @@ public abstract class PyIntroduceTestCase extends PyTestCase {
String name = getTestName(true);
myFixture.configureByFile(name + ".py");
final boolean enabled = myFixture.getEditor().getSettings().isVariableInplaceRenameEnabled();
TemplateManagerImpl templateManager = (TemplateManagerImpl)TemplateManager.getInstance(LightPlatformTestCase.getProject());
try {
templateManager.setTemplateTesting(true);
TemplateManagerImpl.setTemplateTesting(myFixture.getProject(), getTestRootDisposable());
myFixture.getEditor().getSettings().setVariableInplaceRenameEnabled(true);
IntroduceHandler handler = createHandler();
@@ -83,7 +80,6 @@ public abstract class PyIntroduceTestCase extends PyTestCase {
}
finally {
myFixture.getEditor().getSettings().setVariableInplaceRenameEnabled(enabled);
templateManager.setTemplateTesting(false);
}
}
}