mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-3569 Inspection to warn if a loop variable is assigned inside the loop
This commit is contained in:
committed by
Ilya.Kazakevich
parent
d912f2d8bf
commit
14bdb823c0
@@ -1,13 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<span style="font-family: verdana,serif;">
|
||||
This inspection checks for cases when loop variable is redeclared inside of loop.
|
||||
</span>
|
||||
<pre style="font-family: monospace">
|
||||
for i in xrange(5):
|
||||
for i in xrange(20, 25):
|
||||
print("Inner", i)
|
||||
print("Outer", i)
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<html>
|
||||
<body>
|
||||
<span style="font-family: verdana,serif;">
|
||||
This inspection checks for cases when loop variable is redeclared inside of loop:
|
||||
</span>
|
||||
<pre style="font-family: monospace">
|
||||
for i in xrange(5):
|
||||
for i in xrange(20, 25):
|
||||
print("Inner", i)
|
||||
print("Outer", i)
|
||||
</pre>
|
||||
<span style="font-family: verdana,serif;">
|
||||
It also warns you if variable declared in <code>with</code> statement is redeclared inside of statement body:
|
||||
</span>
|
||||
<pre style="font-family: monospace">
|
||||
with open("file") as f:
|
||||
f.read()
|
||||
f = open("another file")
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -329,7 +329,7 @@
|
||||
<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="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyPep8NamingInspection"/>
|
||||
<localInspection language="Python" shortName="PyAssignmentToForLoopParameterInspection" displayName="Assignment to 'for' loop parameter" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyAssignmentToForLoopParameterInspection"/>
|
||||
<localInspection language="Python" shortName="PyAssignmentToLoopOrWithParameterInspection" displayName="Assignment to 'for' loop or 'with' statement parameter" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyAssignmentToLoopOrWithParameterInspection"/>
|
||||
|
||||
<liveTemplateContext implementation="com.jetbrains.python.codeInsight.liveTemplates.PythonTemplateContextType"/>
|
||||
<liveTemplateMacro implementation="com.jetbrains.python.codeInsight.liveTemplates.CollectionElementNameMacro"/>
|
||||
|
||||
@@ -511,8 +511,8 @@ INSP.none.function.assignment=Function ''{0}'' doesn''t return anything
|
||||
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
|
||||
|
||||
#PyAssignmentToForLoopParameterInspection
|
||||
INSP.NAME.assignment.to.for.loop.parameter.display.name=Assignment to 'for' loop parameter
|
||||
#PyAssignmentToLoopOrWithParameterInspection
|
||||
INSP.NAME.assignment.to.loop.or.with.parameter.display.name=Assignment to 'for' loop or 'with' statement parameter
|
||||
|
||||
# Refactoring
|
||||
# introduce
|
||||
|
||||
+13
-11
@@ -19,10 +19,11 @@ import com.intellij.codeInspection.LocalInspectionToolSession;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.psi.PyForPart;
|
||||
import com.jetbrains.python.psi.PyTargetExpression;
|
||||
import com.jetbrains.python.psi.PyWithStatement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -34,12 +35,18 @@ import org.jetbrains.annotations.Nullable;
|
||||
* for i in range(1, 10):
|
||||
* i = "new value"
|
||||
* </pre>
|
||||
* and
|
||||
* <pre>
|
||||
* with open("file") as f:
|
||||
* f.read()
|
||||
* f = open("another file")
|
||||
* </pre>
|
||||
*
|
||||
* @author link
|
||||
*/
|
||||
public class PyAssignmentToForLoopParameterInspection extends PyInspection {
|
||||
public class PyAssignmentToLoopOrWithParameterInspection extends PyInspection {
|
||||
|
||||
private static final String MESSAGE = PyBundle.message("INSP.NAME.assignment.to.for.loop.parameter.display.name");
|
||||
private static final String MESSAGE = PyBundle.message("INSP.NAME.assignment.to.loop.or.with.parameter.display.name");
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -73,14 +80,9 @@ public class PyAssignmentToForLoopParameterInspection extends PyInspection {
|
||||
return; //We are checking first time declaration
|
||||
}
|
||||
|
||||
//Find "for" between predecessors until we tree root
|
||||
PsiElement element = variableFirstTimeDeclaration;
|
||||
while (!(element instanceof PsiFile) && element != null) {
|
||||
if (element instanceof PyForPart) {
|
||||
registerProblem(node, MESSAGE);
|
||||
return;
|
||||
}
|
||||
element = element.getParent();
|
||||
//Check if variable declared in "for" or "with" statement
|
||||
if (PsiTreeUtil.getNonStrictParentOfType(variableFirstTimeDeclaration, PyForPart.class, PyWithStatement.class) != null) {
|
||||
registerProblem(node, MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
for i in range(1, 2):
|
||||
print(i)
|
||||
<warning descr="Assignment to 'for' loop parameter">i</warning> = 12
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
for i in [1, 2, 3]:
|
||||
print(i)
|
||||
(<warning descr="Assignment to 'for' loop parameter">i</warning>, f) = (1, 2)
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
for (k, v) in {"K": "V"}.items():
|
||||
print(k)
|
||||
<warning descr="Assignment to 'for' loop parameter">k</warning> = "12"
|
||||
@@ -1,4 +0,0 @@
|
||||
for i in range(5):
|
||||
for <warning descr="Assignment to 'for' loop parameter">i</warning> in range(20, 25):
|
||||
print("Inner", i)
|
||||
print("Outer", i)
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
for i in range(1, 2):
|
||||
print(i)
|
||||
<warning descr="Assignment to 'for' loop or 'with' statement parameter">i</warning> = 12
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
for i in [1, 2, 3]:
|
||||
print(i)
|
||||
(<warning descr="Assignment to 'for' loop or 'with' statement parameter">i</warning>, f) = (1, 2)
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
for (k, v) in {"K": "V"}.items():
|
||||
print(k)
|
||||
<warning descr="Assignment to 'for' loop or 'with' statement parameter">k</warning> = "12"
|
||||
@@ -0,0 +1,4 @@
|
||||
for i in range(5):
|
||||
for <warning descr="Assignment to 'for' loop or 'with' statement parameter">i</warning> in range(20, 25):
|
||||
print("Inner", i)
|
||||
print("Outer", i)
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
with open("file") as f:
|
||||
f.read()
|
||||
<warning descr="Assignment to 'for' loop or 'with' statement parameter">f</warning> = open("another file")
|
||||
+5
-2
@@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* @author link
|
||||
*/
|
||||
public class PyAssignmentToForLoopParameterInspectionTest extends PyInspectionTestCase {
|
||||
public class PyAssignmentToLoopOrWithParameterInspectionTest extends PyInspectionTestCase {
|
||||
|
||||
public void testGood() {
|
||||
doTest();
|
||||
@@ -42,12 +42,15 @@ public class PyAssignmentToForLoopParameterInspectionTest extends PyInspectionTe
|
||||
public void testTwoLoops() {
|
||||
doTest();
|
||||
}
|
||||
public void testWithStatement() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Class<? extends PyInspection> getInspectionClass() {
|
||||
return PyAssignmentToForLoopParameterInspection.class;
|
||||
return PyAssignmentToLoopOrWithParameterInspection.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
Reference in New Issue
Block a user