diff --git a/src/main/kotlin/space/whitememory/pythoninlayparams/types/AbstractPythonInlayTypeHintsCollector.kt b/src/main/kotlin/space/whitememory/pythoninlayparams/types/AbstractPythonInlayTypeHintsCollector.kt index 23b0ba1..ce2b450 100644 --- a/src/main/kotlin/space/whitememory/pythoninlayparams/types/AbstractPythonInlayTypeHintsCollector.kt +++ b/src/main/kotlin/space/whitememory/pythoninlayparams/types/AbstractPythonInlayTypeHintsCollector.kt @@ -22,7 +22,7 @@ abstract class AbstractPythonInlayTypeHintsCollector(editor: Editor, open val se protected fun renderTypeHint(element: PyElement, typeEvalContext: TypeEvalContext, sink: InlayHintsSink) { val typeAnnotation = HintResolver.getExpressionAnnotationType(element, typeEvalContext) - val hintName = HintGenerator.generateTypeHintText(typeAnnotation, typeEvalContext) + val hintName = HintGenerator.generateTypeHintText(element, typeAnnotation, typeEvalContext) displayTypeHint(element, sink, hintName) } diff --git a/src/main/kotlin/space/whitememory/pythoninlayparams/types/hints/HintGenerator.kt b/src/main/kotlin/space/whitememory/pythoninlayparams/types/hints/HintGenerator.kt index 0452682..1fbfcf9 100644 --- a/src/main/kotlin/space/whitememory/pythoninlayparams/types/hints/HintGenerator.kt +++ b/src/main/kotlin/space/whitememory/pythoninlayparams/types/hints/HintGenerator.kt @@ -1,19 +1,22 @@ package space.whitememory.pythoninlayparams.types.hints import com.jetbrains.python.PyNames +import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider +import com.jetbrains.python.psi.PyElement +import com.jetbrains.python.psi.PyFunction import com.jetbrains.python.psi.PyLambdaExpression import com.jetbrains.python.psi.types.* enum class HintGenerator { - UNION_TYPE { - override fun handleType(type: PyType?, typeEvalContext: TypeEvalContext): String? { + UNION_TYPE() { + override fun handleType(element: PyElement, type: PyType?, typeEvalContext: TypeEvalContext): String? { if (type !is PyUnionType) { return null } val generatedValues = type.members .filterNotNull() - .map { generateTypeHintText(it, typeEvalContext) } + .map { generateTypeHintText(element, it, typeEvalContext) } .distinct() if (PyNames.NONE in generatedValues) { @@ -24,8 +27,24 @@ enum class HintGenerator { } }, - COLLECTION_TYPE { - override fun handleType(type: PyType?, typeEvalContext: TypeEvalContext): String? { + ASYNC_TYPE() { + override fun handleType(element: PyElement, type: PyType?, typeEvalContext: TypeEvalContext): String? { + if (type == null || element !is PyFunction) { + return null + } + + if (type is PyCollectionType && type.classQName == PyTypingTypeProvider.COROUTINE && element.isAsync) { + return generateTypeHintText( + element, PyTypingTypeProvider.coroutineOrGeneratorElementType(type)?.get(), typeEvalContext + ) + } + + return null + } + }, + + COLLECTION_TYPE() { + override fun handleType(element: PyElement, type: PyType?, typeEvalContext: TypeEvalContext): String? { if ( type is PyCollectionType && type.name != null @@ -41,7 +60,7 @@ enum class HintGenerator { return collectionName } - val elements = type.elementTypes.mapNotNull { generateTypeHintText(it, typeEvalContext) } + val elements = type.elementTypes.mapNotNull { generateTypeHintText(element, it, typeEvalContext) } if (elements.isEmpty()) { return collectionName @@ -54,8 +73,8 @@ enum class HintGenerator { } }, - TUPLE_TYPE { - override fun handleType(type: PyType?, typeEvalContext: TypeEvalContext): String? { + TUPLE_TYPE() { + override fun handleType(element: PyElement, type: PyType?, typeEvalContext: TypeEvalContext): String? { if (type !is PyTupleType) { return null } @@ -65,20 +84,20 @@ enum class HintGenerator { } if (type.elementCount > 2) { - val firstElement = generateTypeHintText(type.elementTypes[0], typeEvalContext) - val secondElement = generateTypeHintText(type.elementTypes[1], typeEvalContext) - + val firstElement = generateTypeHintText(element, type.elementTypes[0], typeEvalContext) + val secondElement = generateTypeHintText(element, type.elementTypes[1], typeEvalContext) + return "${PyNames.TUPLE}[$firstElement, $secondElement, ...]" } return type.elementTypes - .mapNotNull { generateTypeHintText(it, typeEvalContext) } + .mapNotNull { generateTypeHintText(element, it, typeEvalContext) } .joinToString(separator = ", ", prefix = "${PyNames.TUPLE}[", postfix = "]") } }, - CLASS_TYPE { - override fun handleType(type: PyType?, typeEvalContext: TypeEvalContext): String? { + CLASS_TYPE() { + override fun handleType(element: PyElement, type: PyType?, typeEvalContext: TypeEvalContext): String? { if (type is PyClassType && type.isDefinition) { return "${PyNames.TYPE.replaceFirstChar { it.titlecaseChar() }}[${type.declarationElement?.name}]" } @@ -87,8 +106,8 @@ enum class HintGenerator { } }, - FUNCTION_TYPE { - override fun handleType(type: PyType?, typeEvalContext: TypeEvalContext): String? { + FUNCTION_TYPE() { + override fun handleType(element: PyElement, type: PyType?, typeEvalContext: TypeEvalContext): String? { if (type !is PyFunctionType) { return null } @@ -104,20 +123,20 @@ enum class HintGenerator { val callableReturnType = typeEvalContext.getReturnType(type.callable) - return "$parametersText -> (${generateTypeHintText(callableReturnType, typeEvalContext)})" + return "$parametersText -> (${generateTypeHintText(element, callableReturnType, typeEvalContext)})" } }, - ANY_TYPE { - override fun handleType(type: PyType?, typeEvalContext: TypeEvalContext): String { + ANY_TYPE() { + override fun handleType(element: PyElement, type: PyType?, typeEvalContext: TypeEvalContext): String { return type?.name ?: PyNames.UNKNOWN_TYPE } }; - abstract fun handleType(type: PyType?, typeEvalContext: TypeEvalContext): String? + abstract fun handleType(element: PyElement, type: PyType?, typeEvalContext: TypeEvalContext): String? companion object { - fun generateTypeHintText(type: PyType?, typeEvalContext: TypeEvalContext): String = - values().firstNotNullOf { it.handleType(type, typeEvalContext) } + fun generateTypeHintText(element: PyElement, type: PyType?, typeEvalContext: TypeEvalContext): String = + values().firstNotNullOf { it.handleType(element, type, typeEvalContext) } } } \ No newline at end of file diff --git a/src/main/kotlin/space/whitememory/pythoninlayparams/types/hints/HintResolver.kt b/src/main/kotlin/space/whitememory/pythoninlayparams/types/hints/HintResolver.kt index b10c6a6..63ea3ea 100644 --- a/src/main/kotlin/space/whitememory/pythoninlayparams/types/hints/HintResolver.kt +++ b/src/main/kotlin/space/whitememory/pythoninlayparams/types/hints/HintResolver.kt @@ -458,7 +458,6 @@ enum class HintResolver { if ( typeAnnotation == null - || (element is PyFunction && element.isAsync) // TODO: Handle async functions properly || (element is PyFunction && typeAnnotation is PyNoneType) || ((element is PyFunction || element is PyTargetExpression) && (element as PyTypeCommentOwner).typeCommentAnnotation != null) || (element is PyAnnotationOwner && element.annotation != null)