mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-29894 Fix Python quick fixes for PSI consistency
This commit is contained in:
+3
@@ -132,6 +132,9 @@ public class PyConvertTripleQuotedStringIntention extends PyBaseIntentionAction
|
||||
parent instanceof PyArgumentList && ArrayUtil.getFirstElement(((PyArgumentList)parent).getArguments()) == pyString)) {
|
||||
expression = ((PyParenthesizedExpression)expression).getContainedExpression();
|
||||
}
|
||||
if (expression instanceof PyStringLiteralExpression && ((PyStringLiteralExpression)expression).isDocString()) {
|
||||
expression = elementGenerator.createStringLiteralAlreadyEscaped(result.toString());
|
||||
}
|
||||
if (expression != null) {
|
||||
pyString.replace(expression);
|
||||
}
|
||||
|
||||
+54
-1
@@ -19,6 +19,7 @@ import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.psi.PyBinaryExpression;
|
||||
@@ -28,6 +29,8 @@ import com.jetbrains.python.psi.PyExpression;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.assertNotNull;
|
||||
import static com.jetbrains.python.psi.PyUtil.as;
|
||||
|
||||
@@ -103,10 +106,60 @@ public class ChainedComparisonsQuickFix implements LocalQuickFix {
|
||||
}
|
||||
}
|
||||
final PyBinaryExpression binaryExpression = elementGenerator.createBinaryExpression(operator, newLeftExpression, newRightExpression);
|
||||
leftExpression.replace(binaryExpression);
|
||||
leftExpression.replace(makePsiConsistentBinaryExpression(project, binaryExpression));
|
||||
rightExpression.delete();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PyExpression makePsiConsistentBinaryExpression(@NotNull Project project, @NotNull PyBinaryExpression binaryExpression) {
|
||||
final ArrayList<PyExpression> elements = new ArrayList<>();
|
||||
final ArrayList<String> operators = new ArrayList<>();
|
||||
collectExpressionsDfs(elements, operators, binaryExpression);
|
||||
PyExpression resultExpression = buildResultExpression(project, elements, operators);
|
||||
return ObjectUtils.chooseNotNull(resultExpression, binaryExpression);
|
||||
}
|
||||
|
||||
private static void collectExpressionsDfs(@NotNull ArrayList<PyExpression> elements,
|
||||
@NotNull ArrayList<String> operators,
|
||||
@NotNull PyBinaryExpression expression) {
|
||||
final PyExpression rightExpr = expression.getRightExpression();
|
||||
if (rightExpr instanceof PyBinaryExpression && isComparisonExpression(rightExpr)) {
|
||||
collectExpressionsDfs(elements, operators, (PyBinaryExpression)rightExpr);
|
||||
}
|
||||
else {
|
||||
elements.add(rightExpr);
|
||||
}
|
||||
if (expression.getPsiOperator() != null) {
|
||||
operators.add(expression.getPsiOperator().getText());
|
||||
}
|
||||
final PyExpression leftExpr = expression.getLeftExpression();
|
||||
if (leftExpr instanceof PyBinaryExpression && isComparisonExpression(leftExpr)) {
|
||||
collectExpressionsDfs(elements, operators, (PyBinaryExpression)leftExpr);
|
||||
}
|
||||
else {
|
||||
elements.add(leftExpr);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PyExpression buildResultExpression(@NotNull Project project,
|
||||
@NotNull ArrayList<PyExpression> elements,
|
||||
@NotNull ArrayList<String> operators) {
|
||||
final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
|
||||
final int size = elements.size();
|
||||
if (elements.isEmpty()) return null;
|
||||
PyExpression currentResult = elements.get(size - 1);
|
||||
int i = size - 2;
|
||||
while (i >= 0) {
|
||||
PyExpression nextElement = elements.get(i);
|
||||
String nextOperator = operators.get(i);
|
||||
currentResult = elementGenerator.createBinaryExpression(nextOperator, currentResult, nextElement);
|
||||
i--;
|
||||
}
|
||||
return currentResult;
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
private static PsiElement getLeftestOperator(@NotNull PyBinaryExpression expression) {
|
||||
PsiElement op = expression.getPsiOperator();
|
||||
|
||||
@@ -48,7 +48,10 @@ public class ConvertSetLiteralQuickFix implements LocalQuickFix {
|
||||
stringBuilder.append(expressions[i].getText());
|
||||
}
|
||||
PyStatement newElement = elementGenerator.createFromText(LanguageLevel.getDefault(), PyExpressionStatement.class, "set([" + stringBuilder.toString() + "])");
|
||||
setLiteral.replace(newElement);
|
||||
final PsiElement parent = setLiteral.getParent();
|
||||
if (parent instanceof PyExpressionStatement) {
|
||||
parent.replace(newElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -53,7 +53,8 @@ public class PyAddExceptionSuperClassQuickFix implements LocalQuickFix {
|
||||
assert expressionList != null;
|
||||
final ASTNode nameNode = ((PyClass)psiElement).getNameNode();
|
||||
assert nameNode != null;
|
||||
psiElement.addAfter(expressionList, nameNode.getPsi());
|
||||
final PsiElement oldArgList = nameNode.getPsi().getNextSibling();
|
||||
oldArgList.replace(expressionList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -50,7 +50,10 @@ public class PyConvertToNewStyleQuickFix implements LocalQuickFix {
|
||||
assert list != null;
|
||||
final ASTNode node = pyClass.getNameNode();
|
||||
assert node != null;
|
||||
pyClass.addAfter(list, node.getPsi());
|
||||
final PsiElement oldArgList = node.getPsi().getNextSibling();
|
||||
if (oldArgList instanceof PyArgumentList) {
|
||||
oldArgList.replace(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -20,8 +20,7 @@ import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.psi.PyAssignmentStatement;
|
||||
import com.jetbrains.python.psi.PyExpression;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PyRemoveAssignmentQuickFix implements LocalQuickFix {
|
||||
@@ -37,7 +36,10 @@ public class PyRemoveAssignmentQuickFix implements LocalQuickFix {
|
||||
if (assignment instanceof PyAssignmentStatement) {
|
||||
final PyExpression value = ((PyAssignmentStatement)assignment).getAssignedValue();
|
||||
if (value != null) {
|
||||
assignment.replace(value);
|
||||
PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
|
||||
final PyExpressionStatement newStatement =
|
||||
elementGenerator.createFromText(LanguageLevel.forElement(assignment), PyExpressionStatement.class, value.getText());
|
||||
assignment.replace(newStatement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,7 @@ import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.psi.PyArgumentList;
|
||||
import com.jetbrains.python.psi.PyCallExpression;
|
||||
import com.jetbrains.python.psi.PyDecorator;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PyRemoveCallQuickFix implements LocalQuickFix {
|
||||
@@ -43,6 +41,10 @@ public class PyRemoveCallQuickFix implements LocalQuickFix {
|
||||
final PyArgumentList argumentList = ((PyCallExpression)call).getArgumentList();
|
||||
assert argumentList != null;
|
||||
argumentList.delete();
|
||||
final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
|
||||
// regenerate element for Psi consistency, because it isn't PyCallExpression anymore
|
||||
final PyExpression expression = elementGenerator.createExpressionFromText(LanguageLevel.forElement(call), call.getText());
|
||||
call.replace(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-1
@@ -17,6 +17,7 @@ package com.jetbrains.python.inspections.quickfix;
|
||||
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -60,7 +61,15 @@ public class RedundantParenthesesQuickFix implements LocalQuickFix {
|
||||
else if (element instanceof PyArgumentList) {
|
||||
LOG.assertTrue(element.getParent() instanceof PyClass, "Parent type: " + element.getParent().getClass());
|
||||
LOG.assertTrue(((PyArgumentList)element).getArguments().length == 0, "Argument list: " + element.getText());
|
||||
element.delete();
|
||||
final ASTNode nameNode = PyElementGenerator.getInstance(project).createFromText(
|
||||
LanguageLevel.forElement(element), PyClass.class, "class A: pass").getNameNode();
|
||||
if (nameNode != null) {
|
||||
final PsiElement emptyArgList = nameNode.getPsi().getNextSibling();
|
||||
element.replace(emptyArgList);
|
||||
}
|
||||
else {
|
||||
element.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
'x' +<caret> u'привет'
|
||||
t = 'x' +<caret> u'привет'
|
||||
+1
-1
@@ -1 +1 @@
|
||||
u'xпривет'
|
||||
t = u'xпривет'
|
||||
@@ -1,4 +1,5 @@
|
||||
def foo():
|
||||
pass
|
||||
|
||||
|
||||
a = <caret>foo()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
def foo():
|
||||
pass
|
||||
|
||||
|
||||
foo()
|
||||
|
||||
@@ -251,7 +251,6 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
|
||||
// PY-15506
|
||||
public void testEmptyListOfBaseClasses() {
|
||||
PsiTestUtil.disablePsiTextConsistencyChecks(getTestRootDisposable());
|
||||
doInspectionTest(PyRedundantParenthesesInspection.class, PyBundle.message("QFIX.redundant.parentheses"), true, true);
|
||||
}
|
||||
|
||||
@@ -267,13 +266,11 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
|
||||
// PY-3126
|
||||
public void testChainedComparison1() {
|
||||
PsiTestUtil.disablePsiTextConsistencyChecks(getTestRootDisposable());
|
||||
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
}
|
||||
|
||||
// PY-3126
|
||||
public void testChainedComparison2() {
|
||||
PsiTestUtil.disablePsiTextConsistencyChecks(getTestRootDisposable());
|
||||
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
}
|
||||
|
||||
@@ -284,7 +281,6 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
|
||||
// PY-5623
|
||||
public void testChainedComparison4() {
|
||||
PsiTestUtil.disablePsiTextConsistencyChecks(getTestRootDisposable());
|
||||
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
}
|
||||
|
||||
@@ -295,7 +291,6 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
|
||||
// PY-20004
|
||||
public void testChainedComparison7() {
|
||||
PsiTestUtil.disablePsiTextConsistencyChecks(getTestRootDisposable());
|
||||
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,6 @@ public class PyIntentionTest extends PyTestCase {
|
||||
}
|
||||
|
||||
public void testConvertSetLiteral() {
|
||||
PsiTestUtil.disablePsiTextConsistencyChecks(getTestRootDisposable());
|
||||
doTest(PyBundle.message("INTN.convert.set.literal.to"), LanguageLevel.PYTHON26);
|
||||
}
|
||||
|
||||
@@ -275,7 +274,6 @@ public class PyIntentionTest extends PyTestCase {
|
||||
}
|
||||
|
||||
public void testConvertTripleQuotedUnicodeString() { //PY-7152
|
||||
PsiTestUtil.disablePsiTextConsistencyChecks(getTestRootDisposable());
|
||||
doTest(PyBundle.message("INTN.triple.quoted.string"));
|
||||
}
|
||||
|
||||
@@ -299,7 +297,6 @@ public class PyIntentionTest extends PyTestCase {
|
||||
}
|
||||
|
||||
public void testConvertTripleQuotedEmptyString() {
|
||||
PsiTestUtil.disablePsiTextConsistencyChecks(getTestRootDisposable());
|
||||
doTest(PyBundle.message("INTN.triple.quoted.string"), LanguageLevel.PYTHON34);
|
||||
}
|
||||
|
||||
|
||||
-2
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.jetbrains.python.intentions;
|
||||
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
|
||||
@@ -53,7 +52,6 @@ public class PyStringConcatenationToFormatIntentionTest extends PyIntentionTestC
|
||||
}
|
||||
|
||||
public void testUnicodeSecondString() { //PY-7463
|
||||
PsiTestUtil.disablePsiTextConsistencyChecks(getTestRootDisposable());
|
||||
doTest(PyBundle.message("INTN.replace.plus.with.format.operator"), LanguageLevel.PYTHON26);
|
||||
}
|
||||
|
||||
|
||||
-2
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.jetbrains.python.quickFixes;
|
||||
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PyQuickFixTestCase;
|
||||
@@ -25,7 +24,6 @@ import com.jetbrains.python.inspections.PyExceptionInheritInspection;
|
||||
public class PyAddExceptionSuperClassQuickFixTest extends PyQuickFixTestCase {
|
||||
|
||||
public void testEmptySuperList() {
|
||||
PsiTestUtil.disablePsiTextConsistencyChecks(getTestRootDisposable());
|
||||
doQuickFixTest(PyExceptionInheritInspection.class, PyBundle.message("QFIX.NAME.add.exception.base"));
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.jetbrains.python.quickFixes;
|
||||
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PyQuickFixTestCase;
|
||||
@@ -25,7 +24,6 @@ import com.jetbrains.python.inspections.PyOldStyleClassesInspection;
|
||||
public class PyConvertToNewStyleQuickFixTest extends PyQuickFixTestCase {
|
||||
|
||||
public void testEmptySuperClassList() {
|
||||
PsiTestUtil.disablePsiTextConsistencyChecks(getTestRootDisposable());
|
||||
doQuickFixTest(PyOldStyleClassesInspection.class, PyBundle.message("QFIX.convert.to.new.style"));
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.jetbrains.python.quickFixes;
|
||||
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PyQuickFixTestCase;
|
||||
@@ -25,7 +24,6 @@ import com.jetbrains.python.inspections.PyNoneFunctionAssignmentInspection;
|
||||
public class PyRemoveAssignmentQuickFixTest extends PyQuickFixTestCase {
|
||||
|
||||
public void testEmptyFunction() {
|
||||
PsiTestUtil.disablePsiTextConsistencyChecks(getTestRootDisposable());
|
||||
doQuickFixTest(PyNoneFunctionAssignmentInspection.class, PyBundle.message("QFIX.NAME.remove.assignment"));
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.jetbrains.python.quickFixes;
|
||||
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PyQuickFixTestCase;
|
||||
@@ -25,7 +24,6 @@ import com.jetbrains.python.inspections.PyCallingNonCallableInspection;
|
||||
public class PyRemoveCallQuickFixTest extends PyQuickFixTestCase {
|
||||
|
||||
public void testExpression() {
|
||||
PsiTestUtil.disablePsiTextConsistencyChecks(getTestRootDisposable());
|
||||
doQuickFixTest(PyCallingNonCallableInspection.class, PyBundle.message("QFIX.NAME.remove.call"));
|
||||
}
|
||||
|
||||
@@ -34,7 +32,6 @@ public class PyRemoveCallQuickFixTest extends PyQuickFixTestCase {
|
||||
}
|
||||
|
||||
public void testClass() {
|
||||
PsiTestUtil.disablePsiTextConsistencyChecks(getTestRootDisposable());
|
||||
doQuickFixTest(PyCallingNonCallableInspection.class, PyBundle.message("QFIX.NAME.remove.call"));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user