mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-01 23:06:24 +07:00
Fix completion private members described in stubs (PY-27146)
No more private element filtering in CompletionVariantsProcessor, let's leave it for types.
This commit is contained in:
@@ -157,13 +157,7 @@ public class PyProtectedMemberInspection extends PyInspection {
|
||||
@Nullable
|
||||
private PyClass getNotPyiClassOwner(@Nullable PsiElement element) {
|
||||
final PyClass owner = getClassOwner(element);
|
||||
if (owner != null) {
|
||||
final PsiElement originalOwner = PyiUtil.getOriginalElement(owner);
|
||||
if (originalOwner instanceof PyClass) {
|
||||
return (PyClass)originalOwner;
|
||||
}
|
||||
}
|
||||
return owner;
|
||||
return owner == null ? null : PyiUtil.stubToOriginal(owner, PyClass.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -128,10 +128,9 @@ public class PyQualifiedReference extends PyReferenceImpl {
|
||||
return true;
|
||||
}
|
||||
if (match.size() > 1) {
|
||||
final PyClass ourClass = qualifierType.getPyClass();
|
||||
final PsiElement originalOurClass = PyiUtil.getOriginalElement(ourClass);
|
||||
final PyClass ourClass = PyiUtil.stubToOriginal(qualifierType.getPyClass(), PyClass.class);
|
||||
final PsiElement theirClass = CompletionUtil.getOriginalOrSelf(match.get(match.size() - 1));
|
||||
if (originalOurClass != null && originalOurClass != theirClass || originalOurClass == null && ourClass != theirClass) return true;
|
||||
if (ourClass != theirClass) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -156,9 +156,6 @@ public class CompletionVariantsProcessor extends VariantsProcessor {
|
||||
|
||||
@Override
|
||||
protected void addElement(@NotNull String name, @NotNull PsiElement element) {
|
||||
if (PyUtil.isClassPrivateName(name) && !PyUtil.inSameFile(element, myContext)) {
|
||||
return;
|
||||
}
|
||||
markAsProcessed(name);
|
||||
myVariants.put(name, setupItem(LookupElementBuilder.createWithSmartPointer(name, element).withIcon(element.getIcon(0))));
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.jetbrains.python.psi.resolve.CompletionVariantsProcessor;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveProcessor;
|
||||
import com.jetbrains.python.psi.resolve.RatedResolveResult;
|
||||
import com.jetbrains.python.pyi.PyiUtil;
|
||||
import com.jetbrains.python.toolbox.Maybe;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -788,7 +789,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
if (containingClass != null) {
|
||||
containingClass = CompletionUtil.getOriginalElement(containingClass);
|
||||
}
|
||||
boolean withinOurClass = containingClass == getPyClass() || isInSuperCall(expressionHook);
|
||||
final boolean withinOurClass = containingClass == PyiUtil.stubToOriginal(getPyClass(), PyClass.class) || isInSuperCall(expressionHook);
|
||||
|
||||
final CompletionVariantsProcessor processor = new CompletionVariantsProcessor(
|
||||
expressionHook, new FilterNotInstance(myClass), null, false, suppressParentheses
|
||||
@@ -808,7 +809,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
for (LookupElement le : processor.getResultList()) {
|
||||
String name = le.getLookupString();
|
||||
if (namesAlready.contains(name)) continue;
|
||||
if (!withinOurClass && isClassPrivate(name)) continue;
|
||||
if (!withinOurClass && PyUtil.isClassPrivateName(name)) continue;
|
||||
if (!withinOurClass && isClassProtected(name) && prefix == null) continue;
|
||||
namesAlready.add(name);
|
||||
ret.add(le);
|
||||
@@ -849,7 +850,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
Object[] ancestry = type.getCompletionVariants(name, expressionHook, context);
|
||||
for (Object ob : ancestry) {
|
||||
String inheritedName = ob.toString();
|
||||
if (!namesAlready.contains(inheritedName) && !isClassPrivate(inheritedName)) {
|
||||
if (!namesAlready.contains(inheritedName) && !PyUtil.isClassPrivateName(inheritedName)) {
|
||||
ret.add(ob);
|
||||
namesAlready.add(inheritedName);
|
||||
}
|
||||
@@ -858,10 +859,6 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isClassPrivate(String lookup_string) {
|
||||
return lookup_string.startsWith("__") && !lookup_string.endsWith("__");
|
||||
}
|
||||
|
||||
private static boolean isClassProtected(@NotNull final String lookupString) {
|
||||
return lookupString.startsWith("_") && !lookupString.startsWith("__");
|
||||
}
|
||||
|
||||
@@ -125,6 +125,15 @@ public class PyiUtil {
|
||||
PyKnownDecoratorUtil.getKnownDecorators((PyFunction)element, context).contains(overload);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends PyElement> T stubToOriginal(@NotNull T element, @NotNull Class<T> cls) {
|
||||
final PsiElement originalElement = getOriginalElement(element);
|
||||
if (cls.isInstance(originalElement)) {
|
||||
return cls.cast(originalElement);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
private static boolean pyButNotPyiFile(@Nullable PsiFile file) {
|
||||
return file instanceof PyFile && !(file instanceof PyiFile);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
class Test:
|
||||
@classmethod
|
||||
def foo(cls):
|
||||
return cls._bar(), cls.__egg()
|
||||
|
||||
@staticmethod
|
||||
def _bar():
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def __egg():
|
||||
pass
|
||||
@@ -0,0 +1,12 @@
|
||||
class Test:
|
||||
@classmethod
|
||||
def foo(cls):
|
||||
return cls._bar(), cls.__eg<caret>
|
||||
|
||||
@staticmethod
|
||||
def _bar():
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def __egg():
|
||||
pass
|
||||
@@ -0,0 +1,7 @@
|
||||
class Test:
|
||||
@classmethod
|
||||
def foo(cls): ...
|
||||
@staticmethod
|
||||
def _bar(): ...
|
||||
@staticmethod
|
||||
def __egg(): ...
|
||||
@@ -1194,6 +1194,11 @@ public class PythonCompletionTest extends PyTestCase {
|
||||
assertDoesntContain(variants, "bar=");
|
||||
}
|
||||
|
||||
// PY-27146
|
||||
public void testPrivateMemberOwnerResolvedToStub() {
|
||||
doMultiFileTest();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return super.getTestDataPath() + "/completion";
|
||||
|
||||
Reference in New Issue
Block a user