diff --git a/python/src/com/jetbrains/python/PyNames.java b/python/src/com/jetbrains/python/PyNames.java index e66542c2ba48..9de1a569355f 100644 --- a/python/src/com/jetbrains/python/PyNames.java +++ b/python/src/com/jetbrains/python/PyNames.java @@ -37,6 +37,7 @@ public class PyNames { @NonNls public static final String ALL = "__all__"; @NonNls public static final String SLOTS = "__slots__"; + @NonNls public static final String DEBUG = "__debug__"; @NonNls private static final Set _UnderscoredAttributes = new HashSet(); static { diff --git a/python/src/com/jetbrains/python/psi/PyElementVisitor.java b/python/src/com/jetbrains/python/psi/PyElementVisitor.java index 2170c1175b98..e934476fae4c 100644 --- a/python/src/com/jetbrains/python/psi/PyElementVisitor.java +++ b/python/src/com/jetbrains/python/psi/PyElementVisitor.java @@ -237,4 +237,12 @@ public class PyElementVisitor extends PsiElementVisitor { public void visitPyAssertStatement(final PyAssertStatement node) { visitPyElement(node); } + + public void visitPyNoneLiteralExpression(final PyNoneLiteralExpression node) { + visitPyElement(node); + } + + public void visitPyBoolLiteralExpression(final PyBoolLiteralExpression node) { + visitPyElement(node); + } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyBoolLiteralExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyBoolLiteralExpressionImpl.java index 96f16fc53b13..af6dd0090f52 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyBoolLiteralExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyBoolLiteralExpressionImpl.java @@ -2,6 +2,7 @@ package com.jetbrains.python.psi.impl; import com.intellij.lang.ASTNode; import com.jetbrains.python.psi.PyBoolLiteralExpression; +import com.jetbrains.python.psi.PyElementVisitor; import com.jetbrains.python.psi.types.PyType; import com.jetbrains.python.psi.types.TypeEvalContext; import org.jetbrains.annotations.NotNull; @@ -22,4 +23,9 @@ public class PyBoolLiteralExpressionImpl extends PyElementImpl implements PyBool public boolean getValue() { return "True".equals(getText()); } + + @Override + protected void acceptPyVisitor(PyElementVisitor pyVisitor) { + pyVisitor.visitPyBoolLiteralExpression(this); + } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyNoneLiteralExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyNoneLiteralExpressionImpl.java index 21f19d256b47..530a25ed7f6e 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyNoneLiteralExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyNoneLiteralExpressionImpl.java @@ -1,6 +1,7 @@ package com.jetbrains.python.psi.impl; import com.intellij.lang.ASTNode; +import com.jetbrains.python.psi.PyElementVisitor; import com.jetbrains.python.psi.PyNoneLiteralExpression; import com.jetbrains.python.psi.types.PyNoneType; import com.jetbrains.python.psi.types.PyType; @@ -18,4 +19,9 @@ public class PyNoneLiteralExpressionImpl extends PyElementImpl implements PyNone public PyType getType(@NotNull TypeEvalContext context) { return PyNoneType.INSTANCE; } + + @Override + protected void acceptPyVisitor(PyElementVisitor pyVisitor) { + pyVisitor.visitPyNoneLiteralExpression(this); + } } diff --git a/python/src/com/jetbrains/python/validation/AssignTargetAnnotator.java b/python/src/com/jetbrains/python/validation/AssignTargetAnnotator.java index 5539d1891ee0..464b3ccb6b40 100644 --- a/python/src/com/jetbrains/python/validation/AssignTargetAnnotator.java +++ b/python/src/com/jetbrains/python/validation/AssignTargetAnnotator.java @@ -66,7 +66,7 @@ public class AssignTargetAnnotator extends PyAnnotator { @Override public void visitPyReferenceExpression(final PyReferenceExpression node) { String referencedName = node.getReferencedName(); - if (referencedName != null && referencedName.equals(PyNames.NONE)) { + if (PyNames.NONE.equals(referencedName)) { getHolder().createErrorAnnotation(node, (_op == Operation.Delete) ? DELETING_NONE : ASSIGNMENT_TO_NONE); } } @@ -74,12 +74,20 @@ public class AssignTargetAnnotator extends PyAnnotator { @Override public void visitPyTargetExpression(final PyTargetExpression node) { String targetName = node.getName(); - if (targetName != null && targetName.equals(PyNames.NONE)) { + if (PyNames.NONE.equals(targetName)) { final VirtualFile vfile = node.getContainingFile().getVirtualFile(); if (vfile != null && !vfile.getUrl().contains("/" + PythonSdkType.SKELETON_DIR_NAME + "/")){ getHolder().createErrorAnnotation(node, (_op == Operation.Delete) ? DELETING_NONE : ASSIGNMENT_TO_NONE); } } + if (PyNames.DEBUG.equals(targetName)) { + if (LanguageLevel.forElement(node).isPy3K()) { + getHolder().createErrorAnnotation(node, "assignment to keyword"); + } + else { + getHolder().createErrorAnnotation(node, "cannot assign to __debug__"); + } + } } @Override @@ -182,5 +190,15 @@ public class AssignTargetAnnotator extends PyAnnotator { public void visitPyLambdaExpression(final PyLambdaExpression node) { getHolder().createErrorAnnotation(node, message("ANN.cant.assign.to.lambda")); } + + @Override + public void visitPyNoneLiteralExpression(PyNoneLiteralExpression node) { + getHolder().createErrorAnnotation(node, "assignment to keyword"); + } + + @Override + public void visitPyBoolLiteralExpression(PyBoolLiteralExpression node) { + getHolder().createErrorAnnotation(node, "assignment to keyword"); + } } } diff --git a/python/testData/highlighting/assignmentTargets3K.py b/python/testData/highlighting/assignmentTargets3K.py index d2985f25fabc..8ec4a1de7e82 100644 --- a/python/testData/highlighting/assignmentTargets3K.py +++ b/python/testData/highlighting/assignmentTargets3K.py @@ -5,3 +5,7 @@ for a, *b in [(1, 2, 3), (4, 5, 6, 7)]: a, b, c = seq[0], seq[1:-1], seq[-1] a, *b, c = seq [a, *b, c] = seq +True = 2 +False = 1 +None = 0 +__debug__ = -1