Merge branch 'python-fixes'

Conflicts:
	python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java
This commit is contained in:
Andrey Vlasovskikh
2012-08-13 23:10:47 +04:00
9 changed files with 60 additions and 53 deletions
@@ -328,6 +328,7 @@ INSP.empty.docstring=Empty docstring
# PyStatementEffectInspection
INSP.NAME.statement.effect=Statement has no effect
INSP.NAME.statement.message=Statement seems to have no effect
# PySimplifyBooleanCheckInspection
INSP.NAME.check.can.be.simplified=Boolean variable check can be simplified
@@ -97,7 +97,7 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
return describeDecorators(cls, LSame2, ", ", LSame1).add(describeClass(cls, LSame2, false, false)).toString() + "\n" + summary;
}
else if (element instanceof PyTargetExpression || element instanceof PyNamedParameter) {
return describeExpression((PyExpression)element, originalElement);
return describeExpression((PyExpression)element);
}
return null;
}
@@ -126,7 +126,7 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
}
@Nullable
private static String describeExpression(PyExpression expr, PsiElement originalElement) {
private static String describeExpression(PyExpression expr) {
final String name = expr.getName();
if (name != null) {
StringBuilder result = new StringBuilder((expr instanceof PyNamedParameter) ? "parameter" : "variable");
@@ -138,9 +138,7 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
result.append(String.format(" \"%s\"", function.getName()));
}
}
if (originalElement instanceof PyExpression && originalElement.isValid()) {
result.append("\n").append(describeExpressionType((PyExpression)originalElement));
}
result.append("\n").append(describeExpressionType(expr));
return result.toString();
}
return null;
@@ -62,10 +62,15 @@ public class PyStatementEffectInspection extends PyInspection {
return;
}
}
if (checkStringLiteral(expression))
if (checkStringLiteral(expression)) {
return;
registerProblem(expression, "Statement seems to have no effect",
new StatementEffectIntroduceVariableQuickFix());
}
if (expression instanceof PyReferenceExpression && ((PyReferenceExpression)expression).getQualifier() == null) {
registerProblem(expression, PyBundle.message("INSP.NAME.statement.message"));
}
else {
registerProblem(expression, PyBundle.message("INSP.NAME.statement.message"), new StatementEffectIntroduceVariableQuickFix());
}
}
private boolean checkStringLiteral(PyExpression expression) {
@@ -266,8 +266,7 @@ public class PyUnusedLocalInspectionVisitor extends PyInspectionVisitor {
if (paramList != null && paramList.getParent() instanceof PyFunction) {
final PyFunction func = (PyFunction) paramList.getParent();
containingClass = func.getContainingClass();
final String funcName = func.getName();
if (PyNames.INIT.equals(funcName) && containingClass != null) {
if (PyNames.INIT.equals(func.getName()) && containingClass != null) {
if (!namedParameter.isKeywordContainer() && !namedParameter.isPositionalContainer()) {
mayBeField = true;
}
@@ -276,9 +275,6 @@ public class PyUnusedLocalInspectionVisitor extends PyInspectionVisitor {
continue;
}
if (func.asMethod() != null) {
if (funcName != null && isSpecialName(funcName) && !PyNames.INIT.equals(funcName) && !PyNames.NEW.equals(funcName)) {
continue;
}
Boolean isEmpty = emptyFunctions.get(func);
if (isEmpty == null) {
isEmpty = isEmptyFunction(func);
@@ -313,11 +309,6 @@ public class PyUnusedLocalInspectionVisitor extends PyInspectionVisitor {
}
}
private static boolean isSpecialName(@NotNull String name) {
final String dunder = "__";
return name.startsWith(dunder) && name.endsWith(dunder) && name.length() > (dunder.length() * 2);
}
private boolean isRangeIteration(PyForStatement forStatement) {
final PyExpression source = forStatement.getForPart().getSource();
if (!(source instanceof PyCallExpression)) {
@@ -178,9 +178,16 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
final PyType exprType = expression.getType(context);
if (exprType instanceof PyClassType) {
final PyClass cls = ((PyClassType)exprType).getPyClass();
final PyFunction enter = cls.findMethodByName(PyNames.ENTER, true);
if (enter != null) {
return enter.getReturnType(context, null);
if (cls != null) {
final PyFunction enter = cls.findMethodByName(PyNames.ENTER, true);
if (enter != null) {
final PyType enterType = enter.getReturnType(context, null);
if (enterType != null) {
return enterType;
}
// Guess the return type of __enter__
return PyUnionType.createWeakType(exprType);
}
}
}
}
@@ -275,7 +282,7 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
type = ((PyCollectionType)sourceType).getElementType(context);
if (sourceType instanceof PyClassType) {
final PyClass cls = ((PyClassType)sourceType).getPyClass();
if (type instanceof PyTupleType && PyABCUtil.isSubclass(cls, PyNames.MAPPING)) {
if (cls != null && type instanceof PyTupleType && PyABCUtil.isSubclass(cls, PyNames.MAPPING)) {
final PyTupleType mappingType = (PyTupleType)type;
if (mappingType.getElementCount() == 2) {
return mappingType.getElementType(0);
@@ -285,30 +292,32 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
}
else if (sourceType instanceof PyClassType) {
final PyClass pyClass = ((PyClassType)sourceType).getPyClass();
for (PyTypeProvider provider: Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
final PyType iterType = provider.getIterationType(pyClass);
if (iterType != null) {
type = iterType;
break;
}
}
if (PyABCUtil.isSubclass(pyClass, PyNames.ITERATOR)) {
final PyFunction iter = pyClass.findMethodByName(PyNames.ITER, true);
PyType iterMethodType = null;
if (iter != null) {
iterMethodType = getContextSensitiveType(iter, context, source);
}
if (iterMethodType instanceof PyCollectionType) {
final PyCollectionType collectionType = (PyCollectionType)iterMethodType;
type = collectionType.getElementType(context);
}
if (type == null) {
PyFunction next = pyClass.findMethodByName(PyNames.NEXT, true);
if (next == null) {
next = pyClass.findMethodByName(PyNames.DUNDER_NEXT, true);
if (pyClass != null) {
for (PyTypeProvider provider: Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
final PyType iterType = provider.getIterationType(pyClass);
if (iterType != null) {
type = iterType;
break;
}
if (next != null) {
type = getContextSensitiveType(next, context, source);
}
if (PyABCUtil.isSubclass(pyClass, PyNames.ITERATOR)) {
final PyFunction iter = pyClass.findMethodByName(PyNames.ITER, true);
PyType iterMethodType = null;
if (iter != null) {
iterMethodType = getContextSensitiveType(iter, context, source);
}
if (iterMethodType instanceof PyCollectionType) {
final PyCollectionType collectionType = (PyCollectionType)iterMethodType;
type = collectionType.getElementType(context);
}
if (type == null) {
PyFunction next = pyClass.findMethodByName(PyNames.NEXT, true);
if (next == null) {
next = pyClass.findMethodByName(PyNames.DUNDER_NEXT, true);
}
if (next != null) {
type = getContextSensitiveType(next, context, source);
}
}
}
}
@@ -437,7 +446,10 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
return stub.getInitializer();
}
else if (initializerType == PyTargetExpressionStub.InitializerType.Custom) {
return stub.getCustomStub(CustomTargetExpressionStub.class).getCalleeName();
final CustomTargetExpressionStub customStub = stub.getCustomStub(CustomTargetExpressionStub.class);
if (customStub != null) {
return customStub.getCalleeName();
}
}
return null;
}
@@ -39,7 +39,7 @@ public class PyModuleType implements PyType { // Modules don't descend from obje
@NotNull private final PyFile myModule;
@Nullable private final PyImportedModule myImportedModule;
protected static ImmutableSet<String> ourPossibleFields = ImmutableSet.of("__name__", "__file__", "__path__", "__doc__", "__dict__");
protected static ImmutableSet<String> ourPossibleFields = ImmutableSet.of("__name__", "__file__", "__path__", "__doc__", "__dict__", "__package__");
public PyModuleType(@NotNull PyFile source) {
this(source, null);
@@ -0,0 +1 @@
__package__ #pass
@@ -286,9 +286,3 @@ class C:
# PY-7126
def test_unused_empty_function(<weak_warning descr="Parameter 'x' value is not used">x</weak_warning>):
pass
# PY-7178
class C(object):
def __getattr__(self, name): # pass
return 42
@@ -165,6 +165,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase {
doTest();
}
// PY-7043
public void testDunderPackage() {
doTest();
}
private void doTest() {
myFixture.configureByFile(TEST_DIRECTORY + getTestName(true) + ".py");
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);