From f30dc5d25474624390e4dc7b73d187c9db461c9c Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 20 May 2025 18:07:52 +0200 Subject: [PATCH] PY-78828 No `Protocol[] must include all type variables` error is reported GitOrigin-RevId: 5b8ed27b66cf78fa49009b39f9e70a14eae65d9d --- .../resources/messages/PyPsiBundle.properties | 2 +- .../python/inspections/PyTypeHintsInspection.kt | 15 +++++++-------- .../inspections/PyTypeHintsInspectionTest.java | 12 ++++++++---- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/python/python-psi-impl/resources/messages/PyPsiBundle.properties b/python/python-psi-impl/resources/messages/PyPsiBundle.properties index 4a716d5e3b2a..1af93b912fab 100644 --- a/python/python-psi-impl/resources/messages/PyPsiBundle.properties +++ b/python/python-psi-impl/resources/messages/PyPsiBundle.properties @@ -1162,7 +1162,7 @@ INSP.type.hints.typed.dict.is.not.allowed.as.a.bound.for.a.type.var=TypedDict is INSP.type.hints.generics.should.be.specified.through.square.brackets=Generics should be specified through square brackets INSP.type.hints.cannot.inherit.from.plain.generic=Cannot inherit from plain 'Generic' INSP.type.hints.cannot.inherit.from.generic.multiple.times=Cannot inherit from 'Generic[...]' multiple times -INSP.type.hints.some.type.variables.are.not.listed.in.generic=Some type variables ({0}) are not listed in ''Generic[{1}]'' +INSP.type.hints.generic.or.protocol.should.list.all.type.variables=''Generic[...]'' or ''Protocol[...]'' should list all type variables ({0}) INSP.type.hints.illegal.literal.parameter='Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types INSP.type.hints.parameters.to.generic.must.all.be.type.variables=Parameters to 'Generic[...]' must all be type variables INSP.type.hints.parameters.to.generic.must.all.be.unique=Parameters to 'Generic[...]' must all be unique diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypeHintsInspection.kt b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypeHintsInspection.kt index 013a3f8a0f56..413d92c39687 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypeHintsInspection.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypeHintsInspection.kt @@ -57,6 +57,8 @@ class PyTypeHintsInspection : PyInspection() { private class Visitor(holder: ProblemsHolder, context: TypeEvalContext) : PyInspectionVisitor(holder, context) { private val genericQName = QualifiedName.fromDottedString(PyTypingTypeProvider.GENERIC) + private val protocolQName = QualifiedName.fromDottedString(PyTypingTypeProvider.PROTOCOL) + private val protocolExtQName = QualifiedName.fromDottedString(PyTypingTypeProvider.PROTOCOL_EXT) override fun visitPyCallExpression(node: PyCallExpression) { super.visitPyCallExpression(node) @@ -830,14 +832,9 @@ class PyTypeHintsInspection : PyInspection() { .mapNotNull { it.name } .joinToString(", ") - val genericTypeVarsNames = genericTypeVars - .asSequence() - .mapNotNull { it.name } - .joinToString(", ") - registerProblem(cls.superClassExpressionList, - PyPsiBundle.message("INSP.type.hints.some.type.variables.are.not.listed.in.generic", - nonGenericTypeVarsNames, genericTypeVarsNames), + PyPsiBundle.message("INSP.type.hints.generic.or.protocol.should.list.all.type.variables", + nonGenericTypeVarsNames), ProblemHighlightType.GENERIC_ERROR) } } @@ -859,7 +856,9 @@ class PyTypeHintsInspection : PyInspection() { val operand = superSubscription.operand val generic = operand is PyReferenceExpression && - genericQName in PyResolveUtil.resolveImportedElementQNameLocally(operand) + PyResolveUtil.resolveImportedElementQNameLocally(operand).any { + it in listOf(genericQName, protocolQName, protocolExtQName) + } val index = superSubscription.indexExpression val parameters = (index as? PyTupleExpression)?.elements ?: arrayOf(index) diff --git a/python/testSrc/com/jetbrains/python/inspections/PyTypeHintsInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyTypeHintsInspectionTest.java index 59794a911b05..de0ee9643eb2 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyTypeHintsInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyTypeHintsInspectionTest.java @@ -209,17 +209,20 @@ public class PyTypeHintsInspectionTest extends PyInspectionTestCase { // PY-28227 public void testGenericCompleteness() { doTestByText(""" - from typing import Generic, TypeVar, Iterable + from typing import Generic, TypeVar, Iterable, Protocol T = TypeVar('T') S = TypeVar('S') - class C(Generic[T], Iterable[S]): + class C(Generic[T], Iterable[S]): + pass + + class P(Iterable[S], Protocol[T]): pass B = Generic D = T - class A(B[D], Iterable[S]): + class A(B[D], Iterable[S]): pass class E(Generic[T], Iterable[T]): @@ -229,7 +232,8 @@ public class PyTypeHintsInspectionTest extends PyInspectionTestCase { pass class G(Iterable[T]): - pass"""); + pass + """); } // PY-31147