mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-15 20:26:04 +07:00
fixed PY-9253 Broken "add field to class" adds the field to the instance instead.
moved tests to the separate testCase
This commit is contained in:
@@ -700,7 +700,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
actions.add(new AddMethodQuickFix(refText, (PyClassType)qtype, true));
|
||||
}
|
||||
else if (!(reference instanceof PyOperatorReference)) {
|
||||
actions.add(new AddFieldQuickFix(refText, cls, "None"));
|
||||
actions.add(new AddFieldQuickFix(refText, (PyClassType)qtype, "None"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.jetbrains.python.psi.impl.PyImportStatementNavigator;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.search.PyOverridingMethodsSearch;
|
||||
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
|
||||
import com.jetbrains.python.psi.types.PyClassTypeImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
@@ -280,7 +281,7 @@ public class PyUnusedLocalInspectionVisitor extends PyInspectionVisitor {
|
||||
}
|
||||
}
|
||||
final LocalQuickFix[] fixes = mayBeField
|
||||
? new LocalQuickFix[] { new AddFieldQuickFix(name, containingClass, name) }
|
||||
? new LocalQuickFix[] { new AddFieldQuickFix(name, new PyClassTypeImpl(containingClass, false), name) }
|
||||
: LocalQuickFix.EMPTY_ARRAY;
|
||||
registerWarning(element, PyBundle.message("INSP.unused.locals.parameter.isnot.used", name), fixes);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyBuiltinCache;
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
import com.jetbrains.python.psi.types.PyClassType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -24,19 +25,19 @@ import org.jetbrains.annotations.Nullable;
|
||||
*/
|
||||
public class AddFieldQuickFix implements LocalQuickFix {
|
||||
|
||||
private PyClass myQualifierClass;
|
||||
private PyClassType myQualifierType;
|
||||
private final String myInitializer;
|
||||
private String myIdentifier;
|
||||
|
||||
public AddFieldQuickFix(String identifier, PyClass qualifierClass, String initializer) {
|
||||
public AddFieldQuickFix(String identifier, PyClassType qualifierType, String initializer) {
|
||||
myIdentifier = identifier;
|
||||
myQualifierClass = qualifierClass;
|
||||
myQualifierType = qualifierType;
|
||||
myInitializer = initializer;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return PyBundle.message("QFIX.NAME.add.field.$0.to.class.$1", myIdentifier, myQualifierClass.getName());
|
||||
return PyBundle.message("QFIX.NAME.add.field.$0.to.class.$1", myIdentifier, myQualifierType.getName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -66,14 +67,19 @@ public class AddFieldQuickFix implements LocalQuickFix {
|
||||
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
// expect the descriptor to point to the unresolved identifier.
|
||||
PyClass cls = myQualifierClass;
|
||||
String item_name = myIdentifier;
|
||||
if (cls != null) {
|
||||
PsiElement initStatement = addFieldToInit(project, cls, item_name, new CreateFieldCallback(project, item_name, myInitializer));
|
||||
if (initStatement != null) {
|
||||
showTemplateBuilder(initStatement);
|
||||
return;
|
||||
}
|
||||
PyClass cls = myQualifierType.getPyClass();
|
||||
PsiElement initStatement;
|
||||
if (!myQualifierType.isDefinition()) {
|
||||
initStatement = addFieldToInit(project, cls, myIdentifier, new CreateFieldCallback(project, myIdentifier, myInitializer));
|
||||
}
|
||||
else {
|
||||
PyStatement field = PyElementGenerator.getInstance(project)
|
||||
.createFromText(LanguageLevel.getDefault(), PyStatement.class, myIdentifier + " = " + myInitializer);
|
||||
initStatement = PyUtil.addElementToStatementList(field, cls.getStatementList(), true);
|
||||
}
|
||||
if (initStatement != null) {
|
||||
showTemplateBuilder(initStatement);
|
||||
return;
|
||||
}
|
||||
// somehow we failed. tell about this
|
||||
PyUtil.showBalloon(project, PyBundle.message("QFIX.failed.to.add.field"), MessageType.ERROR);
|
||||
@@ -83,8 +89,11 @@ public class AddFieldQuickFix implements LocalQuickFix {
|
||||
initStatement = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(initStatement);
|
||||
if (initStatement instanceof PyAssignmentStatement) {
|
||||
final TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(initStatement);
|
||||
builder.replaceElement(((PyAssignmentStatement) initStatement).getAssignedValue(), myInitializer);
|
||||
builder.run();
|
||||
final PyExpression assignedValue = ((PyAssignmentStatement)initStatement).getAssignedValue();
|
||||
if (assignedValue != null) {
|
||||
builder.replaceElement(assignedValue, myInitializer);
|
||||
builder.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ public class AddMethodQuickFix implements LocalQuickFix {
|
||||
meth.addBefore(deco_list, meth.getFirstChild()); // in the very beginning
|
||||
}
|
||||
|
||||
meth = (PyFunction)PyUtil.addElementToStatementList(meth, cls_stmt_list);
|
||||
meth = (PyFunction)PyUtil.addElementToStatementList(meth, cls_stmt_list, PyNames.INIT.equals(meth.getName()));
|
||||
if (myReplaceUsage)
|
||||
showTemplateBuilder(meth);
|
||||
}
|
||||
|
||||
@@ -54,13 +54,13 @@ public class PyMoveAttributeToInitQuickFix implements LocalQuickFix {
|
||||
PyFunction.class,
|
||||
"def __init__(self):\n\t" +
|
||||
copy.getText());
|
||||
PyUtil.addElementToStatementList(init, classStatementList);
|
||||
PyUtil.addElementToStatementList(init, classStatementList, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
final PyStatementList statementList = init.getStatementList();
|
||||
if (statementList == null) return false;
|
||||
PyUtil.addElementToStatementList(copy, statementList);
|
||||
PyUtil.addElementToStatementList(copy, statementList, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1203,15 +1203,16 @@ public class PyUtil {
|
||||
}
|
||||
|
||||
|
||||
public static PsiElement addElementToStatementList(@NotNull PsiElement element, @NotNull PyStatementList statementList) {
|
||||
public static PsiElement addElementToStatementList(@NotNull PsiElement element,
|
||||
@NotNull PyStatementList statementList,
|
||||
boolean toTheBeginning) {
|
||||
final PsiElement firstChild = statementList.getFirstChild();
|
||||
if (firstChild == statementList.getLastChild() && firstChild instanceof PyPassStatement) {
|
||||
element = firstChild.replace(element);
|
||||
}
|
||||
else {
|
||||
final PyStatement[] statements = statementList.getStatements();
|
||||
String name = element instanceof PsiNamedElement ? ((PsiNamedElement)element).getName() : "";
|
||||
if (PyNames.INIT.equals(name) && statements.length > 0) {
|
||||
if (toTheBeginning && statements.length > 0) {
|
||||
final PyDocStringOwner docStringOwner = PsiTreeUtil.getParentOfType(statementList, PyDocStringOwner.class);
|
||||
final PyStatement firstStatement = statements[0];
|
||||
if (docStringOwner != null && firstStatement instanceof PyExpressionStatement &&
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
__author__ = 'ktisha'
|
||||
|
||||
class A(object):
|
||||
|
||||
def method(self):
|
||||
var = A.<warning descr="Unresolved attribute reference 'FIELD' for class 'A'"><caret>FIELD</warning>
|
||||
var = self.<warning descr="Unresolved attribute reference 'test' for class 'A'">test</warning>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
__author__ = 'ktisha'
|
||||
|
||||
class A(object):
|
||||
|
||||
FIELD = None
|
||||
|
||||
def method(self):
|
||||
var = A.FIELD
|
||||
var = self.test
|
||||
|
||||
@@ -3,8 +3,8 @@ __author__ = 'ktisha'
|
||||
|
||||
class A:
|
||||
def __init__(self):
|
||||
self._a = 1
|
||||
self.b = 1
|
||||
self._a = 1
|
||||
|
||||
def foo(self):
|
||||
pass
|
||||
|
||||
@@ -3,8 +3,8 @@ __author__ = 'ktisha'
|
||||
|
||||
class A:
|
||||
def __init__(self):
|
||||
self._a = 1
|
||||
self.b = 1
|
||||
self._a = 1
|
||||
|
||||
def foo(self):
|
||||
c = 1
|
||||
@@ -95,26 +95,6 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
true);
|
||||
}
|
||||
|
||||
public void testAddFieldFromMethod() {
|
||||
doInspectionTest("AddFieldFromMethod.py", PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.field.$0.to.class.$1", "y", "A"),
|
||||
true, true);
|
||||
}
|
||||
|
||||
public void testAddFieldFromInstance() {
|
||||
doInspectionTest("AddFieldFromInstance.py", PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.field.$0.to.class.$1", "y", "A"),
|
||||
true, true);
|
||||
}
|
||||
|
||||
public void testAddFieldAddConstructor() {
|
||||
doInspectionTest("AddFieldAddConstructor.py", PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.field.$0.to.class.$1", "x", "B"),
|
||||
true, true);
|
||||
}
|
||||
|
||||
public void testAddFieldNewConstructor() {
|
||||
doInspectionTest("AddFieldNewConstructor.py", PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.field.$0.to.class.$1", "x", "B"),
|
||||
true, true);
|
||||
}
|
||||
|
||||
public void testRemoveTrailingSemicolon() {
|
||||
doInspectionTest("RemoveTrailingSemicolon.py", PyTrailingSemicolonInspection.class, PyBundle.message("QFIX.remove.trailing.semicolon"),
|
||||
true, true);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.jetbrains.python.quickFixes;
|
||||
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.inspections.PyUnresolvedReferencesInspection;
|
||||
|
||||
/**
|
||||
* User: ktisha
|
||||
*/
|
||||
public class AddFieldQuickFixTest extends PyQuickFixTestCase {
|
||||
|
||||
public void testAddClassField() {
|
||||
doInspectionTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.field.$0.to.class.$1", "FIELD", "A"));
|
||||
}
|
||||
|
||||
public void testAddFieldFromMethod() {
|
||||
doInspectionTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.field.$0.to.class.$1", "y", "A"));
|
||||
}
|
||||
|
||||
public void testAddFieldFromInstance() {
|
||||
doInspectionTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.field.$0.to.class.$1", "y", "A"));
|
||||
}
|
||||
|
||||
public void testAddFieldAddConstructor() {
|
||||
doInspectionTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.field.$0.to.class.$1", "x", "B"));
|
||||
}
|
||||
|
||||
public void testAddFieldNewConstructor() {
|
||||
doInspectionTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.NAME.add.field.$0.to.class.$1", "x", "B"));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user