mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-79201 reveal inferred variance of type var
GitOrigin-RevId: 300ca43057147f83290e2e232c4b8fa91d643876
This commit is contained in:
committed by
intellij-monorepo-bot
parent
15702a130d
commit
4ffced1811
+11
-11
@@ -185,7 +185,7 @@ public final class PyDocumentationBuilder {
|
||||
|
||||
|
||||
if (myBody.isEmpty() && myContent.isEmpty()) {
|
||||
return null; // got nothing substantial to say!
|
||||
return null; // got nothing significant to say!
|
||||
}
|
||||
else {
|
||||
final HtmlBuilder result = new HtmlBuilder();
|
||||
@@ -217,7 +217,7 @@ public final class PyDocumentationBuilder {
|
||||
|
||||
if (elementType == PyTokenTypes.FROM_KEYWORD) {
|
||||
// We want to show yield doc in 'yield from ...' expressions when hover to 'from',
|
||||
// but there is no particular PyStatement for 'yield' keyword, therefore we make such a check.
|
||||
// but there is no particular PyStatement for 'yield' keyword; therefore, we make such a check.
|
||||
if (parentStatement.getFirstChild() instanceof PyYieldExpression) {
|
||||
return PyNames.YIELD;
|
||||
}
|
||||
@@ -302,7 +302,7 @@ public final class PyDocumentationBuilder {
|
||||
}
|
||||
if (link != null && typeParamName != null) {
|
||||
myBody.appendRaw(PyPsiBundle.message("QDOC.type.parameter.name.of.link", HtmlChunk.text(typeParamName).bold(), link)).br();
|
||||
myBody.append(PythonDocumentationProvider.describeTypeParameter(typeParameter, true, myContext));
|
||||
myBody.append(PythonDocumentationProvider.describeTypeParameter(typeParameter, myOriginalElement, true, myContext));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,7 +476,7 @@ public final class PyDocumentationBuilder {
|
||||
}
|
||||
if (effectiveDocstring != null) {
|
||||
addFunctionSpecificSections(effectiveDocstring, pyFunction);
|
||||
// if function is init without doc we will take attributes from the class doc
|
||||
// if the function is init without a doc, we will take attributes from the class doc
|
||||
if (effectiveDocstring != ownDocstring && PyUtil.isInitOrNewMethod(pyFunction)) {
|
||||
addAttributesSection(effectiveDocstring);
|
||||
}
|
||||
@@ -516,7 +516,7 @@ public final class PyDocumentationBuilder {
|
||||
|
||||
if (owner instanceof PyClass pyClass) {
|
||||
final PyFunction init = pyClass.findMethodByName(PyNames.INIT, false, myContext);
|
||||
// if class doesn't have any doc return init doc
|
||||
// if the class doesn't have any doc return init doc
|
||||
if (init != null) {
|
||||
return getEffectiveDocStringExpression(init);
|
||||
}
|
||||
@@ -560,7 +560,7 @@ public final class PyDocumentationBuilder {
|
||||
}
|
||||
myBody.br();
|
||||
}
|
||||
// if there is no separate doc for attribute we will try to take it from class doc
|
||||
// if there is no separate doc for attribute, we will try to take it from class doc
|
||||
if (getEffectiveDocStringExpression(target) == null) {
|
||||
final PyStringLiteralExpression docString = getEffectiveDocStringExpression(containingClass);
|
||||
if (docString != null) {
|
||||
@@ -572,7 +572,7 @@ public final class PyDocumentationBuilder {
|
||||
}
|
||||
}
|
||||
}
|
||||
myBody.append(PythonDocumentationProvider.describeTarget(target, myContext));
|
||||
myBody.append(PythonDocumentationProvider.describeTarget(target, myOriginalElement, myContext));
|
||||
}
|
||||
|
||||
private void addAttributesSection(@NotNull PyStringLiteralExpression docstring) {
|
||||
@@ -635,7 +635,7 @@ public final class PyDocumentationBuilder {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Reference expression can be passed as the target element in Python console
|
||||
// Reference expression can be passed as the target element in the Python console
|
||||
if (myElement instanceof PyReferenceExpression) {
|
||||
final PsiElement resolved = resolve((PyReferenceExpression)myElement);
|
||||
if (resolved != null) {
|
||||
@@ -669,7 +669,7 @@ public final class PyDocumentationBuilder {
|
||||
final boolean isConstructor = PyUtil.isInitOrNewMethod(pyFunction);
|
||||
List<PyClass> classes = pyClass.getAncestorClasses(myContext);
|
||||
if (isConstructor) {
|
||||
// look at our own class again and maybe inherit class's doc
|
||||
// look at our own class again and maybe inherit the class's doc
|
||||
classes = ContainerUtil.prepend(classes, pyClass);
|
||||
}
|
||||
for (PyClass ancestor : classes) {
|
||||
@@ -737,7 +737,7 @@ public final class PyDocumentationBuilder {
|
||||
.takeWhile(line -> !line.startsWith(">>>")) //TODO: PyConsoleUtil.ORDINARY_PROMPT
|
||||
.toList();
|
||||
final HtmlBuilder result = new HtmlBuilder();
|
||||
// reconstruct back, dropping first empty fragment as needed
|
||||
// reconstruct back, dropping the first empty fragment as needed
|
||||
boolean isFirstLine = true;
|
||||
final int tabSize = PythonCodeStyleService.getInstance().getTabSize(element.getContainingFile());
|
||||
for (@NlsSafe String line : updatedLines) {
|
||||
@@ -821,7 +821,7 @@ public final class PyDocumentationBuilder {
|
||||
private static @Nullable HtmlChunk getLinkToFunction(@NotNull PyFunction function, boolean preferQualifiedName) {
|
||||
final String qualifiedName = function.getQualifiedName();
|
||||
final PyClass pyClass = function.getContainingClass();
|
||||
// Preserve name of a containing class even if the whole qualified name can't be constructed
|
||||
// Preserve the name of a containing class even if the whole qualified name can't be constructed
|
||||
final String shortName = pyClass == null ? function.getName() : pyClass.getName() + "." + function.getName();
|
||||
|
||||
final String linkText = preferQualifiedName && qualifiedName != null ? qualifiedName : shortName;
|
||||
|
||||
+77
-9
@@ -6,6 +6,7 @@ import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.HtmlBuilder;
|
||||
import com.intellij.openapi.util.text.HtmlChunk;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -62,9 +63,12 @@ import com.jetbrains.python.psi.impl.PyClassImpl;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
|
||||
import com.jetbrains.python.psi.types.PyCallableParameter;
|
||||
import com.jetbrains.python.psi.types.PyClassType;
|
||||
import com.jetbrains.python.psi.types.PyCollectionType;
|
||||
import com.jetbrains.python.psi.types.PyInferredVarianceJudgment;
|
||||
import com.jetbrains.python.psi.types.PyTupleType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
import com.jetbrains.python.psi.types.PyTypeVarType;
|
||||
import com.jetbrains.python.psi.types.PyTypeVisitor;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import one.util.streamex.StreamEx;
|
||||
@@ -77,6 +81,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static com.jetbrains.python.documentation.PyDocSignaturesHighlighterKt.functionNameTextAttribute;
|
||||
import static com.jetbrains.python.documentation.PyDocSignaturesHighlighterKt.highlightExpressionText;
|
||||
@@ -84,6 +89,7 @@ import static com.jetbrains.python.documentation.PyDocSignaturesHighlighterKt.pa
|
||||
import static com.jetbrains.python.documentation.PyDocSignaturesHighlighterKt.styledReference;
|
||||
import static com.jetbrains.python.documentation.PyDocSignaturesHighlighterKt.styledSpan;
|
||||
import static com.jetbrains.python.psi.PyUtil.as;
|
||||
import static com.jetbrains.python.psi.types.PyInferredVarianceJudgment.isEffectivelyInvariant;
|
||||
|
||||
/**
|
||||
* Provides quick docs for classes, methods, and functions.
|
||||
@@ -144,7 +150,7 @@ public class PythonDocumentationProvider implements DocumentationProvider {
|
||||
return describeExpression((PyExpression)element, referenceElement, context);
|
||||
}
|
||||
else if (element instanceof PyTypeParameter typeParameter) {
|
||||
return PyPsiBundle.message("QDOC.type.parameter.name", describeTypeParameter(typeParameter, true, context));
|
||||
return PyPsiBundle.message("QDOC.type.parameter.name", describeTypeParameter(typeParameter, originalElement, true, context));
|
||||
}
|
||||
else if (element instanceof PyTypeAliasStatement typeAliasStatement) {
|
||||
return describeTypeAlias(typeAliasStatement, context).toString();
|
||||
@@ -158,11 +164,14 @@ public class PythonDocumentationProvider implements DocumentationProvider {
|
||||
return HtmlChunk.raw(describeFunctionWithTypes(function, context, forTooltip));
|
||||
}
|
||||
|
||||
static @NotNull HtmlChunk describeTarget(@NotNull PyTargetExpression target, @NotNull TypeEvalContext context) {
|
||||
static @NotNull HtmlChunk describeTarget(@NotNull PyTargetExpression target,
|
||||
@NotNull PsiElement originalElement,
|
||||
@NotNull TypeEvalContext context) {
|
||||
final HtmlBuilder result = new HtmlBuilder();
|
||||
result.append(styledSpan(StringUtil.notNullize(target.getName()), DefaultLanguageHighlighterColors.IDENTIFIER));
|
||||
result.append(styledSpan(": ", PyHighlighter.PY_OPERATION_SIGN));
|
||||
result.append(styledSpan(formatTypeWithLinks(context.getType(target), target, target, context), PyHighlighter.PY_ANNOTATION));
|
||||
PyType type = context.getType(target);
|
||||
result.append(styledSpan(formatTypeWithLinks(type, target, target, context), PyHighlighter.PY_ANNOTATION));
|
||||
|
||||
// Can return not physical elements such as foo()[0] for assignments like x, _ = foo()
|
||||
final PyExpression value = target.findAssignedValue();
|
||||
@@ -177,6 +186,27 @@ public class PythonDocumentationProvider implements DocumentationProvider {
|
||||
result.append(highlightExpressionText(initializerText.substring(0, index), value));
|
||||
result.append(styledSpan("...", PyHighlighter.PY_DOT));
|
||||
}
|
||||
if (type instanceof PyClassType classType && PyTypingTypeProvider.TYPE_VAR.equals(classType.getClassQName())) {
|
||||
Ref<PyType> typeRef = PyTypingTypeProvider.getType(value, context);
|
||||
if (typeRef != null && typeRef.get() instanceof PyTypeVarType valueType) {
|
||||
PsiElement refExpr = findReferenceOrTypeParameter(originalElement);
|
||||
if (refExpr != null) {
|
||||
if (isEffectivelyInvariant(refExpr, context)) {
|
||||
if (valueType.getVariance() != PyTypeVarType.Variance.INVARIANT) {
|
||||
String varianceStr = PyTypeVarType.Variance.INVARIANT.name().toLowerCase(Locale.ROOT); //NON-NLS
|
||||
result.append(styledSpan(" # treated as " + varianceStr, PyHighlighter.PY_LINE_COMMENT)); //NON-NLS
|
||||
}
|
||||
}
|
||||
else if (valueType.getVariance() == PyTypeVarType.Variance.INFER_VARIANCE) {
|
||||
PyTypeVarType.Variance inferredVariance = PyInferredVarianceJudgment.getInferredVariance(refExpr, context);
|
||||
if (inferredVariance != null) {
|
||||
String varianceStr = inferredVariance.name().toLowerCase(Locale.ROOT); //NON-NLS
|
||||
result.append(styledSpan(" # inferred as " + varianceStr, PyHighlighter.PY_LINE_COMMENT)); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toFragment();
|
||||
}
|
||||
@@ -190,14 +220,39 @@ public class PythonDocumentationProvider implements DocumentationProvider {
|
||||
}
|
||||
|
||||
static @NotNull HtmlChunk describeTypeParameter(@NotNull PyTypeParameter typeParameter,
|
||||
@Nullable PsiElement originalElement,
|
||||
boolean showKind,
|
||||
@NotNull TypeEvalContext context) {
|
||||
HtmlBuilder result = new HtmlBuilder();
|
||||
PsiElement refExpr = findReferenceOrTypeParameter(originalElement);
|
||||
boolean effectivelyInvariant = isEffectivelyInvariant(refExpr, context);
|
||||
PyTypeVarType.Variance variance = effectivelyInvariant
|
||||
? PyTypeVarType.Variance.INVARIANT
|
||||
: PyInferredVarianceJudgment.getInferredVariance(refExpr, context);
|
||||
String varianceStr = switch (variance) {
|
||||
case null -> null;
|
||||
case INFER_VARIANCE -> null;
|
||||
case COVARIANT -> "out "; //NON-NLS
|
||||
case CONTRAVARIANT -> "in "; //NON-NLS
|
||||
case INVARIANT -> "invariant "; //NON-NLS
|
||||
case BIVARIANT -> "bivariant "; //NON-NLS
|
||||
};
|
||||
if (varianceStr != null) {
|
||||
result.append(styledSpan(varianceStr, PyHighlighter.PY_KEYWORD));
|
||||
}
|
||||
result.append(styledSpan(StringUtil.notNullize(typeParameter.getName()), PyHighlighter.PY_TYPE_PARAMETER));
|
||||
PyExpression boundExpression = typeParameter.getBoundExpression();
|
||||
if (boundExpression != null && typeParameter.getBoundExpressionText() != null) {
|
||||
Ref<PyType> boundExprTR = boundExpression == null ? null : PyTypingTypeProvider.getType(boundExpression, context);
|
||||
if (boundExprTR != null && boundExprTR.get() != null) {
|
||||
result.append(styledSpan(": ", PyHighlighter.PY_OPERATION_SIGN));
|
||||
result.append(highlightExpressionText(typeParameter.getBoundExpressionText(), typeParameter.getBoundExpression()));
|
||||
result.append(styledSpan(formatTypeWithLinks(boundExprTR.get(), boundExpression, boundExpression, context),
|
||||
PyHighlighter.PY_ANNOTATION));
|
||||
}
|
||||
PyExpression defaultExpr = typeParameter.getDefaultExpression();
|
||||
Ref<PyType> defaultExprTR = defaultExpr == null ? null : PyTypingTypeProvider.getType(defaultExpr, context);
|
||||
if (defaultExprTR != null && defaultExprTR.get() != null) {
|
||||
result.append(styledSpan(" = ", PyHighlighter.PY_OPERATION_SIGN));
|
||||
result.append(styledSpan(formatTypeWithLinks(defaultExprTR.get(), defaultExpr, defaultExpr, context), PyHighlighter.PY_ANNOTATION));
|
||||
}
|
||||
if (showKind) {
|
||||
result
|
||||
@@ -210,6 +265,19 @@ public class PythonDocumentationProvider implements DocumentationProvider {
|
||||
return result.toFragment();
|
||||
}
|
||||
|
||||
private static @Nullable PsiElement findReferenceOrTypeParameter(@Nullable PsiElement originalElement) {
|
||||
if (originalElement == null) return originalElement;
|
||||
if (originalElement instanceof PyReferenceExpression refExpr) return refExpr;
|
||||
if (originalElement.getParent() instanceof PyTypeParameter typeParam) return typeParam;
|
||||
if (originalElement.getParent() instanceof PyReferenceExpression refExpr) return refExpr;
|
||||
PsiElement prevElement = PsiTreeUtil.prevLeaf(originalElement, true);
|
||||
if (prevElement == null) return originalElement;
|
||||
if (prevElement.getParent() instanceof PyTypeParameter typeParam) return typeParam;
|
||||
if (prevElement instanceof PyReferenceExpression refExpr) return refExpr;
|
||||
if (prevElement.getParent() instanceof PyReferenceExpression refExpr) return refExpr;
|
||||
return originalElement;
|
||||
}
|
||||
|
||||
|
||||
static @NotNull HtmlChunk describeTypeAlias(@NotNull PyTypeAliasStatement typeAliasStatement, @NotNull TypeEvalContext context) {
|
||||
HtmlBuilder result = new HtmlBuilder();
|
||||
@@ -220,7 +288,7 @@ public class PythonDocumentationProvider implements DocumentationProvider {
|
||||
result.append(styledSpan("[", PyHighlighter.PY_BRACKETS));
|
||||
result.append(StreamEx
|
||||
.of(typeParameters)
|
||||
.map(typeParameter -> describeTypeParameter(typeParameter, false, context))
|
||||
.map(typeParameter -> describeTypeParameter(typeParameter, null, false, context))
|
||||
.collect(HtmlChunk.toFragment(styledSpan(", ", PyHighlighter.PY_COMMA))));
|
||||
result.append(styledSpan("]", PyHighlighter.PY_BRACKETS));
|
||||
}
|
||||
@@ -306,7 +374,7 @@ public class PythonDocumentationProvider implements DocumentationProvider {
|
||||
}
|
||||
else {
|
||||
paramName = StringUtil.notNullize(paramName, PyNames.UNNAMED_ELEMENT);
|
||||
// Don't show type for "self" unless it's explicitly annotated
|
||||
// Don't show a type for "self" unless it's explicitly annotated
|
||||
showType = !isSelf || (named != null && new PyTypingTypeProvider().getParameterType(named, function, context) != null);
|
||||
}
|
||||
|
||||
@@ -379,7 +447,7 @@ public class PythonDocumentationProvider implements DocumentationProvider {
|
||||
* Render a type in a human-readable format.
|
||||
* <p>
|
||||
* The format is our own compact representation of types, intended to be used in inspection warnings,
|
||||
* documentation and other user-facing messages. It's not PEP-484 compatible.
|
||||
* documentation, and other user-facing messages. It's not PEP-484 compatible.
|
||||
* In particular callables are rendered as {@code (p1: T1, p2: T2, ...) -> R}, not as {@code Callable[[T1, T2, ...], R]}.
|
||||
* To render a type as a valid expression for a type annotation use {@link #getTypeHint(PyType, TypeEvalContext)}.
|
||||
*
|
||||
@@ -462,7 +530,7 @@ public class PythonDocumentationProvider implements DocumentationProvider {
|
||||
@NotNull TypeEvalContext context,
|
||||
@NotNull PsiElement anchor,
|
||||
@NotNull HtmlBuilder body) {
|
||||
// Variable annotated with "typing.TypeAlias" marker is deliberately treated as having "Any" type
|
||||
// Variable annotated with 'typing.TypeAlias' marker is deliberately treated as having "Any" type
|
||||
if (typeOwner instanceof PyTargetExpression && type == null) {
|
||||
PyAssignmentStatement assignment = as(typeOwner.getParent(), PyAssignmentStatement.class);
|
||||
if (assignment != null && PyTypingTypeProvider.isExplicitTypeAlias(assignment, context)) {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
class A[<weak_warning descr="Type parameter 'T' is not used">T</weak_warning>]:
|
||||
def f(self):
|
||||
pass
|
||||
|
||||
class B[S, <weak_warning descr="Type parameter 'T' is not used">T</weak_warning>]:
|
||||
def f(self, s: S):
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
<html><body><div class="definition"><pre>Type parameter <b>X</b> of <a href="psi_element://#typename#TypeParameter_variance_co.Box">TypeParameter_variance_co.Box</a><br/><span style="color:#000080;font-weight:bold;">out </span><span style="color:#000000;">X</span>, kind: <span style="color:#000000;">TypeVar</span></pre></div></body></html>
|
||||
@@ -0,0 +1,3 @@
|
||||
class Box[X]:
|
||||
def m(self) -> X<the_ref>:
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
<html><body><div class="definition"><pre>Type parameter <b>X</b> of <a href="psi_element://#typename#TypeParameter_variance_contra.Box">TypeParameter_variance_contra.Box</a><br/><span style="color:#000080;font-weight:bold;">in </span><span style="color:#000000;">X</span>, kind: <span style="color:#000000;">TypeVar</span></pre></div></body></html>
|
||||
@@ -0,0 +1,3 @@
|
||||
class Box[X]:
|
||||
def m(self, a: X<the_ref>):
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
<html><body><div class="definition"><pre>Type parameter <b>X</b> of <a href="psi_element://#typename#TypeParameter_variance_inv.Box">TypeParameter_variance_inv.Box</a><br/><span style="color:#000080;font-weight:bold;">invariant </span><span style="color:#000000;">X</span>, kind: <span style="color:#000000;">TypeVar</span></pre></div></body></html>
|
||||
@@ -0,0 +1,2 @@
|
||||
class Box[X]:
|
||||
a: X<the_ref>
|
||||
@@ -0,0 +1 @@
|
||||
<html><body><div class="definition"><pre>Type parameter <b>YY</b> of <a href="psi_element://#func#TypeParameter_variance_not_affected_1.m">TypeParameter_variance_not_affected_1.m</a><br/><span style="color:#000080;font-weight:bold;">invariant </span><span style="color:#000000;">YY</span><span style="">: </span><span style="color:#000000;"><span style="color:#000080;"><a href="psi_element://#typename#int">int</a></span></span>, kind: <span style="color:#000000;">TypeVar</span></pre></div></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
def m[YY:int](self) -> Y<the_ref>Y:
|
||||
@@ -0,0 +1 @@
|
||||
<html><body><div class="definition"><pre>Type parameter <b>X</b> of <a href="psi_element://#typename#TypeParameter_variance_not_affected_2.Box2">TypeParameter_variance_not_affected_2.Box2</a><br/><span style="color:#000080;font-weight:bold;">invariant </span><span style="color:#000000;">X</span>, kind: <span style="color:#000000;">TypeVar</span></pre></div></body></html>
|
||||
@@ -0,0 +1,6 @@
|
||||
class Box2[X]:
|
||||
def m(self) -> X: # inferred as 'out Any'
|
||||
pass
|
||||
@classmethod
|
||||
def f(cls) -> X<the_ref>: # inferred as 'Any'
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
<html><body><div class="definition"><pre>Type parameter <b>X</b> of <a href="psi_element://#typename#TypeParameter_variance_on_its_declaration.Box">TypeParameter_variance_on_its_declaration.Box</a><br/><span style="color:#000080;font-weight:bold;">out </span><span style="color:#000000;">X</span>, kind: <span style="color:#000000;">TypeVar</span></pre></div></body></html>
|
||||
@@ -0,0 +1,3 @@
|
||||
class Box[X<the_ref>]:
|
||||
def m(self) -> X:
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
<html><body><div class="definition"><pre>Type parameter <b>X</b> of <a href="psi_element://#typename#TypeParameter_variance_with_default.A">TypeParameter_variance_with_default.A</a><br/><span style="color:#000080;font-weight:bold;">in </span><span style="color:#000000;">X</span><span style=""> = </span><span style="color:#000000;"><span style="color:#000080;"><a href="psi_element://#typename#int">int</a></span></span>, kind: <span style="color:#000000;">TypeVar</span></pre></div></body></html>
|
||||
@@ -0,0 +1,3 @@
|
||||
class A[X = int]:
|
||||
def f2(self, x: X<the_ref>):
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
<html><body><div class="bottom"><icon src="AllIcons.Nodes.Package"/> <code><a href="psi_element://#module#TypeVar_variance_co">TypeVar_variance_co</a></code></div><div class="definition"><pre><span style="color:#000000;">TT</span><span style="">: </span><span style="color:#000000;"><a href="psi_element://#typename#typing.TypeVar">TypeVar</a></span><span style=""> = </span><span style="">TypeVar(</span><span style="color:#008000;font-weight:bold;">'TT'</span><span style="">, infer_variance=</span><span style="color:#000080;font-weight:bold;">True</span><span style="">)</span><span style="color:#808080;font-style:italic;"> # inferred as covariant</span></pre></div></body></html>
|
||||
@@ -0,0 +1,7 @@
|
||||
from typing import TypeVar, Generic
|
||||
|
||||
TT = TypeVar('TT', infer_variance=True)
|
||||
|
||||
class C(Generic[TT]):
|
||||
def f(self) -> T<the_ref>T:
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
<html><body><div class="bottom"><icon src="AllIcons.Nodes.Package"/> <code><a href="psi_element://#module#TypeVar_variance_contra">TypeVar_variance_contra</a></code></div><div class="definition"><pre><span style="color:#000000;">TT</span><span style="">: </span><span style="color:#000000;"><a href="psi_element://#typename#typing.TypeVar">TypeVar</a></span><span style=""> = </span><span style="">TypeVar(</span><span style="color:#008000;font-weight:bold;">'TT'</span><span style="">, infer_variance=</span><span style="color:#000080;font-weight:bold;">True</span><span style="">)</span><span style="color:#808080;font-style:italic;"> # inferred as contravariant</span></pre></div></body></html>
|
||||
@@ -0,0 +1,7 @@
|
||||
from typing import TypeVar, Generic
|
||||
|
||||
TT = TypeVar('TT', infer_variance=True)
|
||||
|
||||
class C(Generic[TT]):
|
||||
def f(self, p: T<the_ref>T):
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
<html><body><div class="bottom"><icon src="AllIcons.Nodes.Package"/> <code><a href="psi_element://#module#TypeVar_variance_in_init">TypeVar_variance_in_init</a></code></div><div class="definition"><pre><span style="color:#000000;">T</span><span style="">: </span><span style="color:#000000;"><a href="psi_element://#typename#typing.TypeVar">TypeVar</a></span><span style=""> = </span><span style="">TypeVar(</span><span style="color:#008000;font-weight:bold;">'T'</span><span style="">, infer_variance=</span><span style="color:#000080;font-weight:bold;">True</span><span style="">)</span><span style="color:#808080;font-style:italic;"> # treated as invariant</span></pre></div></body></html>
|
||||
@@ -0,0 +1,9 @@
|
||||
from typing import TypeVar, Generic
|
||||
|
||||
T = TypeVar('T', infer_variance=True)
|
||||
|
||||
class C(Generic[T]):
|
||||
def __init__(self, t: T<the_ref>):
|
||||
pass
|
||||
def method(self) -> T:
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
<html><body><div class="bottom"><icon src="AllIcons.Nodes.Package"/> <code><a href="psi_element://#module#TypeVar_variance_inv">TypeVar_variance_inv</a></code></div><div class="definition"><pre><span style="color:#000000;">TT</span><span style="">: </span><span style="color:#000000;"><a href="psi_element://#typename#typing.TypeVar">TypeVar</a></span><span style=""> = </span><span style="">TypeVar(</span><span style="color:#008000;font-weight:bold;">'TT'</span><span style="">, infer_variance=</span><span style="color:#000080;font-weight:bold;">True</span><span style="">)</span><span style="color:#808080;font-style:italic;"> # inferred as invariant</span></pre></div></body></html>
|
||||
@@ -0,0 +1,7 @@
|
||||
from typing import TypeVar, Generic
|
||||
|
||||
TT = TypeVar('TT', infer_variance=True)
|
||||
|
||||
class C(Generic[TT]):
|
||||
def f(self, p: T<the_ref>T) -> TT:
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
<html><body><div class="bottom"><icon src="AllIcons.Nodes.Package"/> <code><a href="psi_element://#module#TypeVar_variance_not_affected_1">TypeVar_variance_not_affected_1</a></code></div><div class="definition"><pre><span style="color:#000000;">TT</span><span style="">: </span><span style="color:#000000;"><a href="psi_element://#typename#typing.TypeVar">TypeVar</a></span><span style=""> = </span><span style="">TypeVar(</span><span style="color:#008000;font-weight:bold;">'TT'</span><span style="">, infer_variance=</span><span style="color:#000080;font-weight:bold;">True</span><span style="">)</span><span style="color:#808080;font-style:italic;"> # inferred as invariant</span></pre></div></body></html>
|
||||
@@ -0,0 +1,9 @@
|
||||
from typing import TypeVar, Generic
|
||||
|
||||
TT = TypeVar('TT', infer_variance=True)
|
||||
|
||||
class C(Generic[TT]):
|
||||
def method(self) -> TT:
|
||||
pass
|
||||
|
||||
def f() -> T<the_ref>T:
|
||||
@@ -0,0 +1 @@
|
||||
<html><body><div class="bottom"><icon src="AllIcons.Nodes.Package"/> <code><a href="psi_element://#module#TypeVar_variance_not_affected_2">TypeVar_variance_not_affected_2</a></code></div><div class="definition"><pre><span style="color:#000000;">TT</span><span style="">: </span><span style="color:#000000;"><a href="psi_element://#typename#typing.TypeVar">TypeVar</a></span><span style=""> = </span><span style="">TypeVar(</span><span style="color:#008000;font-weight:bold;">'TT'</span><span style="">, covariant=</span><span style="color:#000080;font-weight:bold;">True</span><span style="">)</span><span style="color:#808080;font-style:italic;"> # treated as invariant</span></pre></div></body></html>
|
||||
@@ -0,0 +1,6 @@
|
||||
from typing import TypeVar, Generic
|
||||
|
||||
TT = TypeVar('TT', covariant=True)
|
||||
|
||||
class C(Generic[TT]):
|
||||
def f() -> T<the_ref>T: ...
|
||||
@@ -843,6 +843,71 @@ public class Py3QuickDocTest extends LightMarkedTestCase {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
// PY-87075
|
||||
public void testTypeParameter_variance_with_default() {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
// PY-87075
|
||||
public void testTypeParameter_variance_inv() {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
// PY-87075
|
||||
public void testTypeParameter_variance_co() {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
// PY-87075
|
||||
public void testTypeParameter_variance_contra() {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
// PY-87075
|
||||
public void testTypeParameter_variance_not_affected_1() {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
// PY-87075
|
||||
public void testTypeParameter_variance_not_affected_2() {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
// PY-87075
|
||||
public void testTypeParameter_variance_on_its_declaration() {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
// PY-87075
|
||||
public void testTypeVar_variance_co() {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
// PY-87075
|
||||
public void testTypeVar_variance_contra() {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
// PY-87075
|
||||
public void testTypeVar_variance_inv() {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
// PY-87075
|
||||
public void testTypeVar_variance_in_init() {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
// PY-87075
|
||||
public void testTypeVar_variance_not_affected_1() {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
// PY-87075
|
||||
public void testTypeVar_variance_not_affected_2() {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
// PY-64074
|
||||
public void testTypeKeyword() {
|
||||
checkHTMLOnly();
|
||||
@@ -852,7 +917,7 @@ public class Py3QuickDocTest extends LightMarkedTestCase {
|
||||
public void testTypeAliasStatement() {
|
||||
checkHTMLOnly();
|
||||
}
|
||||
|
||||
|
||||
// PY-78119
|
||||
public void testNeverType() {
|
||||
checkHTMLOnly();
|
||||
|
||||
Reference in New Issue
Block a user