PY-62608 PEP 695 Type Parameter Syntax: PSI stubs for type parameter lists and type aliases

GitOrigin-RevId: b8707b4677519bab5bcf922c9747eb8388e3157b
This commit is contained in:
Daniil Kalinin
2023-09-28 15:05:30 +00:00
committed by intellij-monorepo-bot
parent c94a4fea62
commit 1c5b0c5ac3
25 changed files with 516 additions and 26 deletions
@@ -45,6 +45,12 @@ public interface PyFile extends PyElement, PsiFile, PyDocStringOwner, ScopeOwner
@Nullable
PyTargetExpression findTopLevelAttribute(@NotNull String name);
@NotNull
List<PyTypeAliasStatement> getTypeAliasStatements();
@Nullable
PyTypeAliasStatement findTypeAliasStatement(@NotNull String name);
LanguageLevel getLanguageLevel();
/**
@@ -2,13 +2,24 @@
package com.jetbrains.python.psi;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.stubs.PyTypeAliasStatementStub;
import org.jetbrains.annotations.Nullable;
/**
* Represents Type Alias Statement added in <a href="https://peps.python.org/pep-0695/">PEP 695</a>
*/
public interface PyTypeAliasStatement extends PyStatement, PsiNameIdentifierOwner, PyTypeParameterListOwner, PyTypedElement {
public interface PyTypeAliasStatement extends PyStatement, PsiNameIdentifierOwner, PyTypeParameterListOwner, PyTypedElement,
StubBasedPsiElement<PyTypeAliasStatementStub> {
@Nullable
PyExpression getTypeExpression();
/**
* Returns right-hand side of the type alias statement as text.
* <p>
* The text is taken from stub if the stub is presented.
*/
@Nullable
String getTypeExpressionText();
}
@@ -1,19 +1,25 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.python.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.stubs.PyTypeParameterStub;
import org.jetbrains.annotations.Nullable;
/**
* Represents a Type Parameter that can be a part of {@link PyTypeParameterList}<br>
* For more information see <a href="https://peps.python.org/pep-0695/">PEP 695</a>
*/
public interface PyTypeParameter extends PyElement, PsiNameIdentifierOwner, PyTypedElement {
public interface PyTypeParameter extends PyElement, PsiNameIdentifierOwner, PyTypedElement, StubBasedPsiElement<PyTypeParameterStub> {
@Nullable
PyExpression getBoundExpression();
/**
* Returns the text of the bound expression of the type parameter
* <p>
* The text is taken from stub if the stub is presented.
*/
@Nullable
ASTNode getNameNode();
String getBoundExpressionText();
}
@@ -1,6 +1,8 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.python.psi;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.psi.stubs.PyTypeParameterListStub;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -11,7 +13,7 @@ import java.util.List;
* where {@code [T, U]} is the list of generic Type Parameters.<br>
* For more information see <a href="https://peps.python.org/pep-0695/">PEP 695</a>
*/
public interface PyTypeParameterList extends PyElement {
public interface PyTypeParameterList extends PyElement, StubBasedPsiElement<PyTypeParameterListStub> {
@NotNull
List<PyTypeParameter> getTypeParameters();
@@ -0,0 +1,12 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.python.psi.stubs;
import com.intellij.psi.stubs.NamedStub;
import com.jetbrains.python.psi.PyTypeAliasStatement;
import org.jetbrains.annotations.Nullable;
public interface PyTypeAliasStatementStub extends NamedStub<PyTypeAliasStatement> {
@Nullable
String getTypeExpressionText();
}
@@ -0,0 +1,8 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.python.psi.stubs;
import com.intellij.psi.stubs.StubElement;
import com.jetbrains.python.psi.PyTypeParameterList;
public interface PyTypeParameterListStub extends StubElement<PyTypeParameterList> {
}
@@ -0,0 +1,12 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.python.psi.stubs;
import com.intellij.psi.stubs.NamedStub;
import com.jetbrains.python.psi.PyTypeParameter;
import org.jetbrains.annotations.Nullable;
public interface PyTypeParameterStub extends NamedStub<PyTypeParameter> {
@Nullable
String getBoundExpressionText();
}
@@ -46,6 +46,9 @@ public interface PyElementTypes {
PyStubElementType<PyImportStatementStub, PyImportStatement> IMPORT_STATEMENT = PyStubElementTypes.IMPORT_STATEMENT;
PyStubElementType<PyTargetExpressionStub, PyTargetExpression> TARGET_EXPRESSION = PyStubElementTypes.TARGET_EXPRESSION;
PyStubElementType<PyTypeParameterStub, PyTypeParameter> TYPE_PARAMETER = PyStubElementTypes.TYPE_PARAMETER;
PyStubElementType<PyTypeParameterListStub, PyTypeParameterList> TYPE_PARAMETER_LIST = PyStubElementTypes.TYPE_PARAMETER_LIST;
PyStubElementType<PyTypeAliasStatementStub, PyTypeAliasStatement> TYPE_ALIAS_STATEMENT = PyStubElementTypes.TYPE_ALIAS_STATEMENT;
TokenSet PARAMETER_LIST_SET = TokenSet.create(PARAMETER_LIST);
@@ -55,8 +58,6 @@ public interface PyElementTypes {
PyElementType PRINT_TARGET = new PyElementType("PRINT_TARGET", node -> new PyPrintTargetImpl(node));
PyElementType DECORATOR = new PyElementType("DECORATOR", node -> new PyDecoratorImpl(node));
PyElementType TYPE_PARAMETER = new PyElementType("TYPE_PARAMETER", node -> new PyTypeParameterImpl(node));
PyElementType TYPE_PARAMETER_LIST = new PyElementType("TYPE_PARAMETER_LIST", node -> new PyTypeParameterListImpl(node));
// Statements
PyElementType EXPRESSION_STATEMENT = new PyElementType("EXPRESSION_STATEMENT", node -> new PyExpressionStatementImpl(node));
@@ -173,5 +174,4 @@ public interface PyElementTypes {
PyElementType KEYWORD_PATTERN = new PyElementType("KEYWORD_PATTERN", node -> new PyKeywordPatternImpl(node));
PyElementType OR_PATTERN = new PyElementType("OR_PATTERN", node -> new PyOrPatternImpl(node));
PyElementType AS_PATTERN = new PyElementType("AS_PATTERN", node -> new PyAsPatternImpl(node));
PyElementType TYPE_ALIAS_STATEMENT = new PyElementType("TYPE_ALIAS_STATEMENT", node -> new PyTypeAliasStatementImpl(node));
}
@@ -30,4 +30,7 @@ public interface PyStubElementTypes {
PyStubElementType<PyImportStatementStub, PyImportStatement> IMPORT_STATEMENT = new PyImportStatementElementType();
PyStubElementType<PyTargetExpressionStub, PyTargetExpression> TARGET_EXPRESSION = new PyTargetExpressionElementType();
PyStubElementType<PyTypeParameterStub, PyTypeParameter> TYPE_PARAMETER = new PyTypeParameterElementType();
PyStubElementType<PyTypeParameterListStub, PyTypeParameterList> TYPE_PARAMETER_LIST = new PyTypeParameterListElementType();
PyStubElementType<PyTypeAliasStatementStub, PyTypeAliasStatement> TYPE_ALIAS_STATEMENT = new PyTypeAliasStatementElementType();
}
@@ -146,7 +146,7 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
@Override
@Nullable
public PyTypeParameterList getTypeParameterList() {
return childToPsi(PyElementTypes.TYPE_PARAMETER_LIST);
return getStubOrPsiChild(PyElementTypes.TYPE_PARAMETER_LIST);
}
@Override
@@ -225,6 +225,17 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
return findByName(name, getTopLevelAttributes());
}
@Override
public @NotNull List<PyTypeAliasStatement> getTypeAliasStatements() {
return PyPsiUtils.collectStubChildren(this, getGreenStub(), PyTypeAliasStatement.class);
}
@Override
@Nullable
public PyTypeAliasStatement findTypeAliasStatement(@NotNull String name) {
return findByName(name, getTypeAliasStatements());
}
@Nullable
private static <T extends PsiNamedElement> T findByName(@NotNull String name, @NotNull List<T> namedElements) {
for (T namedElement : namedElements) {
@@ -67,7 +67,7 @@ public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> implements
@Override
@Nullable
public PyTypeParameterList getTypeParameterList() {
return childToPsi(PyElementTypes.TYPE_PARAMETER_LIST);
return getStubOrPsiChild(PyElementTypes.TYPE_PARAMETER_LIST);
}
private class CachedStructuredDocStringProvider implements CachedValueProvider<StructuredDocString> {
@@ -3,20 +3,31 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.stubs.PyTypeAliasStatementStub;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PyTypeAliasStatementImpl extends PyElementImpl implements PyTypeAliasStatement {
public class PyTypeAliasStatementImpl extends PyBaseElementImpl<PyTypeAliasStatementStub> implements PyTypeAliasStatement {
public PyTypeAliasStatementImpl(ASTNode astNode) {
super(astNode);
}
public PyTypeAliasStatementImpl(PyTypeAliasStatementStub stub) {
this(stub, PyElementTypes.TYPE_ALIAS_STATEMENT);
}
public PyTypeAliasStatementImpl(PyTypeAliasStatementStub stub, IStubElementType nodeType) {
super(stub, nodeType);
}
@Override
protected void acceptPyVisitor(PyElementVisitor pyVisitor) {
pyVisitor.visitPyTypeAliasStatement(this);
@@ -33,10 +44,24 @@ public class PyTypeAliasStatementImpl extends PyElementImpl implements PyTypeAli
return (PyExpression)child;
}
@Override
@Nullable
public String getTypeExpressionText() {
PyTypeAliasStatementStub stub = getStub();
if (stub != null) {
return stub.getTypeExpressionText();
}
else {
PyExpression typeExpression = getTypeExpression();
return typeExpression != null ? typeExpression.getText() : null;
}
}
@Override
@Nullable
public PyTypeParameterList getTypeParameterList() {
return childToPsi(PyElementTypes.TYPE_PARAMETER_LIST);
return getStubOrPsiChild(PyElementTypes.TYPE_PARAMETER_LIST);
}
@Override
@@ -48,8 +73,15 @@ public class PyTypeAliasStatementImpl extends PyElementImpl implements PyTypeAli
@Override
public String getName() {
PsiElement identifier = getNameIdentifier();
return identifier != null ? identifier.getText() : null;
PyTypeAliasStatementStub stub = getStub();
if (stub != null) {
return stub.getName();
}
else {
PsiElement identifier = getNameIdentifier();
return identifier != null ? identifier.getText() : null;
}
}
@Override
@@ -2,24 +2,35 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyTypeParameter;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.stubs.PyTypeParameterStub;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PyTypeParameterImpl extends PyElementImpl implements PyTypeParameter {
public class PyTypeParameterImpl extends PyBaseElementImpl<PyTypeParameterStub> implements PyTypeParameter {
public PyTypeParameterImpl(ASTNode astNode) {
super(astNode);
}
public PyTypeParameterImpl(PyTypeParameterStub stub) {
this(stub, PyElementTypes.TYPE_PARAMETER);
}
public PyTypeParameterImpl(PyTypeParameterStub stub, IStubElementType nodeType) {
super(stub, nodeType);
}
@Override
protected void acceptPyVisitor(PyElementVisitor pyVisitor) {
pyVisitor.visitPyTypeParameter(this);
@@ -28,8 +39,15 @@ public class PyTypeParameterImpl extends PyElementImpl implements PyTypeParamete
@Override
@Nullable
public String getName() {
ASTNode nameNode = getNameNode();
return nameNode != null ? nameNode.getText() : null;
PyTypeParameterStub stub = getStub();
if (stub != null) {
return stub.getName();
}
else {
PsiElement identifier = getNameIdentifier();
return identifier != null ? identifier.getText() : null;
}
}
@Override
@@ -40,23 +58,35 @@ public class PyTypeParameterImpl extends PyElementImpl implements PyTypeParamete
@Override
@Nullable
public ASTNode getNameNode() {
return getNode().findChildByType(PyTokenTypes.IDENTIFIER);
public String getBoundExpressionText() {
PyTypeParameterStub stub = getStub();
if (stub != null) {
return stub.getBoundExpressionText();
}
PyExpression boundExpression = getBoundExpression();
if (boundExpression != null) {
return boundExpression.getText();
}
return null;
}
@Override
@Nullable
public PsiElement getNameIdentifier() {
ASTNode nameNode = getNameNode();
ASTNode nameNode = getNode().findChildByType(PyTokenTypes.IDENTIFIER);
return nameNode != null ? nameNode.getPsi() : null;
}
@Override
public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
ASTNode oldNameElement = getNameNode();
if (oldNameElement != null) {
ASTNode nameElement = PyUtil.createNewName(this, name);
getNode().replaceChild(oldNameElement, nameElement);
PsiElement identifier = getNameIdentifier();
if (identifier != null) {
ASTNode newName = PyUtil.createNewName(this, name);
ASTNode nameNode = identifier.getNode();
getNode().replaceChild(nameNode, newName);
}
return this;
}
@@ -1,19 +1,29 @@
package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.stubs.IStubElementType;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.PyTypeParameter;
import com.jetbrains.python.psi.PyTypeParameterList;
import com.jetbrains.python.psi.stubs.PyTypeParameterListStub;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class PyTypeParameterListImpl extends PyElementImpl implements PyTypeParameterList {
public class PyTypeParameterListImpl extends PyBaseElementImpl<PyTypeParameterListStub> implements PyTypeParameterList {
public PyTypeParameterListImpl(ASTNode astNode) {
super(astNode);
}
public PyTypeParameterListImpl(PyTypeParameterListStub stub) {
this(stub, PyElementTypes.PARAMETER_LIST);
}
public PyTypeParameterListImpl(PyTypeParameterListStub stub, IStubElementType nodeType) {
super(stub, nodeType);
}
@Override
protected void acceptPyVisitor(PyElementVisitor pyVisitor) {
pyVisitor.visitPyTypeParameterList(this);
@@ -23,6 +33,6 @@ public class PyTypeParameterListImpl extends PyElementImpl implements PyTypePara
@Override
@NotNull
public List<PyTypeParameter> getTypeParameters() {
return findChildrenByType(PyElementTypes.TYPE_PARAMETER);
return List.of(getStubOrPsiChildren(PyElementTypes.TYPE_PARAMETER, new PyTypeParameter[0]));
}
}
@@ -0,0 +1,62 @@
package com.jetbrains.python.psi.impl.stubs;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubInputStream;
import com.intellij.psi.stubs.StubOutputStream;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.psi.PyStubElementType;
import com.jetbrains.python.psi.PyTypeAliasStatement;
import com.jetbrains.python.psi.impl.PyTypeAliasStatementImpl;
import com.jetbrains.python.psi.stubs.PyTypeAliasStatementStub;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public class PyTypeAliasStatementElementType extends PyStubElementType<PyTypeAliasStatementStub, PyTypeAliasStatement> {
public PyTypeAliasStatementElementType() {
super("TYPE_ALIAS_STATEMENT");
}
@Override
@NotNull
public PsiElement createElement(@NotNull ASTNode node) {
return new PyTypeAliasStatementImpl(node);
}
@Override
public PyTypeAliasStatement createPsi(@NotNull PyTypeAliasStatementStub stub) {
return new PyTypeAliasStatementImpl(stub);
}
@Override
@NotNull
public PyTypeAliasStatementStub createStub(@NotNull PyTypeAliasStatement psi, StubElement<? extends PsiElement> parentStub) {
return new PyTypeAliasStatementStubImpl(psi.getName(), (psi.getTypeExpression() != null ? psi.getTypeExpression().getText() : null),
parentStub, getStubElementType());
}
@Override
public void serialize(@NotNull PyTypeAliasStatementStub stub, @NotNull StubOutputStream dataStream) throws IOException {
dataStream.writeName(stub.getName());
dataStream.writeName(stub.getTypeExpressionText());
}
@Override
@NotNull
public PyTypeAliasStatementStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
String name = dataStream.readNameString();
String typeExpressionText = dataStream.readNameString();
return new PyTypeAliasStatementStubImpl(name, typeExpressionText, parentStub, getStubElementType());
}
@NotNull
protected IStubElementType getStubElementType() {
return PyElementTypes.TYPE_ALIAS_STATEMENT;
}
}
@@ -0,0 +1,41 @@
package com.jetbrains.python.psi.impl.stubs;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
import com.jetbrains.python.psi.PyTypeAliasStatement;
import com.jetbrains.python.psi.stubs.PyTypeAliasStatementStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PyTypeAliasStatementStubImpl extends StubBase<PyTypeAliasStatement> implements PyTypeAliasStatementStub {
private final String myName;
private final String myTypeExpressionText;
public PyTypeAliasStatementStubImpl(@Nullable String name,
@Nullable String typeExpressionText,
@Nullable StubElement parent,
@NotNull IStubElementType stubElementType) {
super(parent, stubElementType);
myName = name;
myTypeExpressionText = typeExpressionText;
}
@Override
@Nullable
public String getName() {
return myName;
}
@Override
@Nullable
public String getTypeExpressionText() {
return myTypeExpressionText;
}
@Override
public String toString() {
return "PyTypeAliasStatementStub(name=" + myName + ", type expression=" + myTypeExpressionText +")";
}
}
@@ -0,0 +1,63 @@
package com.jetbrains.python.psi.impl.stubs;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubInputStream;
import com.intellij.psi.stubs.StubOutputStream;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.psi.PyStubElementType;
import com.jetbrains.python.psi.PyTypeParameter;
import com.jetbrains.python.psi.impl.PyTypeParameterImpl;
import com.jetbrains.python.psi.stubs.PyTypeParameterStub;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public class PyTypeParameterElementType extends PyStubElementType<PyTypeParameterStub, PyTypeParameter> {
public PyTypeParameterElementType() {
super("TYPE_PARAMETER");
}
@Override
public PyTypeParameter createPsi(@NotNull PyTypeParameterStub stub) {
return new PyTypeParameterImpl(stub);
}
@Override
@NotNull
public PyTypeParameterStub createStub(@NotNull PyTypeParameter psi, StubElement<? extends PsiElement> parentStub) {
return new PyTypeParameterStubImpl(psi.getName(), psi.getBoundExpression() != null ? psi.getBoundExpression().getText() : null,
parentStub, getStubElementType());
}
@Override
public void serialize(@NotNull PyTypeParameterStub stub, @NotNull StubOutputStream dataStream) throws IOException {
dataStream.writeName(stub.getName());
dataStream.writeName(stub.getBoundExpressionText());
}
@Override
@NotNull
public PyTypeParameterStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
String name = dataStream.readNameString();
String boundExpressionText = dataStream.readNameString();
return new PyTypeParameterStubImpl(name,
boundExpressionText,
parentStub, getStubElementType());
}
@Override
@NotNull
public PsiElement createElement(@NotNull ASTNode node) {
return new PyTypeParameterImpl(node);
}
@NotNull
protected IStubElementType getStubElementType() {
return PyElementTypes.TYPE_PARAMETER;
}
}
@@ -0,0 +1,56 @@
package com.jetbrains.python.psi.impl.stubs;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubInputStream;
import com.intellij.psi.stubs.StubOutputStream;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.psi.PyStubElementType;
import com.jetbrains.python.psi.PyTypeParameterList;
import com.jetbrains.python.psi.impl.PyTypeParameterListImpl;
import com.jetbrains.python.psi.stubs.PyTypeParameterListStub;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public class PyTypeParameterListElementType extends PyStubElementType<PyTypeParameterListStub, PyTypeParameterList> {
public PyTypeParameterListElementType() {
super("TYPE_PARAMETER_LIST");
}
@Override
public PyTypeParameterList createPsi(@NotNull PyTypeParameterListStub stub) {
return new PyTypeParameterListImpl(stub);
}
@Override
@NotNull
public PyTypeParameterListStub createStub(@NotNull PyTypeParameterList psi, StubElement<? extends PsiElement> parentStub) {
return new PyTypeParameterListStubImpl(parentStub, getStubElementType());
}
@Override
public void serialize(@NotNull PyTypeParameterListStub stub, @NotNull StubOutputStream dataStream) throws IOException {
}
@Override
@NotNull
public PyTypeParameterListStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
return new PyTypeParameterListStubImpl(parentStub, getStubElementType());
}
@Override
@NotNull
public PsiElement createElement(@NotNull ASTNode node) {
return new PyTypeParameterListImpl(node);
}
protected IStubElementType<PyTypeParameterListStub, PyTypeParameterList> getStubElementType() {
return PyElementTypes.TYPE_PARAMETER_LIST;
}
}
@@ -0,0 +1,13 @@
package com.jetbrains.python.psi.impl.stubs;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
import com.jetbrains.python.psi.PyTypeParameterList;
import com.jetbrains.python.psi.stubs.PyTypeParameterListStub;
public class PyTypeParameterListStubImpl extends StubBase<PyTypeParameterList> implements PyTypeParameterListStub {
public PyTypeParameterListStubImpl(StubElement parent, IStubElementType stubElementType) {
super(parent, stubElementType);
}
}
@@ -0,0 +1,41 @@
package com.jetbrains.python.psi.impl.stubs;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
import com.jetbrains.python.psi.PyTypeParameter;
import com.jetbrains.python.psi.stubs.PyTypeParameterStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PyTypeParameterStubImpl extends StubBase<PyTypeParameter> implements PyTypeParameterStub {
private final String myName;
private final String myBoundExpressionText;
public PyTypeParameterStubImpl(@Nullable String name,
@Nullable String boundExpressionText,
@Nullable StubElement parent,
@NotNull IStubElementType stubElementType) {
super(parent, stubElementType);
myName = name;
myBoundExpressionText = boundExpressionText;
}
@Override
@Nullable
public String getBoundExpressionText() {
return myBoundExpressionText;
}
@Override
@Nullable
public String getName() {
return myName;
}
@Override
public String toString() {
return "PyTypeParameterStub(name=" + myName + ", bound=" + myBoundExpressionText + ")";
}
}
@@ -0,0 +1 @@
type myType[T, U: str] = Union[T, U]
@@ -0,0 +1,3 @@
class Clazz[T, U: str]:
a: T
b: U
@@ -0,0 +1,2 @@
def foo[T, U: str](a: T, b: U):
pass
@@ -1090,6 +1090,71 @@ public class PyStubsTest extends PyTestCase {
assertNotParsed(file);
}
// PY-62608
public void testTypeParameterListInFunctionDeclaration() {
PyFile file = getTestFile();
PyFunction function = file.findTopLevelFunction("foo");
PyTypeParameter firstTypeParameter = function.getTypeParameterList().getTypeParameters().get(0);
PyTypeParameter secondTypeParameter = function.getTypeParameterList().getTypeParameters().get(1);
assertNotNull(firstTypeParameter);
assertNotNull(secondTypeParameter);
assertEquals("T", firstTypeParameter.getName());
assertEquals("U", secondTypeParameter.getName());
assertNull(firstTypeParameter.getBoundExpressionText());
assertEquals(secondTypeParameter.getBoundExpressionText(), "str");
assertNotParsed(file);
}
// PY-62608
public void testTypeParameterListInClassDeclaration() {
PyFile file = getTestFile();
PyClass cls = file.findTopLevelClass("Clazz");
PyTypeParameter firstTypeParameter = cls.getTypeParameterList().getTypeParameters().get(0);
PyTypeParameter secondTypeParameter = cls.getTypeParameterList().getTypeParameters().get(1);
assertNotNull(firstTypeParameter);
assertNotNull(secondTypeParameter);
assertEquals("T", firstTypeParameter.getName());
assertEquals("U", secondTypeParameter.getName());
assertNull(firstTypeParameter.getBoundExpressionText());
assertEquals(secondTypeParameter.getBoundExpressionText(), "str");
assertNotParsed(file);
}
// PY-62608
public void testTypeAliasStatement() {
PyFile file = getTestFile();
PyTypeAliasStatement typeAliasStatement = file.findTypeAliasStatement("myType");
assertNotNull(typeAliasStatement);
PyTypeParameter firstTypeParameter = typeAliasStatement.getTypeParameterList().getTypeParameters().get(0);
PyTypeParameter secondTypeParameter = typeAliasStatement.getTypeParameterList().getTypeParameters().get(1);
assertNotNull(firstTypeParameter);
assertNotNull(secondTypeParameter);
assertEquals("T", firstTypeParameter.getName());
assertEquals("U", secondTypeParameter.getName());
assertNull(firstTypeParameter.getBoundExpressionText());
assertEquals(secondTypeParameter.getBoundExpressionText(), "str");
assertNotParsed(file);
}
private void doTestTypingTypedDictArguments() {
doTestTypedDict("name", Arrays.asList("x", "y"), Arrays.asList("str", "int"), QualifiedName.fromComponents("TypedDict"));