PY-45206 IJ-CR-3996 Fixed resolve to fallback definition from __init__() to method defined above

GitOrigin-RevId: 7c9b302f9ce78fe901a1c28adb9f647c86d60e96
This commit is contained in:
Andrey Vlasovskikh
2021-03-30 14:27:00 +00:00
committed by intellij-monorepo-bot
parent 1b647e64cf
commit 19962fdaa7
3 changed files with 24 additions and 5 deletions
@@ -1107,7 +1107,7 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
private List<PyTargetExpression> collectInstanceAttributes(Map<String, ScopeOwner> scopesToSkip) {
Map<String, PyTargetExpression> result = new HashMap<>();
collectAttributesInConstructors(result);
collectAttributesInConstructors(result, scopesToSkip);
Set<String> existing = new HashSet<>(result.keySet());
final PyFunction[] methods = getMethods();
for (PyFunction method : methods) {
@@ -1117,16 +1117,20 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
return new ArrayList<>(result.values());
}
private void collectAttributesInConstructors(Map<String, PyTargetExpression> result) {
private void collectAttributesInConstructors(Map<String, PyTargetExpression> result,
Map<String, ScopeOwner> scopesToSkip) {
PyFunction newMethod = findMethodByName(PyNames.NEW, false, null);
if (newMethod != null) {
for (PyTargetExpression target : getTargetExpressions(newMethod)) {
result.put(target.getName(), target);
String name = target.getName();
if (scopesToSkip.get(name) != newMethod) {
result.put(name, target);
}
}
}
PyFunctionImpl initMethod = (PyFunctionImpl)findMethodByName(PyNames.INIT, false, null);
PyFunction initMethod = findMethodByName(PyNames.INIT, false, null);
if (initMethod != null) {
collectInstanceAttributes(initMethod, result);
collectInstanceAttributes(initMethod, result, Collections.emptySet(), scopesToSkip);
}
}
@@ -0,0 +1,9 @@
class C:
def g(self):
self.foo = 0
def __init__(self):
self.g()
print(self.foo) # -> self.foo in g
# <ref>
self.foo = 1
@@ -836,4 +836,10 @@ public class Py3ResolveTest extends PyResolveTestCase {
PyTargetExpression target = assertResolvesTo(PyTargetExpression.class, "foo");
assertEquals("self.foo = 1", target.getParent().getText());
}
public void testInstanceAttrBelowInInitAndOtherMethodAbove() {
final PyTargetExpression target = assertResolvesTo(PyTargetExpression.class, "foo");
final PyFunction function = assertInstanceOf(ScopeUtil.getScopeOwner(target), PyFunction.class);
assertEquals("g", function.getName());
}
}