mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
Multiple targets support fixed in followAssignmentsChain(); some tests added.
This commit is contained in:
@@ -621,10 +621,9 @@ public class PyUtil {
|
||||
else if (ret == null && elt instanceof PyElement) { // remember this result, but a reference may be the next resolve result
|
||||
ret = (PyElement)elt;
|
||||
}
|
||||
else { // not a reassignment, not anything from Python; no point to continue
|
||||
break SEARCH;
|
||||
}
|
||||
}
|
||||
// all resolve results checked, reassignment not detected, nothing more to do
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.ResolveState;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.psi.*;
|
||||
@@ -81,31 +82,16 @@ public class PyAssignmentStatementImpl extends PyElementImpl implements PyAssign
|
||||
|
||||
@NotNull
|
||||
public List<Pair<PyExpression, PyExpression>> getTargetsToValuesMapping() {
|
||||
List<Pair<PyExpression, PyExpression>> ret = new ArrayList<Pair<PyExpression, PyExpression>>();
|
||||
List<PyExpression> lhses = new ArrayList<PyExpression>(1);
|
||||
PyExpression rhs = null;
|
||||
// extract all LHSes and RHS
|
||||
boolean seen_eq = false;
|
||||
for (PsiElement child = this.getFirstChild(); child != null; child = child.getNextSibling()) {
|
||||
if (child instanceof PsiWhiteSpace) continue;
|
||||
if ("=".equals(child.getText())) seen_eq = true;
|
||||
if (child instanceof PyExpression) {
|
||||
PyExpression expr = (PyExpression)child;
|
||||
if (seen_eq) {
|
||||
if (rhs != null) { // more than one RHS is clearly a parsing error, return nothing.
|
||||
ret.clear();
|
||||
return ret;
|
||||
}
|
||||
rhs = expr;
|
||||
}
|
||||
else lhses.add(expr);
|
||||
List<Pair<PyExpression, PyExpression>> ret = new SmartList<Pair<PyExpression, PyExpression>>();
|
||||
if (!PsiTreeUtil.hasErrorElements(this)) { // no parse errors
|
||||
PyExpression[] constituents = PsiTreeUtil.getChildrenOfType(this, PyExpression.class); // "a = b = c" -> [a, b, c]
|
||||
if (constituents != null && constituents.length > 1) {
|
||||
PyExpression rhs = constituents[constituents.length - 1]; // last
|
||||
List<PyExpression> lhses = new ArrayList<PyExpression>(constituents.length - 1);
|
||||
for (int i = 0; i < constituents.length - 1; i += 1) lhses.add(constituents[i]); // copy all but last; most often it's one element.
|
||||
for (PyExpression lhs : lhses) mapToValues(lhs, rhs, ret);
|
||||
}
|
||||
}
|
||||
if (lhses.size() == 0) { // no LHS, must be incorrectly parsed
|
||||
ret.clear();
|
||||
return ret;
|
||||
}
|
||||
for (PyExpression lhs : lhses) mapToValues(lhs, rhs, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ public class PyCallExpressionHelper {
|
||||
if (callee instanceof PyReferenceExpression) {
|
||||
PyReferenceExpression ref = (PyReferenceExpression)callee;
|
||||
PsiElement resolved = PyUtil.followAssignmentsChain(ref);
|
||||
if (resolved instanceof PyClass) resolved = ((PyClass)resolved).findMethodByName(PyNames.INIT); // class to constructor call
|
||||
if (resolved instanceof PyFunction) {
|
||||
EnumSet<PyCallExpression.Flag> flags = EnumSet.noneOf(PyCallExpression.Flag.class);
|
||||
int implicit_offset = 0;
|
||||
|
||||
7
python/testData/paramInfo/ReassignedClassInit.py
Normal file
7
python/testData/paramInfo/ReassignedClassInit.py
Normal file
@@ -0,0 +1,7 @@
|
||||
class Bar:
|
||||
def __init__(self, a, b):
|
||||
pass
|
||||
|
||||
Boar = Bambr = Bar
|
||||
|
||||
Bambr(<arg1>1, <arg2>2)
|
||||
7
python/testData/paramInfo/ReassignedFunction.py
Normal file
7
python/testData/paramInfo/ReassignedFunction.py
Normal file
@@ -0,0 +1,7 @@
|
||||
def foo(a, b):
|
||||
pass
|
||||
|
||||
zoo = foo
|
||||
moo, n = zoo, 1
|
||||
|
||||
moo(<arg1>1, <arg2>n)
|
||||
8
python/testData/paramInfo/ReassignedInstanceMethod.py
Normal file
8
python/testData/paramInfo/ReassignedInstanceMethod.py
Normal file
@@ -0,0 +1,8 @@
|
||||
class Foo:
|
||||
def moo(self, a, b, c):
|
||||
pass
|
||||
|
||||
foo = Foo()
|
||||
qoo = foo
|
||||
|
||||
qoo.moo(<arg1>1, <arg2>2, <arg3>"bamboo")
|
||||
@@ -213,7 +213,32 @@ public class PyParameterInfoTest extends MarkedTestCase {
|
||||
feignCtrlP(marks.get("<arg2>").getTextOffset()).check("self,a", new String[]{"a"});
|
||||
}
|
||||
|
||||
// TODO: add method tests with decorators when a mock SDK is available
|
||||
public void testReassignedFunction() throws Exception {
|
||||
Map<String, PsiElement> marks = loadTest();
|
||||
assertEquals("Test data sanity", marks.size(), 2);
|
||||
|
||||
feignCtrlP(marks.get("<arg1>").getTextOffset()).check("a,b", new String[]{"a,"});
|
||||
feignCtrlP(marks.get("<arg2>").getTextOffset()).check("a,b", new String[]{"b"});
|
||||
}
|
||||
|
||||
public void testReassignedInstanceMethod() throws Exception {
|
||||
Map<String, PsiElement> marks = loadTest();
|
||||
assertEquals("Test data sanity", marks.size(), 3);
|
||||
|
||||
feignCtrlP(marks.get("<arg1>").getTextOffset()).check("self,a,b,c", new String[]{"a,"}, new String[]{"self,"});
|
||||
feignCtrlP(marks.get("<arg2>").getTextOffset()).check("self,a,b,c", new String[]{"b,"}, new String[]{"self,"});
|
||||
feignCtrlP(marks.get("<arg3>").getTextOffset()).check("self,a,b,c", new String[]{"c"}, new String[]{"self,"});
|
||||
}
|
||||
|
||||
public void testReassignedClassInit() throws Exception {
|
||||
Map<String, PsiElement> marks = loadTest();
|
||||
assertEquals("Test data sanity", marks.size(), 2);
|
||||
|
||||
feignCtrlP(marks.get("<arg1>").getTextOffset()).check("self,a,b", new String[]{"a,"}, new String[]{"self,"});
|
||||
feignCtrlP(marks.get("<arg2>").getTextOffset()).check("self,a,b", new String[]{"b"}, new String[]{"self,"});
|
||||
}
|
||||
|
||||
// TODO: add method tests with decorators when a mock SDK is available
|
||||
|
||||
/**
|
||||
* Imitates pressing of Ctrl+P; fails if results are not as expected.
|
||||
|
||||
Reference in New Issue
Block a user