mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-28782 Fix remove assignment expression target inspection for multiple targets
(cherry picked from commit 2a8862d459955a23def7941229007e26d076c54e) IJ-CR-4054 GitOrigin-RevId: 0068c0195a89e2272e9c632acc5494ea7ff0b120
This commit is contained in:
committed by
intellij-monorepo-bot
parent
017d156ddf
commit
3b99571638
+15
-6
@@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -37,11 +38,19 @@ public class PyRemoveAssignmentStatementTargetQuickFix implements LocalQuickFix,
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
final PyAssignmentStatement assignmentStatement = PsiTreeUtil.getParentOfType(element, PyAssignmentStatement.class);
|
||||
if (assignmentStatement == null) return;
|
||||
final PyExpression expression = assignmentStatement.getAssignedValue();
|
||||
if (expression == null) return;
|
||||
final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
|
||||
PyExpressionStatement statement = elementGenerator.createFromText(LanguageLevel.forElement(expression), PyExpressionStatement.class,
|
||||
expression.getText());
|
||||
assignmentStatement.replace(statement);
|
||||
if (assignmentStatement.getRawTargets().length == 1) {
|
||||
final PyExpression expression = assignmentStatement.getAssignedValue();
|
||||
if (expression == null) return;
|
||||
final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
|
||||
PyExpressionStatement statement = elementGenerator.createFromText(LanguageLevel.forElement(expression), PyExpressionStatement.class,
|
||||
expression.getText());
|
||||
assignmentStatement.replace(statement);
|
||||
}
|
||||
else {
|
||||
PsiElement possibleNextEq = PsiTreeUtil.nextVisibleLeaf(element);
|
||||
if (possibleNextEq == null) return;
|
||||
assert possibleNextEq.getNode().getElementType() == PyTokenTypes.EQ;
|
||||
element.getParent().deleteChildRange(element, possibleNextEq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-3
@@ -12,6 +12,7 @@ import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
@@ -422,14 +423,18 @@ public final class PyUnusedLocalInspectionVisitor extends PyInspectionVisitor {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: consider assignmentStatement.getRawTargets().length > 1 in PY-28782
|
||||
final PyAssignmentStatement assignmentStatement = PsiTreeUtil.getParentOfType(element, PyAssignmentStatement.class);
|
||||
if (assignmentStatement != null && assignmentStatement.getRawTargets().length == 1 &&
|
||||
PsiTreeUtil.isAncestor(assignmentStatement.getLeftHandSideExpression(), element, false)) {
|
||||
if (assignmentStatement != null && !PsiTreeUtil.isAncestor(assignmentStatement.getAssignedValue(), element, false)) {
|
||||
if (assignmentStatement.getLeftHandSideExpression() == element) {
|
||||
// Single assignment target (unused = value)
|
||||
registerWarning(element, warningMsg, new PyRemoveAssignmentStatementTargetQuickFix(), new PyRemoveStatementQuickFix());
|
||||
}
|
||||
else if (ArrayUtil.contains(element, assignmentStatement.getRawTargets())) {
|
||||
// Chained assignment target (used = unused = value)
|
||||
registerWarning(element, warningMsg, new PyRemoveAssignmentStatementTargetQuickFix());
|
||||
}
|
||||
else {
|
||||
// Unpacking (used, unused = value)
|
||||
registerWarning(element, warningMsg, new ReplaceWithWildCard());
|
||||
}
|
||||
continue;
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
def f():
|
||||
a<caret> = b = 0
|
||||
return b
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
def f():
|
||||
<caret>b = 0
|
||||
return b
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
def f():
|
||||
a = b<caret> = 0
|
||||
return a
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
def f():
|
||||
a = 0
|
||||
return a
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
def f():
|
||||
a = <caret>unused, b = 42, 42
|
||||
return a, b
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
def f():
|
||||
a = _, b = 42, 42
|
||||
return a, b
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
def f():
|
||||
a = b, <caret>unused = 42, 42
|
||||
return a, b
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
def f():
|
||||
a = b, _ = 42, 42
|
||||
return a, b
|
||||
@@ -15,11 +15,13 @@
|
||||
*/
|
||||
package com.jetbrains.python.quickFixes;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.PyQuickFixTestCase;
|
||||
import com.jetbrains.python.inspections.unusedLocal.PyUnusedLocalInspection;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@TestDataPath("$CONTENT_ROOT/../testData/quickFixes/PyRemoveUnusedLocalQuickFixTest/")
|
||||
public class PyRemoveUnusedLocalQuickFixTest extends PyQuickFixTestCase {
|
||||
@@ -66,6 +68,47 @@ public class PyRemoveUnusedLocalQuickFixTest extends PyQuickFixTestCase {
|
||||
});
|
||||
}
|
||||
|
||||
// PY-28782
|
||||
public void testRemoveChainedAssignmentStatementFirstTarget() {
|
||||
runWithLanguageLevel(LanguageLevel.getLatest(), () -> {
|
||||
doQuickFixTest(PyUnusedLocalInspection.class, PyPsiBundle.message("QFIX.NAME.remove.target.expr"));
|
||||
});
|
||||
}
|
||||
|
||||
// PY-28782
|
||||
public void testRemoveChainedAssignmentStatementSecondTarget() {
|
||||
runWithLanguageLevel(LanguageLevel.getLatest(), () -> {
|
||||
doQuickFixTest(PyUnusedLocalInspection.class, PyPsiBundle.message("QFIX.NAME.remove.target.expr"));
|
||||
});
|
||||
}
|
||||
|
||||
// PY-28782
|
||||
public void testRemoveChainedAssignmentStatementUnpackingFirstTarget() {
|
||||
runWithLanguageLevel(LanguageLevel.getLatest(), () -> {
|
||||
doTestNotIgnoreTupleUnpacking(PyPsiBundle.message("INSP.unused.locals.replace.with.wildcard"));
|
||||
});
|
||||
}
|
||||
|
||||
// PY-28782
|
||||
public void testRemoveChainedAssignmentStatementUnpackingSecondTarget() {
|
||||
runWithLanguageLevel(LanguageLevel.getLatest(), () -> {
|
||||
doTestNotIgnoreTupleUnpacking(PyPsiBundle.message("INSP.unused.locals.replace.with.wildcard"));
|
||||
});
|
||||
}
|
||||
|
||||
private void doTestNotIgnoreTupleUnpacking(@NotNull String hint) {
|
||||
final String testFileName = getTestName(true);
|
||||
final PyUnusedLocalInspection inspection = new PyUnusedLocalInspection();
|
||||
inspection.ignoreTupleUnpacking = false;
|
||||
myFixture.configureByFile(testFileName + ".py");
|
||||
myFixture.enableInspections(inspection);
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
final IntentionAction intentionAction = myFixture.findSingleIntention(hint);
|
||||
assertNotNull(intentionAction);
|
||||
myFixture.launchAction(intentionAction);
|
||||
myFixture.checkResultByFile(testFileName + "_after.py", true);
|
||||
}
|
||||
|
||||
// PY-32037
|
||||
public void testGeneratorIterator() {
|
||||
doQuickFixTest(PyUnusedLocalInspection.class, PyPsiBundle.message("INSP.unused.locals.replace.with.wildcard"));
|
||||
|
||||
Reference in New Issue
Block a user