mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Added stubs for docstrings of target expressions
This commit is contained in:
@@ -12,7 +12,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public interface PyTargetExpression extends PyQualifiedExpression, PsiNamedElement, PsiNameIdentifierOwner, StubBasedPsiElement<PyTargetExpressionStub> {
|
||||
public interface PyTargetExpression extends PyQualifiedExpression, PsiNamedElement, PsiNameIdentifierOwner, PyDocStringOwner,
|
||||
StubBasedPsiElement<PyTargetExpressionStub> {
|
||||
PyTargetExpression[] EMPTY_ARRAY = new PyTargetExpression[0];
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,4 +45,7 @@ public interface PyTargetExpressionStub extends NamedStub<PyTargetExpression> {
|
||||
|
||||
@Nullable
|
||||
<T extends CustomTargetExpressionStub> T getCustomStub(Class<T> stubClass);
|
||||
|
||||
@Nullable
|
||||
String getDocString();
|
||||
}
|
||||
|
||||
@@ -73,24 +73,6 @@ public class DocStringUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PyStringLiteralExpression getAttributeDocString(@NotNull PyTargetExpression attr) {
|
||||
if (attr.getParent() instanceof PyAssignmentStatement) {
|
||||
final PyAssignmentStatement assignment = (PyAssignmentStatement)attr.getParent();
|
||||
PsiElement nextSibling = assignment.getNextSibling();
|
||||
while (nextSibling != null && (nextSibling instanceof PsiWhiteSpace || nextSibling instanceof PsiComment)) {
|
||||
nextSibling = nextSibling.getNextSibling();
|
||||
}
|
||||
if (nextSibling instanceof PyExpressionStatement) {
|
||||
final PyExpression expression = ((PyExpressionStatement)nextSibling).getExpression();
|
||||
if (expression instanceof PyStringLiteralExpression) {
|
||||
return (PyStringLiteralExpression)expression;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getAttributeDocComment(@NotNull PyTargetExpression attr) {
|
||||
if (attr.getParent() instanceof PyAssignmentStatement) {
|
||||
|
||||
@@ -446,7 +446,7 @@ class PyDocumentationBuilder {
|
||||
.addItem(" of class ").addWith(PythonDocumentationProvider.LinkMyClass, $().addWith(TagCode, $(cls.getName()))).addItem(BR)
|
||||
;
|
||||
|
||||
final String docString = PyPsiUtils.strValue(DocStringUtil.getAttributeDocString((PyTargetExpression)myElement));
|
||||
final String docString = ((PyTargetExpression)myElement).getDocStringValue();
|
||||
if (docString != null) {
|
||||
addFormattedDocString(myElement, docString, myBody, myEpilog);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,8 @@ public class PyFileElementType extends IStubFileElementType<PyFileStub> {
|
||||
|
||||
@Override
|
||||
public int getStubVersion() {
|
||||
return 47;
|
||||
// Don't forget to update versions of indexes that use the updated stub-based elements
|
||||
return 48;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -4,10 +4,7 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiPolyVariantReference;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.ResolveResult;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
@@ -25,7 +22,6 @@ import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.documentation.DocStringUtil;
|
||||
import com.jetbrains.python.psi.StructuredDocString;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.references.PyQualifiedReference;
|
||||
import com.jetbrains.python.psi.impl.references.PyTargetReference;
|
||||
@@ -120,10 +116,14 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
|
||||
if (pyType != null) {
|
||||
return pyType;
|
||||
}
|
||||
PyType type = getTypeFromDocString();
|
||||
if (type != null) {
|
||||
return type;
|
||||
}
|
||||
if (!context.maySwitchToAST(this)) {
|
||||
final PsiElement value = getStub() != null ? findAssignedValueByStub(context) : findAssignedValue();
|
||||
if (value instanceof PyTypedElement) {
|
||||
final PyType type = context.getType((PyTypedElement)value);
|
||||
type = context.getType((PyTypedElement)value);
|
||||
if (type instanceof PyNoneType) {
|
||||
return null;
|
||||
}
|
||||
@@ -135,10 +135,6 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
|
||||
}
|
||||
return null;
|
||||
}
|
||||
PyType type = getTypeFromDocString(this);
|
||||
if (type != null) {
|
||||
return type;
|
||||
}
|
||||
type = getTypeFromComment(this);
|
||||
if (type != null) {
|
||||
return type;
|
||||
@@ -249,29 +245,27 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PyType getTypeFromDocString(PyTargetExpressionImpl targetExpression) {
|
||||
private PyType getTypeFromDocString() {
|
||||
String typeName = null;
|
||||
final String docString = PyPsiUtils.strValue(DocStringUtil.getAttributeDocString(targetExpression));
|
||||
if (docString != null) {
|
||||
StructuredDocString targetDocString = DocStringUtil.parse(docString);
|
||||
if (targetDocString != null) {
|
||||
typeName = targetDocString.getParamType(null);
|
||||
if (typeName == null) {
|
||||
typeName = targetDocString.getParamType(targetExpression.getName());
|
||||
}
|
||||
final String name = getName();
|
||||
final StructuredDocString targetDocString = getStructuredDocString();
|
||||
if (targetDocString != null) {
|
||||
typeName = targetDocString.getParamType(null);
|
||||
if (typeName == null) {
|
||||
typeName = targetDocString.getParamType(name);
|
||||
}
|
||||
}
|
||||
if (typeName == null && PyUtil.isAttribute(targetExpression)) {
|
||||
final PyClass cls = targetExpression.getContainingClass();
|
||||
if (typeName == null && PyUtil.isAttribute(this)) {
|
||||
final PyClass cls = getContainingClass();
|
||||
if (cls != null) {
|
||||
final StructuredDocString classDocString = cls.getStructuredDocString();
|
||||
if (classDocString != null) {
|
||||
typeName = classDocString.getParamType(targetExpression.getName());
|
||||
typeName = classDocString.getParamType(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeName != null) {
|
||||
return PyTypeParser.getTypeByName(targetExpression, typeName);
|
||||
return PyTypeParser.getTypeByName(this, typeName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -613,4 +607,40 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
|
||||
}
|
||||
return super.getElementLocation();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getDocStringValue() {
|
||||
final PyTargetExpressionStub stub = getStub();
|
||||
if (stub != null) {
|
||||
return stub.getDocString();
|
||||
}
|
||||
return DocStringUtil.getDocStringValue(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public StructuredDocString getStructuredDocString() {
|
||||
return DocStringUtil.getStructuredDocString(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PyStringLiteralExpression getDocStringExpression() {
|
||||
final PsiElement parent = getParent();
|
||||
if (parent instanceof PyAssignmentStatement) {
|
||||
final PyAssignmentStatement assignment = (PyAssignmentStatement)parent;
|
||||
PsiElement nextSibling = assignment.getNextSibling();
|
||||
while (nextSibling != null && (nextSibling instanceof PsiWhiteSpace || nextSibling instanceof PsiComment)) {
|
||||
nextSibling = nextSibling.getNextSibling();
|
||||
}
|
||||
if (nextSibling instanceof PyExpressionStatement) {
|
||||
final PyExpression expression = ((PyExpressionStatement)nextSibling).getExpression();
|
||||
if (expression instanceof PyStringLiteralExpression) {
|
||||
return (PyStringLiteralExpression)expression;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.io.StringRef;
|
||||
import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.documentation.DocStringUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyQualifiedName;
|
||||
import com.jetbrains.python.psi.impl.PyTargetExpressionImpl;
|
||||
@@ -48,10 +49,11 @@ public class PyTargetExpressionElementType extends PyStubElementType<PyTargetExp
|
||||
public PyTargetExpressionStub createStub(@NotNull final PyTargetExpression psi, final StubElement parentStub) {
|
||||
final String name = psi.getName();
|
||||
final PyExpression assignedValue = psi.findAssignedValue();
|
||||
final String docString = DocStringUtil.getDocStringValue(psi);
|
||||
for (CustomTargetExpressionStubType customStubType : getCustomStubTypes()) {
|
||||
CustomTargetExpressionStub customStub = customStubType.createStub(psi);
|
||||
if (customStub != null) {
|
||||
return new PyTargetExpressionStubImpl(name, customStub, parentStub);
|
||||
return new PyTargetExpressionStubImpl(name, docString, customStub, parentStub);
|
||||
}
|
||||
}
|
||||
PyTargetExpressionStub.InitializerType initializerType = PyTargetExpressionStub.InitializerType.Other;
|
||||
@@ -67,12 +69,14 @@ public class PyTargetExpressionElementType extends PyStubElementType<PyTargetExp
|
||||
initializer = ((PyReferenceExpression) callee).asQualifiedName();
|
||||
}
|
||||
}
|
||||
return new PyTargetExpressionStubImpl(name, initializerType, initializer, psi.getQualifier() != null, parentStub);
|
||||
return new PyTargetExpressionStubImpl(name, docString, initializerType, initializer, psi.getQualifier() != null, parentStub);
|
||||
}
|
||||
|
||||
public void serialize(@NotNull final PyTargetExpressionStub stub, @NotNull final StubOutputStream stream)
|
||||
throws IOException {
|
||||
stream.writeName(stub.getName());
|
||||
final String docString = stub.getDocString();
|
||||
stream.writeUTFFast(docString != null ? docString : "");
|
||||
stream.writeVarInt(stub.getInitializerType().getIndex());
|
||||
final CustomTargetExpressionStub customStub = stub.getCustomStub(CustomTargetExpressionStub.class);
|
||||
if (customStub != null) {
|
||||
@@ -89,20 +93,24 @@ public class PyTargetExpressionElementType extends PyStubElementType<PyTargetExp
|
||||
public PyTargetExpressionStub deserialize(@NotNull final StubInputStream stream, final StubElement parentStub)
|
||||
throws IOException {
|
||||
String name = StringRef.toString(stream.readName());
|
||||
String docString = stream.readUTFFast();
|
||||
if (docString.isEmpty()) {
|
||||
docString = null;
|
||||
}
|
||||
PyTargetExpressionStub.InitializerType initializerType = PyTargetExpressionStub.InitializerType.fromIndex(stream.readVarInt());
|
||||
if (initializerType == PyTargetExpressionStub.InitializerType.Custom) {
|
||||
final String typeName = stream.readName().getString();
|
||||
for(CustomTargetExpressionStubType type: getCustomStubTypes()) {
|
||||
if (type.getClass().getCanonicalName().equals(typeName)) {
|
||||
CustomTargetExpressionStub stub = type.deserializeStub(stream);
|
||||
return new PyTargetExpressionStubImpl(name, stub, parentStub);
|
||||
return new PyTargetExpressionStubImpl(name, docString, stub, parentStub);
|
||||
}
|
||||
}
|
||||
throw new IOException("Unknown custom stub type " + typeName);
|
||||
}
|
||||
PyQualifiedName initializer = PyQualifiedName.deserialize(stream);
|
||||
boolean isQualified = stream.readBoolean();
|
||||
return new PyTargetExpressionStubImpl(name, initializerType, initializer, isQualified, parentStub);
|
||||
return new PyTargetExpressionStubImpl(name, docString, initializerType, initializer, isQualified, parentStub);
|
||||
}
|
||||
|
||||
public boolean shouldCreateStub(final ASTNode node) {
|
||||
|
||||
@@ -16,19 +16,24 @@ public class PyTargetExpressionStubImpl extends StubBase<PyTargetExpression> imp
|
||||
private final InitializerType myInitializerType;
|
||||
private final PyQualifiedName myInitializer;
|
||||
private final boolean myQualified;
|
||||
@Nullable private final String myDocString;
|
||||
|
||||
private final CustomTargetExpressionStub myCustomStub;
|
||||
|
||||
public PyTargetExpressionStubImpl(String name, CustomTargetExpressionStub customStub, StubElement parent) {
|
||||
public PyTargetExpressionStubImpl(String name,
|
||||
@Nullable String docString,
|
||||
CustomTargetExpressionStub customStub,
|
||||
StubElement parent) {
|
||||
super(parent, PyElementTypes.TARGET_EXPRESSION);
|
||||
myName = name;
|
||||
myInitializerType = InitializerType.Custom;
|
||||
myInitializer = null;
|
||||
myQualified = false;
|
||||
myCustomStub = customStub;
|
||||
myDocString = docString;
|
||||
}
|
||||
|
||||
public PyTargetExpressionStubImpl(final String name, final InitializerType initializerType,
|
||||
public PyTargetExpressionStubImpl(final String name, @Nullable String docString, final InitializerType initializerType,
|
||||
final PyQualifiedName initializer,
|
||||
final boolean qualified,
|
||||
final StubElement parentStub) {
|
||||
@@ -39,6 +44,7 @@ public class PyTargetExpressionStubImpl extends StubBase<PyTargetExpression> imp
|
||||
myInitializer = initializer;
|
||||
myQualified = qualified;
|
||||
myCustomStub = null;
|
||||
myDocString = docString;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@@ -67,6 +73,12 @@ public class PyTargetExpressionStubImpl extends StubBase<PyTargetExpression> imp
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getDocString() {
|
||||
return myDocString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PyTargetExpressionStub(name=" + myName + ")";
|
||||
|
||||
@@ -16,6 +16,11 @@ import java.util.Collection;
|
||||
public class PyInstanceAttributeIndex extends StringStubIndexExtension<PyTargetExpression> {
|
||||
public static final StubIndexKey<String, PyTargetExpression> KEY = StubIndexKey.createIndexKey("Py.instanceAttribute.name");
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return super.getVersion() + 1;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public StubIndexKey<String, PyTargetExpression> getKey() {
|
||||
|
||||
@@ -16,6 +16,11 @@ import java.util.Collection;
|
||||
public class PyVariableNameIndex extends StringStubIndexExtension<PyTargetExpression> {
|
||||
public static final StubIndexKey<String, PyTargetExpression> KEY = StubIndexKey.createIndexKey("Py.variable.shortName");
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return super.getVersion() + 1;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StubIndexKey<String, PyTargetExpression> getKey() {
|
||||
return KEY;
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
class C(object):
|
||||
foo = None
|
||||
"""Foo docstring."""
|
||||
|
||||
bar = None
|
||||
|
||||
@@ -402,6 +402,14 @@ public class PyStubsTest extends PyTestCase {
|
||||
}
|
||||
classes = PyClassNameIndex.find("Foo", project, GlobalSearchScope.allScope(project));
|
||||
assertEquals(classes.size(), 1);
|
||||
}
|
||||
|
||||
public void testTargetExpressionDocString() {
|
||||
final PyFile file = getTestFile();
|
||||
final PyClass c = file.findTopLevelClass("C");
|
||||
assertNotNull(c);
|
||||
final PyTargetExpression foo = c.findClassAttribute("foo", false);
|
||||
final String docString = foo.getDocStringValue();
|
||||
assertEquals("Foo docstring.", docString);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user