diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/createByPattern.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/createByPattern.kt index db87384fcad..ca5f5c9e7c8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/createByPattern.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/createByPattern.kt @@ -38,9 +38,32 @@ public fun JetPsiFactory.createExpressionByPattern(pattern: String, vararg args: public fun JetPsiFactory.createDeclarationByPattern(pattern: String, vararg args: Any): TDeclaration = createByPattern(pattern, *args) { createDeclaration(it) } +private open class ArgumentType(val klass: Class) + +class PlainTextArgumentType(klass: Class, val toPlainText: (T) -> String) : ArgumentType(klass) + +private val SUPPORTED_ARGUMENT_TYPES = listOf( + ArgumentType(javaClass()), + ArgumentType(javaClass()), + PlainTextArgumentType(javaClass(), toPlainText = { it }), + PlainTextArgumentType(javaClass(), toPlainText = { it.renderName() }) +) + public fun createByPattern(pattern: String, vararg args: Any, factory: (String) -> TElement): TElement { + val argumentTypes = args.map { arg -> + SUPPORTED_ARGUMENT_TYPES.firstOrNull { it.klass.isInstance(arg) } + ?: throw IllegalArgumentException("Unsupported argument type: ${arg.javaClass}, should be one of: ${SUPPORTED_ARGUMENT_TYPES.map { it.klass.getSimpleName() }.joinToString()}") + } + + // convert arguments that can be converted into plain text @suppress("NAME_SHADOWING") - val args = args.map { if (it is Name) it.renderName() else it } + val args = args.zip(argumentTypes).map { + val (arg, type) = it + if (type is PlainTextArgumentType) + (type.toPlainText as Function1).invoke(arg) // TODO: see KT-7833 + else + arg + } val (processedText, allPlaceholders) = processPattern(pattern, args) @@ -55,12 +78,9 @@ public fun createByPattern(pattern: String, vararg args: PlaceholdersLoop@ for ((n, placeholders) in allPlaceholders) { - val expectedElementType = when (args[n]) { - is String -> continue@PlaceholdersLoop // already in the text - is JetExpression -> javaClass() - is JetTypeReference -> javaClass() - else -> throw IllegalArgumentException("Unknown argument ${args[n]} - should be JetExpression, JetTypeReference or String") - } + val arg = args[n] + if (arg is String) continue // already in the text + val expectedElementType = argumentTypes[n].klass for ((range, text) in placeholders) { val token = resultElement.findElementAt(range.getStartOffset())!! @@ -163,7 +183,7 @@ private fun processPattern(pattern: String, args: List): PatternData { if (arg is String) arg else "xyz" } else { - check(arg !is String, "do not specify placeholder text for $$n - String argument passed") + check(arg !is String, "do not specify placeholder text for $$n - plain text argument passed") i += 2 // skip ':' and '\'' val endIndex = pattern.indexOf('\'', i) check(endIndex >= 0, "unclosed placeholder text")