mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-9342 Follow assignments chain to determine that method is bound
This commit is contained in:
@@ -18,10 +18,12 @@ package com.jetbrains.python.psi.types;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyBuiltinCache;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.resolve.QualifiedResolveResult;
|
||||
import com.jetbrains.python.psi.resolve.RatedResolveResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -116,12 +118,23 @@ public class PyFunctionType implements PyCallableType {
|
||||
final PyFunction function = as(getCallable(), PyFunction.class);
|
||||
final boolean isNonStaticMethod = function != null && function.getContainingClass() != null && function.getModifier() != STATICMETHOD;
|
||||
if (isNonStaticMethod) {
|
||||
// In Python 2 unbound methods have __method fake type
|
||||
if (LanguageLevel.forElement(location).isOlderThan(LanguageLevel.PYTHON30)) {
|
||||
return true;
|
||||
}
|
||||
final PyExpression qualifier;
|
||||
if (location.isQualified()) {
|
||||
qualifier = location.getQualifier();
|
||||
}
|
||||
else {
|
||||
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
|
||||
final QualifiedResolveResult resolveResult = location.followAssignmentsChain(resolveContext);
|
||||
final List<PyExpression> qualifiers = resolveResult.getQualifiers();
|
||||
qualifier = ContainerUtil.isEmpty(qualifiers) ? null : qualifiers.get(qualifiers.size() - 1);
|
||||
}
|
||||
if (qualifier != null) {
|
||||
//noinspection ConstantConditions
|
||||
final PyType qualifierType = PyTypeChecker.toNonWeakType(context.getType(location.getQualifier()), context);
|
||||
final PyType qualifierType = PyTypeChecker.toNonWeakType(context.getType(qualifier), context);
|
||||
if (isInstanceType(qualifierType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
class MyClass(object):
|
||||
def method(self):
|
||||
pass
|
||||
|
||||
m = MyClass().method
|
||||
m.__<caret>
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
class MyClass(object):
|
||||
def method(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def static_method():
|
||||
pass
|
||||
|
||||
|
||||
# Unbound method still treated as __method in Python 2
|
||||
MyClass.method.__func__
|
||||
MyClass.method.<warning descr="Cannot find reference '__defaults__' in 'function'">__defaults__</warning>
|
||||
|
||||
# Bound method with qualifier
|
||||
inst = MyClass()
|
||||
inst.method.__func__
|
||||
inst.method.<warning descr="Cannot find reference '__defaults__' in 'function'">__defaults__</warning>
|
||||
|
||||
# Reassigned bound method without qualifier
|
||||
m = inst.method
|
||||
|
||||
# Static method
|
||||
# This reference should be marked as unresolved, but such warnings are suppressed for methods with decorators
|
||||
inst.static_method.__func__
|
||||
inst.static_method.__defaults__
|
||||
@@ -694,6 +694,11 @@ public class PythonCompletionTest extends PyTestCase {
|
||||
assertUnderscoredFunctionAttributesSuggested();
|
||||
}
|
||||
|
||||
// PY-9342
|
||||
public void testReassignedMethodSpecialAttributes() {
|
||||
assertUnderscoredMethodSpecialAttributesSuggested();
|
||||
}
|
||||
|
||||
private void assertUnderscoredFunctionAttributesSuggested() {
|
||||
myFixture.configureByFile("completion/" + getTestName(true) + ".py");
|
||||
myFixture.completeBasic();
|
||||
|
||||
+5
@@ -371,6 +371,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase {
|
||||
doMultiFileTest();
|
||||
}
|
||||
|
||||
// PY-9342
|
||||
public void testMethodSpecialAttributes() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-11472
|
||||
public void testUnusedImportBeforeStarImport() {
|
||||
doMultiFileTest();
|
||||
|
||||
Reference in New Issue
Block a user