Links for function types in quickdoc (PY-3404).

This commit is contained in:
Dmitry Trofimov
2012-11-04 19:11:48 +01:00
parent 023df74d6d
commit e38b35ada5
14 changed files with 343 additions and 242 deletions
@@ -219,7 +219,7 @@ class PyDocumentationBuilder {
}
}
else if (followed != null && outer instanceof PyReferenceExpression) {
myBody.addItem("\nInferred type: ");
myBody.addItem(combUp("\nInferred type: "));
PythonDocumentationProvider.describeExpressionTypeWithLinks(myBody, (PyReferenceExpression)outer, TypeEvalContext.slow());
}
if (myBody.isEmpty() && myEpilog.isEmpty()) {
@@ -0,0 +1,314 @@
package com.jetbrains.python.documentation;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyNamedParameter;
import com.jetbrains.python.psi.PyParameter;
import com.jetbrains.python.psi.types.*;
import com.jetbrains.python.toolbox.ChainIterable;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Map;
import static com.jetbrains.python.documentation.DocumentationBuilderKit.$;
import static com.jetbrains.python.documentation.DocumentationBuilderKit.combUp;
/**
* @author traff
*/
public class PyTypeModelBuilder {
@NonNls static final String UNKNOWN = "unknown";
private final Map<PyType, TypeModel> myVisited = Maps.newHashMap();
private final TypeEvalContext myContext;
PyTypeModelBuilder(TypeEvalContext context) {
this.myContext = context;
}
abstract static class TypeModel {
abstract void accept(TypeVisitor visitor);
public String asString() {
TypeToStringVisitor visitor = new TypeToStringVisitor();
this.accept(visitor);
return visitor.getString();
}
public void toBodyWithLinks(@NotNull ChainIterable<String> body, @NotNull PsiElement anchor) {
TypeToBodyWithLinksVisitor visitor = new TypeToBodyWithLinksVisitor(body, anchor);
this.accept(visitor);
}
}
static class OneOf extends TypeModel {
private Collection<TypeModel> oneOfTypes;
private OneOf(Collection<TypeModel> oneOfTypes) {
this.oneOfTypes = oneOfTypes;
}
@Override
void accept(TypeVisitor visitor) {
visitor.oneOf(this);
}
}
static class CollectionOf extends TypeModel {
private String collectionName;
private TypeModel elementType;
private CollectionOf(String collectionName, TypeModel elementType) {
this.collectionName = collectionName;
this.elementType = elementType;
}
@Override
void accept(TypeVisitor visitor) {
visitor.collectionOf(this);
}
}
static class NamedType extends TypeModel {
private String name;
private NamedType(String name) {
this.name = name;
}
@Override
void accept(TypeVisitor visitor) {
visitor.name(this.name);
}
}
private static TypeModel _(String name) {
return new NamedType(name);
}
static class FunctionType extends TypeModel {
private TypeModel returnType;
private Collection<TypeModel> parameters;
FunctionType(@NotNull TypeModel returnType, Collection<TypeModel> parameters) {
this.returnType = returnType;
this.parameters = parameters;
}
@Override
void accept(TypeVisitor visitor) {
visitor.function(this);
}
}
static class ParamType extends TypeModel {
private final String name;
private final TypeModel type;
private ParamType(String name, @Nullable TypeModel type) {
this.name = name;
this.type = type;
}
@Override
void accept(TypeVisitor visitor) {
visitor.param(this);
}
}
/**
* Builds tree-like type model for PyType
*
* @param type
* @param allowUnions
* @return
*/
public TypeModel build(@Nullable PyType type,
boolean allowUnions) {
final TypeModel evaluated = myVisited.get(type);
if (evaluated != null) {
return evaluated;
}
if (myVisited.containsKey(type)) { //already evaluating?
return type != null ? _(type.getName()) : _(UNKNOWN);
}
myVisited.put(type, null); //mark as evaluating
TypeModel result = null;
if (type instanceof PyTypeReference) {
final PyType resolved = ((PyTypeReference)type).resolve(null, myContext);
if (resolved != null) {
result = build(resolved, true);
}
}
else if (type instanceof PyCollectionType) {
final String name = type.getName();
final PyType elementType = ((PyCollectionType)type).getElementType(myContext);
if (elementType != null) {
result = new CollectionOf(name, build(elementType, true));
}
}
else if (type instanceof PyUnionType && allowUnions) {
if (type instanceof PyDynamicallyEvaluatedType) {
result = build(((PyDynamicallyEvaluatedType)type).exclude(null, myContext), true);
}
else {
result = new OneOf(
Collections2.transform(((PyUnionType)type).getMembers(), new Function<PyType, TypeModel>() {
@Override
public TypeModel apply(PyType t) {
return build(t, false);
}
}));
}
}
if (result == null) {
result = type != null ? _(type.getName()) : _(UNKNOWN);
}
myVisited.put(type, result);
return result;
}
public TypeModel build(PyFunction function) {
final PyType returnType = function.getReturnType(myContext, null);
return new FunctionType(build(returnType, true), Collections2.transform(Lists.newArrayList(function.getParameterList().getParameters()),
new Function<PyParameter, TypeModel>() {
@Override
public TypeModel apply(PyParameter p) {
final PyNamedParameter np = p.getAsNamed();
if (np != null) {
TypeModel paramType =
_(UNKNOWN);
final PyType t = np.getType(myContext);
if (t != null) {
paramType = build(t, true);
}
return new ParamType(np.getName(), paramType);
}
return new ParamType(p.toString(), null);
}
}));
}
private interface TypeVisitor {
void oneOf(OneOf oneOf);
void collectionOf(CollectionOf collectionOf);
void name(String name);
void function(FunctionType type);
void param(ParamType text);
}
private static class TypeToStringVisitor extends TypeNameVisitor {
private final StringBuilder myStringBuilder = new StringBuilder();
@Override
protected void add(String s) {
myStringBuilder.append(s);
}
@Override
protected void addType(String name) {
add(name);
}
public String getString() {
return myStringBuilder.toString();
}
}
private static class TypeToBodyWithLinksVisitor extends TypeNameVisitor {
private ChainIterable<String> myBody;
private PsiElement myAnchor;
public TypeToBodyWithLinksVisitor(ChainIterable<String> body, PsiElement anchor) {
myBody = body;
myAnchor = anchor;
}
@Override
protected void add(String s) {
myBody.addItem(combUp(s));
}
@Override
protected void addType(String name) {
PyType type = PyTypeParser.getTypeByName(myAnchor, name);
if (type instanceof PyClassType) {
myBody.addWith(new DocumentationBuilderKit.LinkWrapper(PythonDocumentationProvider.LINK_TYPE_TYPENAME + name),
$(name));
}
else {
add(name);
}
}
}
private abstract static class TypeNameVisitor implements TypeVisitor {
@Override
public void oneOf(OneOf oneOf) {
add("one of (");
processListCommaSeparated(oneOf.oneOfTypes);
add(")");
}
private void processListCommaSeparated(Collection<TypeModel> list) {
boolean first = true;
for (TypeModel t : list) {
if (!first) {
add(", ");
}
else {
first = false;
}
t.accept(this);
}
}
protected abstract void add(String s);
@Override
public void collectionOf(CollectionOf collectionOf) {
addType(collectionOf.collectionName);
add(" of ");
collectionOf.elementType.accept(this);
}
protected abstract void addType(String name);
@Override
public void name(String name) {
addType(name);
}
@Override
public void function(FunctionType function) {
add("(");
processListCommaSeparated(function.parameters);
add(") -> ");
function.returnType.accept(this);
add("\n");
}
@Override
public void param(ParamType param) {
add(param.name);
if (param.type != null) {
add(": ");
param.type.accept(this);
}
}
}
}
@@ -1,7 +1,5 @@
package com.jetbrains.python.documentation;
import com.google.common.collect.Collections2;
import com.google.common.collect.Maps;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.lang.documentation.AbstractDocumentationProvider;
import com.intellij.lang.documentation.ExternalDocumentationProvider;
@@ -19,7 +17,6 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Function;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
import com.jetbrains.python.console.PydevConsoleRunner;
@@ -57,8 +54,6 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
@NonNls private static final String RST_PREFIX = ":";
@NonNls private static final String EPYDOC_PREFIX = "@";
@NonNls private static final String UNKNOWN = "unknown";
// provides ctrl+hover info
public String getQuickNavigateInfo(final PsiElement element, PsiElement originalElement) {
if (element instanceof PyFunction) {
@@ -125,7 +120,7 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
cat.addItem(escaper.apply(PyUtil.getReadableRepr(fun.getParameterList(), false)));
if (!PyNames.INIT.equals(name)) {
cat.addItem(escaper.apply("\nInferred type: "));
cat.addItem(escaper.apply(getTypeDescription(fun)));
getTypeDescription(fun, cat);
}
return cat;
}
@@ -156,30 +151,24 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
public static String getTypeDescription(@NotNull PyFunction fun) {
final TypeEvalContext context = TypeEvalContext.slow();
final PyType returnType = fun.getReturnType(context, null);
return String.format("(%s) -> %s\n",
StringUtil.join(fun.getParameterList().getParameters(),
new Function<PyParameter, String>() {
@Override
public String fun(PyParameter p) {
final PyNamedParameter np = p.getAsNamed();
if (np != null) {
String name = UNKNOWN;
final PyType t = np.getType(context);
if (t != null) {
name = getTypeName(t, context);
}
return String.format("%s: %s", np.getName(), name);
}
return p.toString();
}
}, ", "),
returnType != null ? getTypeName(returnType, context) : UNKNOWN);
PyTypeModelBuilder builder = new PyTypeModelBuilder(context);
return builder.build(fun).asString();
}
public static void getTypeDescription(@NotNull PyFunction fun, ChainIterable<String> body) {
final TypeEvalContext context = TypeEvalContext.slow();
PyTypeModelBuilder builder = new PyTypeModelBuilder(context);
builder.build(fun).toBodyWithLinks(body, fun);
}
public static String getTypeName(@Nullable PyType type, @NotNull final TypeEvalContext context) {
TypeNameBuilder builder = new TypeNameBuilder(context);
return builder.build(type, true).asString();
PyTypeModelBuilder.TypeModel typeModel = buildTypeModel(type, context);
return typeModel.asString();
}
private static PyTypeModelBuilder.TypeModel buildTypeModel(PyType type, TypeEvalContext context) {
PyTypeModelBuilder builder = new PyTypeModelBuilder(context);
return builder.build(type, true);
}
public static void describeExpressionTypeWithLinks(ChainIterable<String> body,
@@ -192,212 +181,10 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
public static void describeTypeWithLinks(ChainIterable<String> body,
PsiElement anchor,
PyType type, TypeEvalContext context) {
TypeNameBuilder builder = new TypeNameBuilder(context);
PyTypeModelBuilder builder = new PyTypeModelBuilder(context);
builder.build(type, true).toBodyWithLinks(body, anchor);
}
private static class TypeNameBuilder {
private final Map<PyType, Type> myVisited = Maps.newHashMap();
private final TypeEvalContext myContext;
private TypeNameBuilder(TypeEvalContext context) {
this.myContext = context;
}
private abstract static class Type {
abstract void accept(TypeVisitor visitor);
public String asString() {
TypeToStringVisitor visitor = new TypeToStringVisitor();
this.accept(visitor);
return visitor.getString();
}
public void toBodyWithLinks(@NotNull ChainIterable<String> body, @NotNull PsiElement anchor) {
TypeToBodyWithLinksVisitor visitor = new TypeToBodyWithLinksVisitor(body, anchor);
this.accept(visitor);
}
}
private static class OneOf extends Type {
private Collection<Type> oneOfTypes;
private OneOf(Collection<Type> oneOfTypes) {
this.oneOfTypes = oneOfTypes;
}
@Override
void accept(TypeVisitor visitor) {
visitor.oneOf(this);
}
}
private static class CollectionOf extends Type {
private String collectionName;
private Type elementType;
private CollectionOf(String collectionName, Type elementType) {
this.collectionName = collectionName;
this.elementType = elementType;
}
@Override
void accept(TypeVisitor visitor) {
visitor.collectionOf(this);
}
}
private static class NamedType extends Type {
private String name;
private NamedType(String name) {
this.name = name;
}
@Override
void accept(TypeVisitor visitor) {
visitor.name(this.name);
}
}
private static Type _(String name) {
return new NamedType(name);
}
private Type build(@Nullable PyType type,
boolean allowUnions) {
final Type evaluated = myVisited.get(type);
if (evaluated != null) {
return evaluated;
}
if (myVisited.containsKey(type)) { //already evaluating?
return type != null ? _(type.getName()) : _(UNKNOWN);
}
myVisited.put(type, null); //mark as evaluating
Type result = null;
if (type instanceof PyTypeReference) {
final PyType resolved = ((PyTypeReference)type).resolve(null, myContext);
if (resolved != null) {
result = build(resolved, true);
}
}
else if (type instanceof PyCollectionType) {
final String name = type.getName();
final PyType elementType = ((PyCollectionType)type).getElementType(myContext);
if (elementType != null) {
result = new CollectionOf(name, build(elementType, true));
}
}
else if (type instanceof PyUnionType && allowUnions) {
if (type instanceof PyDynamicallyEvaluatedType) {
result = build(((PyDynamicallyEvaluatedType)type).exclude(null, myContext), true);
}
else {
result = new OneOf(Collections2.transform(((PyUnionType)type).getMembers(), new com.google.common.base.Function<PyType, Type>() {
@Override
public Type apply(PyType t) {
return build(t, false);
}
}));
}
}
if (result == null) {
result = type != null ? _(type.getName()) : _(UNKNOWN);
}
myVisited.put(type, result);
return result;
}
private interface TypeVisitor {
void oneOf(OneOf oneOf);
void collectionOf(CollectionOf collectionOf);
void name(String name);
}
private static class TypeToStringVisitor extends TypeNameVisitor {
private final StringBuilder myStringBuilder = new StringBuilder();
@Override
protected void add(String s) {
myStringBuilder.append(s);
}
@Override
protected void addType(String name) {
add(name);
}
public String getString() {
return myStringBuilder.toString();
}
}
private static class TypeToBodyWithLinksVisitor extends TypeNameVisitor {
private ChainIterable<String> myBody;
private PsiElement myAnchor;
public TypeToBodyWithLinksVisitor(ChainIterable<String> body, PsiElement anchor) {
myBody = body;
myAnchor = anchor;
}
@Override
protected void add(String s) {
myBody.addItem(combUp(s));
}
@Override
protected void addType(String name) {
PyType type = PyTypeParser.getTypeByName(myAnchor, name);
if (type instanceof PyClassType) {
myBody.addWith(new LinkWrapper(LINK_TYPE_TYPENAME + name),
$(name));
}
else {
add(name);
}
}
}
private abstract static class TypeNameVisitor implements TypeVisitor {
@Override
public void oneOf(OneOf oneOf) {
add("one of (");
boolean first = true;
for (Type t : oneOf.oneOfTypes) {
if (!first) {
add(", ");
}
else {
first = false;
}
t.accept(this);
}
add(")");
}
protected abstract void add(String s);
@Override
public void collectionOf(CollectionOf collectionOf) {
addType(collectionOf.collectionName);
add(" of ");
collectionOf.elementType.accept(this);
}
protected abstract void addType(String name);
@Override
public void name(String name) {
addType(name);
}
}
}
static ChainIterable<String> describeDecorators(PyDecoratable what, FP.Lambda1<Iterable<String>, Iterable<String>> deco_name_wrapper,
String deco_separator, FP.Lambda1<String, String> escaper) {
@@ -1,2 +1,2 @@
def foo(arg)
Inferred type: (arg: unknown) -> int
Inferred type: (arg:&nbsp;unknown)&nbsp;-&gt;&nbsp;<a href="psi_element://#typename#int">int</a><br>
@@ -1,3 +1,3 @@
class A
def f(self)
Inferred type: (self: A) -> int
Inferred type: (self:&nbsp;<a href="psi_element://#typename#A">A</a>)&nbsp;-&gt;&nbsp;<a href="psi_element://#typename#int">int</a><br>
@@ -1 +1 @@
<html><body><code><small>class <a href="psi_element://#class#">B</a>(<a href="psi_element://#parent#A">A</a>)</small><br><br>def <b>foo</b>(self)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;B)&nbsp;-&gt;&nbsp;None<br></code><br><br><i>Documentation is missing.</i> The following is copied from <code><a href="psi_element://#parent#A">A</a>.foo</code>.<br><br><code>Doc&nbsp;from&nbsp;A.foo.</code></body></html>
<html><body><code><small>class <a href="psi_element://#class#">B</a>(<a href="psi_element://#parent#A">A</a>)</small><br><br>def <b>foo</b>(self)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;<a href="psi_element://#typename#B">B</a>)&nbsp;-&gt;&nbsp;None<br></code><br><br><i>Documentation is missing.</i> The following is copied from <code><a href="psi_element://#parent#A">A</a>.foo</code>.<br><br><code>Doc&nbsp;from&nbsp;A.foo.</code></body></html>
+1 -1
View File
@@ -1 +1 @@
<html><body><code><small>class <a href="psi_element://#class#">Foo</a></small><br><br>@<i>deco</i><br>def <b>meth</b>(self)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;Foo)&nbsp;-&gt;&nbsp;None<br><br><br>Doc&nbsp;of&nbsp;meth.<br></code></body></html>
<html><body><code><small>class <a href="psi_element://#class#">Foo</a></small><br><br>@<i>deco</i><br>def <b>meth</b>(self)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;<a href="psi_element://#typename#Foo">Foo</a>)&nbsp;-&gt;&nbsp;None<br><br><br>Doc&nbsp;of&nbsp;meth.<br></code></body></html>
+1 -1
View File
@@ -1 +1 @@
<html><body>property <b><code>x</code></b> of class <a href="psi_element://#class#">A</a>(<a href="psi_element://#parent#object">object</a>)<br><i>Copied from getter:</i><br>Does things to X<code><br><br>@<i>x.deleter</i><br>def <b>x</b>(self,&nbsp;v)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;A,&nbsp;v:&nbsp;unknown)&nbsp;-&gt;&nbsp;None<br><br>Deletes&nbsp;X</code><small><br><br>Deleter of property</small><br></body></html>
<html><body>property <b><code>x</code></b> of class <a href="psi_element://#class#">A</a>(<a href="psi_element://#parent#object">object</a>)<br><i>Copied from getter:</i><br>Does things to X<code><br><br>@<i>x.deleter</i><br>def <b>x</b>(self,&nbsp;v)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;<a href="psi_element://#typename#A">A</a>,&nbsp;v:&nbsp;unknown)&nbsp;-&gt;&nbsp;None<br><br>Deletes&nbsp;X</code><small><br><br>Deleter of property</small><br></body></html>
+1 -1
View File
@@ -1 +1 @@
<html><body>property <b><code>x</code></b> of class <a href="psi_element://#class#">A</a>(<a href="psi_element://#parent#object">object</a>)<code><br><br>@<i>property</i><br>def <b>x</b>(self)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;A)&nbsp;-&gt;&nbsp;int<br><br>Does&nbsp;things&nbsp;to&nbsp;X</code><small><br><br>Getter of property</small><br></body></html>
<html><body>property <b><code>x</code></b> of class <a href="psi_element://#class#">A</a>(<a href="psi_element://#parent#object">object</a>)<code><br><br>@<i>property</i><br>def <b>x</b>(self)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;<a href="psi_element://#typename#A">A</a>)&nbsp;-&gt;&nbsp;<a href="psi_element://#typename#int">int</a><br><br>Does&nbsp;things&nbsp;to&nbsp;X</code><small><br><br>Getter of property</small><br></body></html>
+1 -1
View File
@@ -1 +1 @@
<html><body>property <b><code>x</code></b> of class <a href="psi_element://#class#">A</a>(<a href="psi_element://#parent#object">object</a>)<br><i>Copied from getter:</i><br>Does things to X<code><br><br>@<i>x.setter</i><br>def <b>x</b>(self,&nbsp;v)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;A,&nbsp;v:&nbsp;unknown)&nbsp;-&gt;&nbsp;None<br><br>Sets&nbsp;X</code><small><br><br>Setter of property</small><br></body></html>
<html><body>property <b><code>x</code></b> of class <a href="psi_element://#class#">A</a>(<a href="psi_element://#parent#object">object</a>)<br><i>Copied from getter:</i><br>Does things to X<code><br><br>@<i>x.setter</i><br>def <b>x</b>(self,&nbsp;v)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;<a href="psi_element://#typename#A">A</a>,&nbsp;v:&nbsp;unknown)&nbsp;-&gt;&nbsp;None<br><br>Sets&nbsp;X</code><small><br><br>Setter of property</small><br></body></html>
+1 -1
View File
@@ -1 +1 @@
<html><body>property <b><code>x</code></b> of class <a href="psi_element://#class#">A</a>(<a href="psi_element://#parent#object">object</a>)<code><br><br>def <b>__getX</b>(self)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;A)&nbsp;-&gt;&nbsp;unknown<br><br>Doc&nbsp;of&nbsp;getter</code><small><br><br>Deleter of property</small><br></body></html>
<html><body>property <b><code>x</code></b> of class <a href="psi_element://#class#">A</a>(<a href="psi_element://#parent#object">object</a>)<code><br><br>def <b>__getX</b>(self)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;<a href="psi_element://#typename#A">A</a>)&nbsp;-&gt;&nbsp;unknown<br><br>Doc&nbsp;of&nbsp;getter</code><small><br><br>Deleter of property</small><br></body></html>
+1 -1
View File
@@ -1 +1 @@
<html><body>property <b><code>x</code></b> of class <a href="psi_element://#class#">A</a>(<a href="psi_element://#parent#object">object</a>)<code><br><br>def <b>__getX</b>(self)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;A)&nbsp;-&gt;&nbsp;unknown<br><br>Doc&nbsp;of&nbsp;getter</code><small><br><br>Getter of property</small><br></body></html>
<html><body>property <b><code>x</code></b> of class <a href="psi_element://#class#">A</a>(<a href="psi_element://#parent#object">object</a>)<code><br><br>def <b>__getX</b>(self)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;<a href="psi_element://#typename#A">A</a>)&nbsp;-&gt;&nbsp;unknown<br><br>Doc&nbsp;of&nbsp;getter</code><small><br><br>Getter of property</small><br></body></html>
+1 -1
View File
@@ -1 +1 @@
<html><body>property <b><code>x</code></b> of class <a href="psi_element://#class#">A</a>(<a href="psi_element://#parent#object">object</a>)<code><br><br>def <b>__getX</b>(self,&nbsp;x)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;A,&nbsp;x:&nbsp;unknown)&nbsp;-&gt;&nbsp;None<br><br>Doc&nbsp;of&nbsp;getter</code><small><br><br>Setter of property</small><br></body></html>
<html><body>property <b><code>x</code></b> of class <a href="psi_element://#class#">A</a>(<a href="psi_element://#parent#object">object</a>)<code><br><br>def <b>__getX</b>(self,&nbsp;x)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;<a href="psi_element://#typename#A">A</a>,&nbsp;x:&nbsp;unknown)&nbsp;-&gt;&nbsp;None<br><br>Doc&nbsp;of&nbsp;getter</code><small><br><br>Setter of property</small><br></body></html>
+1 -1
View File
@@ -1 +1 @@
<html><body><small>Assigned to <code>y</code><br></small><code><br>Inferred type: one&nbsp;of&nbsp;(<a href="psi_element://#typename#int">int</a>,&nbsp;<a href="psi_element://#typename#str">str</a>)</code></body></html>
<html><body><small>Assigned to <code>y</code><br></small><code><br>Inferred&nbsp;type:&nbsp;one&nbsp;of&nbsp;(<a href="psi_element://#typename#int">int</a>,&nbsp;<a href="psi_element://#typename#str">str</a>)</code></body></html>