Support having primary type parameter other than T in generated code
With some limitations: the primary parameter cannot have constraints for now.
This commit is contained in:
@@ -57,6 +57,7 @@ class MemberBuilder(
|
||||
var infix: Boolean = false; private set
|
||||
var operator: Boolean = false; private set
|
||||
val typeParams = mutableListOf<String>()
|
||||
var primaryTypeParameter: String? = null; private set
|
||||
var customReceiver: String? = null; private set
|
||||
var receiverAsterisk: Boolean = false // TODO: rename to genericStarProjection
|
||||
var toNullableT: Boolean = false
|
||||
@@ -97,8 +98,12 @@ class MemberBuilder(
|
||||
@Deprecated("Use specialFor", ReplaceWith("specialFor(*fs) { returns(run(valueBuilder)) }"))
|
||||
fun returns(vararg fs: Family, valueBuilder: () -> String) = specialFor(*fs) { returns(run(valueBuilder)) }
|
||||
|
||||
fun typeParam(typeParameterName: String) {
|
||||
fun typeParam(typeParameterName: String, primary: Boolean = false) {
|
||||
typeParams += typeParameterName
|
||||
if (primary) {
|
||||
check(primaryTypeParameter == null)
|
||||
primaryTypeParameter = typeParameterName
|
||||
}
|
||||
}
|
||||
|
||||
fun annotation(annotation: String) {
|
||||
@@ -171,7 +176,7 @@ class MemberBuilder(
|
||||
}
|
||||
|
||||
val returnType = returns ?: throw RuntimeException("No return type specified for $signature")
|
||||
|
||||
val primaryTypeParameter = this.primaryTypeParameter ?: "T"
|
||||
|
||||
fun renderType(expression: String, receiver: String, self: String): String {
|
||||
val t = StringTokenizer(expression, " \t\n,:()<>?.", true)
|
||||
@@ -210,12 +215,12 @@ class MemberBuilder(
|
||||
"TCollection" -> {
|
||||
when (family) {
|
||||
CharSequences, Strings -> "Appendable"
|
||||
else -> renderType("MutableCollection<in T>", receiver, self)
|
||||
else -> renderType("MutableCollection<in $primaryTypeParameter>", receiver, self)
|
||||
}
|
||||
}
|
||||
"T" -> {
|
||||
primaryTypeParameter -> {
|
||||
when (family) {
|
||||
Generic -> "T"
|
||||
Generic -> primaryTypeParameter
|
||||
CharSequences, Strings -> "Char"
|
||||
Maps -> "Map.Entry<K, V>"
|
||||
else -> primitive?.name ?: token
|
||||
@@ -223,13 +228,13 @@ class MemberBuilder(
|
||||
}
|
||||
"TRange" -> {
|
||||
when (family) {
|
||||
Generic -> "Range<T>"
|
||||
Generic -> "Range<$primaryTypeParameter>"
|
||||
else -> primitive!!.name + "Range"
|
||||
}
|
||||
}
|
||||
"TProgression" -> {
|
||||
when (family) {
|
||||
Generic -> "Progression<out T>"
|
||||
Generic -> "Progression<out $primaryTypeParameter>"
|
||||
else -> primitive!!.name + "Progression"
|
||||
}
|
||||
}
|
||||
@@ -240,7 +245,7 @@ class MemberBuilder(
|
||||
return answer.toString()
|
||||
}
|
||||
|
||||
val isAsteriskOrT = if (receiverAsterisk) "*" else "T"
|
||||
val isAsteriskOrT = if (receiverAsterisk) "*" else primaryTypeParameter
|
||||
val self = (when (family) {
|
||||
Iterables -> "Iterable<$isAsteriskOrT>"
|
||||
Collections -> "Collection<$isAsteriskOrT>"
|
||||
@@ -248,8 +253,8 @@ class MemberBuilder(
|
||||
Maps -> "Map<out K, V>"
|
||||
Sets -> "Set<$isAsteriskOrT>"
|
||||
Sequences -> "Sequence<$isAsteriskOrT>"
|
||||
InvariantArraysOfObjects -> "Array<T>"
|
||||
ArraysOfObjects -> "Array<${isAsteriskOrT.replace("T", "out T")}>"
|
||||
InvariantArraysOfObjects -> "Array<$primaryTypeParameter>"
|
||||
ArraysOfObjects -> "Array<${isAsteriskOrT.replace(primaryTypeParameter, "out $primaryTypeParameter")}>"
|
||||
Strings -> "String"
|
||||
CharSequences -> "CharSequence"
|
||||
Ranges -> "ClosedRange<$isAsteriskOrT>"
|
||||
@@ -257,7 +262,7 @@ class MemberBuilder(
|
||||
RangesOfPrimitives -> primitive?.let { it.name + "Range" } ?: throw IllegalArgumentException("Primitive range should specify primitive type")
|
||||
ProgressionsOfPrimitives -> primitive?.let { it.name + "Progression" } ?: throw IllegalArgumentException("Primitive progression should specify primitive type")
|
||||
Primitives -> primitive?.let { it.name } ?: throw IllegalArgumentException("Primitive should specify primitive type")
|
||||
Generic -> "T"
|
||||
Generic -> primaryTypeParameter
|
||||
})
|
||||
|
||||
val receiver = (customReceiver ?: self).let { renderType(it, it, self) }
|
||||
@@ -268,8 +273,8 @@ class MemberBuilder(
|
||||
val parameters = typeParams.mapTo(mutableListOf()) { parseTypeParameter(it.renderType()) }
|
||||
|
||||
if (family == Generic) {
|
||||
if (parameters.none { it.name == "T" })
|
||||
parameters.add(TypeParameter("T"))
|
||||
if (parameters.none { it.name == primaryTypeParameter })
|
||||
parameters.add(TypeParameter(primaryTypeParameter))
|
||||
return parameters
|
||||
} else if (primitive == null && family != Strings && family != CharSequences) {
|
||||
val mentionedTypes = parseTypeRef(receiver).mentionedTypes() + parameters.flatMap { it.mentionedTypeRefs() }
|
||||
@@ -283,7 +288,7 @@ class MemberBuilder(
|
||||
return parameters
|
||||
} else {
|
||||
// substituted T is no longer a parameter
|
||||
val renderedT = "T".renderType()
|
||||
val renderedT = primaryTypeParameter.renderType()
|
||||
return parameters.filterNot { it.name == renderedT }
|
||||
}
|
||||
}
|
||||
@@ -318,7 +323,7 @@ class MemberBuilder(
|
||||
|
||||
if (!f.isPrimitiveSpecialization && primitive != null) {
|
||||
platformName
|
||||
?.replace("<T>", primitive!!.name)
|
||||
?.replace("<$primaryTypeParameter>", primitive!!.name)
|
||||
?.let { platformName -> builder.append("@kotlin.jvm.JvmName(\"${platformName}\")\n") }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user