mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 14:23:28 +07:00
PY-25655: Store super classes text in stub
This commit is contained in:
committed by
Mikhail Golubev
parent
256be71440
commit
6d9cd9f45c
@@ -25,6 +25,7 @@ import com.jetbrains.python.psi.PyClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -43,6 +44,7 @@ public interface PyClassStub extends NamedStub<PyClass> {
|
||||
@NotNull
|
||||
List<String> getSubscriptedSuperClasses();
|
||||
|
||||
|
||||
@Nullable
|
||||
QualifiedName getMetaClass();
|
||||
|
||||
@@ -51,4 +53,9 @@ public interface PyClassStub extends NamedStub<PyClass> {
|
||||
|
||||
@Nullable
|
||||
String getDocString();
|
||||
|
||||
@NotNull
|
||||
default List<String> getSuperClassesText() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -342,13 +342,10 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
public String getPresentableText() {
|
||||
PyPsiUtils.assertValid(PyClassImpl.this);
|
||||
final StringBuilder result = new StringBuilder(notNullize(getName(), PyNames.UNNAMED_ELEMENT));
|
||||
final PyExpression[] superClassExpressions = getSuperClassExpressions();
|
||||
if (superClassExpressions.length > 0) {
|
||||
final List<String> superClassesText = getSuperClassesText();
|
||||
if (superClassesText.size() > 0) {
|
||||
result.append("(");
|
||||
result.append(join(Arrays.asList(superClassExpressions), expr -> {
|
||||
String name = expr.getText();
|
||||
return notNullize(name, PyNames.UNNAMED_ELEMENT);
|
||||
}, ", "));
|
||||
result.append(join(superClassesText, expr -> notNullize(expr, PyNames.UNNAMED_ELEMENT), ", "));
|
||||
result.append(")");
|
||||
}
|
||||
return result.toString();
|
||||
@@ -356,6 +353,16 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
};
|
||||
}
|
||||
|
||||
private List<String> getSuperClassesText() {
|
||||
PyClassStub stub = getGreenStub();
|
||||
if (stub == null || stub.getSuperClassesText() == null) {
|
||||
return ContainerUtil.map(getSuperClassExpressions(), exp -> exp.getText());
|
||||
}
|
||||
else {
|
||||
return stub.getSuperClassesText();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PyClassLikeType> mroMerge(@NotNull List<List<PyClassLikeType>> sequences) throws MROException {
|
||||
List<PyClassLikeType> result = new LinkedList<>(); // need to insert to 0th position on linearize
|
||||
|
||||
@@ -64,6 +64,7 @@ public class PyClassElementType extends PyStubElementType<PyClassStub, PyClass>
|
||||
parentStub,
|
||||
getSuperClassQNames(psi),
|
||||
ContainerUtil.map(getSubscriptedSuperClasses(psi), PsiElement::getText),
|
||||
ContainerUtil.map(psi.getSuperClassExpressions(), PsiElement::getText),
|
||||
PyPsiUtils.asQualifiedName(psi.getMetaClassExpression()),
|
||||
psi.getOwnSlots(),
|
||||
PyPsiUtils.strValue(psi.getDocStringExpression()),
|
||||
@@ -108,6 +109,7 @@ public class PyClassElementType extends PyStubElementType<PyClassStub, PyClass>
|
||||
PySubscriptionExpression.class));
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private static QualifiedName resolveOriginalSuperClassQName(@NotNull PyExpression superClassExpression) {
|
||||
if (superClassExpression instanceof PyReferenceExpression) {
|
||||
@@ -144,9 +146,14 @@ public class PyClassElementType extends PyStubElementType<PyClassStub, PyClass>
|
||||
QualifiedName.serialize(entry.getValue(), dataStream);
|
||||
}
|
||||
|
||||
final List<String> baseClassesText = pyClassStub.getSubscriptedSuperClasses();
|
||||
final List<String> subscriptedBaseClassesText = pyClassStub.getSubscriptedSuperClasses();
|
||||
final List<String> baseClassesText = pyClassStub.getSuperClassesText();
|
||||
assert baseClassesText != null;
|
||||
|
||||
dataStream.writeByte(baseClassesText.size());
|
||||
for (String text : baseClassesText) {
|
||||
boolean isParametrized = subscriptedBaseClassesText.contains(text);
|
||||
dataStream.writeBoolean(isParametrized);
|
||||
dataStream.writeName(text);
|
||||
}
|
||||
|
||||
@@ -168,15 +175,19 @@ public class PyClassElementType extends PyStubElementType<PyClassStub, PyClass>
|
||||
superClasses.put(QualifiedName.deserialize(dataStream), QualifiedName.deserialize(dataStream));
|
||||
}
|
||||
|
||||
final byte parametrizedBaseClassesCount = dataStream.readByte();
|
||||
final byte baseClassesCount = dataStream.readByte();
|
||||
final ArrayList<String> parametrizedBaseClasses = new ArrayList<>();
|
||||
for (int i = 0; i < parametrizedBaseClassesCount; i++) {
|
||||
final ArrayList<String> baseClassesText = new ArrayList<>();
|
||||
for (int i = 0; i < baseClassesCount; i++) {
|
||||
final boolean isParametrized = dataStream.readBoolean();
|
||||
final StringRef ref = dataStream.readName();
|
||||
if (ref != null) {
|
||||
baseClassesText.add(ref != null ? ref.getString() : null);
|
||||
if (ref != null && isParametrized) {
|
||||
parametrizedBaseClasses.add(ref.getString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final QualifiedName metaClass = QualifiedName.deserialize(dataStream);
|
||||
|
||||
final List<String> slots = PyFileElementType.readNullableList(dataStream);
|
||||
@@ -184,7 +195,8 @@ public class PyClassElementType extends PyStubElementType<PyClassStub, PyClass>
|
||||
final String docStringInStub = dataStream.readUTFFast();
|
||||
final String docString = docStringInStub.length() > 0 ? docStringInStub : null;
|
||||
|
||||
return new PyClassStubImpl(name, parentStub, superClasses, parametrizedBaseClasses, metaClass, slots, docString, getStubElementType());
|
||||
return new PyClassStubImpl(name, parentStub, superClasses, parametrizedBaseClasses, baseClassesText, metaClass, slots, docString,
|
||||
getStubElementType());
|
||||
}
|
||||
|
||||
public void indexStub(@NotNull final PyClassStub stub, @NotNull final IndexSink sink) {
|
||||
|
||||
@@ -30,14 +30,15 @@ import java.util.Map;
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class PyClassStubImpl extends StubBase<PyClass> implements PyClassStub {
|
||||
public class
|
||||
PyClassStubImpl extends StubBase<PyClass> implements PyClassStub {
|
||||
|
||||
@Nullable
|
||||
private final String myName;
|
||||
|
||||
@NotNull
|
||||
private final Map<QualifiedName, QualifiedName> mySuperClasses;
|
||||
private final List<String> mySuperClassesText;
|
||||
private final List<String> mySubscriptedSuperClassesText;
|
||||
|
||||
@Nullable
|
||||
private final QualifiedName myMetaClass;
|
||||
@@ -48,10 +49,25 @@ public class PyClassStubImpl extends StubBase<PyClass> implements PyClassStub {
|
||||
@Nullable
|
||||
private final String myDocString;
|
||||
|
||||
@Nullable
|
||||
private final List<String> mySuperClassesText;
|
||||
|
||||
public PyClassStubImpl(@Nullable String name,
|
||||
@Nullable StubElement parentStub,
|
||||
@NotNull Map<QualifiedName, QualifiedName> superClasses,
|
||||
@NotNull List<String> superClassesText,
|
||||
@NotNull List<String> subscriptedSuperClassesText,
|
||||
@Nullable QualifiedName metaClass,
|
||||
@Nullable List<String> slots,
|
||||
@Nullable String docString,
|
||||
@NotNull IStubElementType stubElementType) {
|
||||
this(name, parentStub, superClasses, subscriptedSuperClassesText, null, metaClass, slots, docString, stubElementType);
|
||||
}
|
||||
|
||||
public PyClassStubImpl(@Nullable String name,
|
||||
@Nullable StubElement parentStub,
|
||||
@NotNull Map<QualifiedName, QualifiedName> superClasses,
|
||||
@NotNull List<String> subscriptedSuperClassesText,
|
||||
@Nullable List<String> superClassesText,
|
||||
@Nullable QualifiedName metaClass,
|
||||
@Nullable List<String> slots,
|
||||
@Nullable String docString,
|
||||
@@ -59,6 +75,7 @@ public class PyClassStubImpl extends StubBase<PyClass> implements PyClassStub {
|
||||
super(parentStub, stubElementType);
|
||||
myName = name;
|
||||
mySuperClasses = superClasses;
|
||||
mySubscriptedSuperClassesText = subscriptedSuperClassesText;
|
||||
mySuperClassesText = superClassesText;
|
||||
myMetaClass = metaClass;
|
||||
mySlots = slots;
|
||||
@@ -78,7 +95,7 @@ public class PyClassStubImpl extends StubBase<PyClass> implements PyClassStub {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getSubscriptedSuperClasses() {
|
||||
return mySuperClassesText;
|
||||
return mySubscriptedSuperClassesText;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -99,6 +116,12 @@ public class PyClassStubImpl extends StubBase<PyClass> implements PyClassStub {
|
||||
return myDocString;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getSuperClassesText() {
|
||||
return mySuperClassesText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PyClassStub(" + myName + ")";
|
||||
|
||||
8
python/testData/stubs/BaseClassText.py
Normal file
8
python/testData/stubs/BaseClassText.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
T = TypeVar('T')
|
||||
V = TypeVar('V')
|
||||
|
||||
|
||||
class Class(Generic[T, V], BaseClass1, SomeModule.SomeClass):
|
||||
pass
|
||||
@@ -843,6 +843,17 @@ public class PyStubsTest extends PyTestCase {
|
||||
assertNotParsed(file);
|
||||
}
|
||||
|
||||
// PY-25655
|
||||
public void testBaseClassText() {
|
||||
final PyFile file = getTestFile();
|
||||
final PyClass pyClass = file.findTopLevelClass("Class");
|
||||
final PyClassStub stub = pyClass.getStub();
|
||||
assertNotNull(stub);
|
||||
final List<String> genericBases = stub.getSuperClassesText();
|
||||
assertContainsOrdered(genericBases, "Generic[T, V]", "BaseClass1", "SomeModule.SomeClass");
|
||||
assertNotParsed(file);
|
||||
}
|
||||
|
||||
// PY-18816
|
||||
public void testComplexGenericType() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON30, () -> {
|
||||
|
||||
Reference in New Issue
Block a user