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