mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-05 16:36:56 +07:00
Remove PyStringLiteralType.fromLiteral
It's sufficient to promote the type of string literals to Literal['content'] when a type containing a literal type (either Literal or LiteralString) is expected, since Literal['content'] is always compatible with LiteralString. (cherry picked from commit 3c9c0b1c451a17b7f56f3376d9e6cd493a770a73) IJ-MR-112631 GitOrigin-RevId: 92e3ad2da4874e33af22c56d9dd38fd9c8ff871e
This commit is contained in:
committed by
intellij-monorepo-bot
parent
be82cf6646
commit
75aaa14404
@@ -50,51 +50,5 @@ class PyLiteralStringType private constructor(val cls: PyClass) : PyClassTypeImp
|
||||
fun match(expected: PyLiteralStringType, actual: PyClassType): Boolean {
|
||||
return actual is PyLiteralStringType || actual is PyLiteralType && expected.pyClass == actual.pyClass
|
||||
}
|
||||
|
||||
fun fromLiteral(expression: PyExpression, context: TypeEvalContext): PyType? {
|
||||
val value = when (expression) {
|
||||
is PyKeywordArgument -> expression.valueExpression
|
||||
is PyParenthesizedExpression -> PyPsiUtils.flattenParens(expression)
|
||||
else -> expression
|
||||
}
|
||||
if (value is PyStringLiteralExpression) {
|
||||
val firstNode = value.stringNodes.firstOrNull()
|
||||
if (firstNode != null) {
|
||||
if (firstNode.elementType === PyElementTypes.FSTRING_NODE) {
|
||||
val allLiteralStringFragments: Boolean = value.stringElements.filterIsInstance<PyFormattedStringElement>().flatMap { it.fragments }.mapNotNull {
|
||||
if (it.expression != null) context.getType(it.expression!!) else null
|
||||
}.all { it is PyLiteralStringType }
|
||||
return if (allLiteralStringFragments) create(expression) else PyBuiltinCache.getInstance(expression).strType
|
||||
}
|
||||
return create(value)
|
||||
}
|
||||
}
|
||||
else if (value is PySequenceExpression) {
|
||||
val classes = if (value is PyDictLiteralExpression) {
|
||||
val keyTypes = value.elements.map { fromLiteral(it.key, context) }
|
||||
val valueTypes = value.elements.map { type -> type.value?.let { fromLiteral(it, context) } }
|
||||
listOf(PyUnionType.union(keyTypes), PyUnionType.union(valueTypes))
|
||||
}
|
||||
else value.elements.map { fromLiteral(it, context) }
|
||||
|
||||
if (value is PyTupleExpression) {
|
||||
return PyTupleType.create(value, classes)
|
||||
}
|
||||
else {
|
||||
val name = when (value) {
|
||||
is PyListLiteralExpression -> "list"
|
||||
is PySetLiteralExpression -> "set"
|
||||
is PyDictLiteralExpression -> "dict"
|
||||
else -> null
|
||||
}
|
||||
return name?.let { PyCollectionTypeImpl.createTypeByQName(value, name, false, classes) }
|
||||
}
|
||||
}
|
||||
else if (value is PyConditionalExpression) {
|
||||
return PyUnionType.union(fromLiteral(value.truePart, context),
|
||||
value.falsePart?.let { fromLiteral(it, context) })
|
||||
}
|
||||
return context.getType(value ?: return null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,12 +97,6 @@ class PyLiteralType private constructor(cls: PyClass, val expression: PyExpressi
|
||||
}
|
||||
val substitution = if (substitutions != null) PyTypeChecker.substitute(expected, substitutions, context) else expected
|
||||
val substitutionOrBound = if (substitution is PyTypeVarType) substitution.bound else substitution
|
||||
if (containsLiteralString(substitutionOrBound)) {
|
||||
val literalStringType = PyLiteralStringType.fromLiteral(expression, context)
|
||||
if (literalStringType != null) {
|
||||
return literalStringType
|
||||
}
|
||||
}
|
||||
if (containsLiteral(substitutionOrBound)) {
|
||||
return fromLiteralValue(expression, context)
|
||||
}
|
||||
@@ -110,17 +104,11 @@ class PyLiteralType private constructor(cls: PyClass, val expression: PyExpressi
|
||||
}
|
||||
|
||||
private fun containsLiteral(type: PyType?): Boolean {
|
||||
return type is PyLiteralType ||
|
||||
return type is PyLiteralType || type is PyLiteralStringType ||
|
||||
type is PyUnionType && type.members.any { containsLiteral(it) } ||
|
||||
type is PyCollectionType && type.elementTypes.any { containsLiteral(it) }
|
||||
}
|
||||
|
||||
private fun containsLiteralString(type: PyType?): Boolean {
|
||||
return type is PyLiteralStringType ||
|
||||
type is PyUnionType && type.members.any { containsLiteralString(it) } ||
|
||||
type is PyCollectionType && type.elementTypes.any { containsLiteralString(it) }
|
||||
}
|
||||
|
||||
private fun toLiteralType(expression: PyExpression, context: TypeEvalContext, index: Boolean): PyType? {
|
||||
if (expression is PyNoneLiteralExpression && !expression.isEllipsis ||
|
||||
expression is PyReferenceExpression &&
|
||||
@@ -151,6 +139,18 @@ class PyLiteralType private constructor(cls: PyClass, val expression: PyExpressi
|
||||
})
|
||||
}
|
||||
|
||||
if (expression is PyStringLiteralExpression && expression.isInterpolated) {
|
||||
val allLiteralStringFragments = expression.stringElements
|
||||
.filterIsInstance<PyFormattedStringElement>()
|
||||
.flatMap { it.fragments }
|
||||
.mapNotNull { it.expression }
|
||||
.map { context.getType(it) }
|
||||
.all { it is PyLiteralStringType }
|
||||
if (allLiteralStringFragments) {
|
||||
return PyLiteralStringType.create(expression)
|
||||
}
|
||||
}
|
||||
|
||||
return classOfAcceptableLiteral(expression, context, index)?.let { PyLiteralType(it, expression) }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user