FIR IDE: render KtFunctionalType in KtTypeRenderer
This commit is contained in:
+75
-4
@@ -16,10 +16,16 @@ abstract class KtTypeRenderer : KtAnalysisSessionComponent() {
|
|||||||
|
|
||||||
data class KtTypeRendererOptions(
|
data class KtTypeRendererOptions(
|
||||||
val renderFqNames: Boolean,
|
val renderFqNames: Boolean,
|
||||||
|
val renderFunctionTypes: Boolean
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
val DEFAULT = KtTypeRendererOptions(
|
val DEFAULT = KtTypeRendererOptions(
|
||||||
renderFqNames = true
|
renderFqNames = true,
|
||||||
|
renderFunctionTypes = true,
|
||||||
|
)
|
||||||
|
val SHORT_NAMES = KtTypeRendererOptions(
|
||||||
|
renderFqNames = false,
|
||||||
|
renderFunctionTypes = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,9 +39,7 @@ class KtDefaultTypeRenderer(override val analysisSession: KtAnalysisSession, ove
|
|||||||
when (type) {
|
when (type) {
|
||||||
is KtDenotableType -> when (type) {
|
is KtDenotableType -> when (type) {
|
||||||
is KtClassType -> {
|
is KtClassType -> {
|
||||||
render(type.classId, options)
|
renderClassType(type, options)
|
||||||
renderTypeArgumentsIfNotEmpty(type.typeArguments, options)
|
|
||||||
renderNullability(type.nullability)
|
|
||||||
}
|
}
|
||||||
is KtTypeParameterType -> {
|
is KtTypeParameterType -> {
|
||||||
append(type.name.asString())
|
append(type.name.asString())
|
||||||
@@ -64,6 +68,67 @@ class KtDefaultTypeRenderer(override val analysisSession: KtAnalysisSession, ove
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun StringBuilder.renderClassType(
|
||||||
|
type: KtClassType,
|
||||||
|
options: KtTypeRendererOptions
|
||||||
|
) {
|
||||||
|
when {
|
||||||
|
type is KtUsualClassType || !options.renderFunctionTypes -> {
|
||||||
|
renderClassTypeAsNonFunctional(type, options)
|
||||||
|
}
|
||||||
|
type is KtFunctionalType -> {
|
||||||
|
renderFunctionalType(type, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun StringBuilder.renderClassTypeAsNonFunctional(
|
||||||
|
type: KtClassType,
|
||||||
|
options: KtTypeRendererOptions
|
||||||
|
) {
|
||||||
|
render(type.classId, options)
|
||||||
|
renderTypeArgumentsIfNotEmpty(type.typeArguments, options)
|
||||||
|
renderNullability(type.nullability)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun StringBuilder.renderFunctionalType(
|
||||||
|
type: KtFunctionalType,
|
||||||
|
options: KtTypeRendererOptions
|
||||||
|
) {
|
||||||
|
wrapIf(type.nullability == KtTypeNullability.NULLABLE, left = "(", right = ")?") {
|
||||||
|
if (type.isSuspend) append("suspend ")
|
||||||
|
renderReceiverTypeOfFunctionalType(type, options)
|
||||||
|
renderParametersOfFunctionalType(type, options)
|
||||||
|
append(" -> ")
|
||||||
|
render(type.typeArguments.last(), options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun StringBuilder.renderReceiverTypeOfFunctionalType(
|
||||||
|
type: KtFunctionalType,
|
||||||
|
options: KtTypeRendererOptions
|
||||||
|
) {
|
||||||
|
type.receiverType?.let { receiverType ->
|
||||||
|
render(receiverType, options)
|
||||||
|
append(".")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun StringBuilder.renderParametersOfFunctionalType(
|
||||||
|
type: KtFunctionalType,
|
||||||
|
options: KtTypeRendererOptions
|
||||||
|
) {
|
||||||
|
append("(")
|
||||||
|
val parameterTypes = type.parameterTypes
|
||||||
|
type.parameterTypes.forEachIndexed { index, parameterType ->
|
||||||
|
render(parameterType, options)
|
||||||
|
if (index != parameterTypes.lastIndex) {
|
||||||
|
append(", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
append(")")
|
||||||
|
}
|
||||||
|
|
||||||
private fun StringBuilder.renderTypeArgumentsIfNotEmpty(typeArguments: List<KtTypeArgument>, options: KtTypeRendererOptions) {
|
private fun StringBuilder.renderTypeArgumentsIfNotEmpty(typeArguments: List<KtTypeArgument>, options: KtTypeRendererOptions) {
|
||||||
if (typeArguments.isNotEmpty()) {
|
if (typeArguments.isNotEmpty()) {
|
||||||
append("<")
|
append("<")
|
||||||
@@ -113,4 +178,10 @@ class KtDefaultTypeRenderer(override val analysisSession: KtAnalysisSession, ove
|
|||||||
render()
|
render()
|
||||||
append(")")
|
append(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inline fun StringBuilder.wrapIf(condition: Boolean, left: String, right: String, render: StringBuilder.() -> Unit) {
|
||||||
|
if (condition) append(left)
|
||||||
|
render()
|
||||||
|
if (condition) append(right)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+51
-3
@@ -83,7 +83,7 @@ class KtTypeRendererTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
type = "Map<List<Int?>, V?>?",
|
type = "Map<List<Int?>, V?>?",
|
||||||
expected = "Map<List<Int?>, V?>?",
|
expected = "Map<List<Int?>, V?>?",
|
||||||
typeArguments = listOf("V"),
|
typeArguments = listOf("V"),
|
||||||
rendererOptions = KtTypeRendererOptions(renderFqNames = false)
|
rendererOptions = KtTypeRendererOptions.SHORT_NAMES
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +91,55 @@ class KtTypeRendererTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
doTestByExpression(
|
doTestByExpression(
|
||||||
expression = "java.lang.String.CASE_INSENSITIVE_ORDER",
|
expression = "java.lang.String.CASE_INSENSITIVE_ORDER",
|
||||||
expected = "(Comparator<(String..String?)>..Comparator<(String..String?)>?)",
|
expected = "(Comparator<(String..String?)>..Comparator<(String..String?)>?)",
|
||||||
rendererOptions = KtTypeRendererOptions(renderFqNames = false)
|
rendererOptions = KtTypeRendererOptions.SHORT_NAMES
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testFunctionalType() {
|
||||||
|
doTestByTypeText(
|
||||||
|
type = "(String, Int?) -> Long",
|
||||||
|
expected = "(String, Int?) -> Long",
|
||||||
|
rendererOptions = KtTypeRendererOptions.SHORT_NAMES
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testNullableFunctionalType() {
|
||||||
|
doTestByTypeText(
|
||||||
|
type = "((String, Int?) -> Long)?",
|
||||||
|
expected = "((String, Int?) -> Long)?",
|
||||||
|
rendererOptions = KtTypeRendererOptions.SHORT_NAMES
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testFunctionalTypeNoArguments() {
|
||||||
|
doTestByTypeText(
|
||||||
|
type = "() -> Long",
|
||||||
|
expected = "() -> Long",
|
||||||
|
rendererOptions = KtTypeRendererOptions.SHORT_NAMES
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testFunctionalTypeReceiver() {
|
||||||
|
doTestByTypeText(
|
||||||
|
type = "Int.(String) -> Long",
|
||||||
|
expected = "Int.(String) -> Long",
|
||||||
|
rendererOptions = KtTypeRendererOptions.SHORT_NAMES
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testFunctionalTypeUnitReturnType() {
|
||||||
|
doTestByTypeText(
|
||||||
|
type = "(String) -> Unit",
|
||||||
|
expected = "(String) -> Unit",
|
||||||
|
rendererOptions = KtTypeRendererOptions.SHORT_NAMES
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testFunctionalTypeRenderAsUsualClassType() {
|
||||||
|
doTestByTypeText(
|
||||||
|
type = "Int.(String, Long) -> Char",
|
||||||
|
expected = "Function3<Int, String, Long, Char>",
|
||||||
|
rendererOptions = KtTypeRendererOptions.SHORT_NAMES.copy(renderFunctionTypes = false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +151,7 @@ class KtTypeRendererTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
if (x is String && x is Int) x else null
|
if (x is String && x is Int) x else null
|
||||||
}""".trimIndent(),
|
}""".trimIndent(),
|
||||||
expected = "(String?&Int?)",
|
expected = "(String?&Int?)",
|
||||||
rendererOptions = KtTypeRendererOptions(renderFqNames = false)
|
rendererOptions = KtTypeRendererOptions.SHORT_NAMES
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user