PY-25655: Store super classes text in stub

This commit is contained in:
fitermay
2017-11-14 14:50:09 -05:00
committed by Mikhail Golubev
parent 256be71440
commit 6d9cd9f45c
6 changed files with 83 additions and 15 deletions

View File

@@ -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();
}
}

View File

@@ -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

View File

@@ -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) {

View File

@@ -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 + ")";

View 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

View File

@@ -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, () -> {