KspTypeMapper.kt
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.room.compiler.processing.ksp
import com.squareup.javapoet.TypeName
/**
* Maps java specific types to their kotlin counterparts.
* see: https://github.com/google/ksp/issues/126
* see: https://github.com/google/ksp/issues/125
*
* `Resolver.getClassDeclarationByName` returns the java representation of a class even when a
* kotlin version of the same class exists. e.g. It returns a KSClassDeclaration representing
* `java.lang.String` if queried with `java.lang.String`. Even though this makes sense by itself,
* it is inconsistent with the kotlin compiler which will resolve all instances of
* `java.lang.String` to `kotlin.String` (even if it is in Java source code).
*
* Until KSP provides compiler consistent behavior, this helper utility does the mapping for us.
*
* This list is built from https://kotlinlang.org/docs/reference/java-interop.html#mapped-types.
* Hopefully, it will be temporary until KSP provides a utility to do the same conversion.
*/
object KspTypeMapper {
private val mapping = mutableMapOf<String, String>()
private val kotlinTypeToJavaPrimitiveMapping = mapOf(
"kotlin.Byte" to TypeName.BYTE,
"kotlin.Short" to TypeName.SHORT,
"kotlin.Int" to TypeName.INT,
"kotlin.Long" to TypeName.LONG,
"kotlin.Char" to TypeName.CHAR,
"kotlin.Float" to TypeName.FLOAT,
"kotlin.Double" to TypeName.DOUBLE,
"kotlin.Boolean" to TypeName.BOOLEAN
)
private val javaPrimitiveQNames = kotlinTypeToJavaPrimitiveMapping
.values.mapTo(mutableSetOf()) {
it.toString()
}
init {
// https://kotlinlang.org/docs/reference/java-interop.html#mapped-types
kotlinTypeToJavaPrimitiveMapping.forEach {
mapping[it.value.toString()] = it.key
}
mapping["java.lang.Object"] = "kotlin.Any"
mapping["java.lang.Cloneable"] = "kotlin.Cloneable"
mapping["java.lang.Comparable"] = "kotlin.Comparable"
mapping["java.lang.Enum"] = "kotlin.Enum"
mapping["java.lang.Annotation"] = "kotlin.Annotation"
mapping["java.lang.CharSequence"] = "kotlin.CharSequence"
mapping["java.lang.String"] = "kotlin.String"
mapping["java.lang.Number"] = "kotlin.Number"
mapping["java.lang.Throwable"] = "kotlin.Throwable"
mapping["java.lang.Byte"] = "kotlin.Byte"
mapping["java.lang.Short"] = "kotlin.Short"
mapping["java.lang.Integer"] = "kotlin.Int"
mapping["java.lang.Long"] = "kotlin.Long"
mapping["java.lang.Character"] = "kotlin.Char"
mapping["java.lang.Float"] = "kotlin.Float"
mapping["java.lang.Double"] = "kotlin.Double"
mapping["java.lang.Boolean"] = "kotlin.Boolean"
// collections. default to mutable ones since java types are always mutable
mapping["java.util.Iterator"] = "kotlin.collections.MutableIterator"
mapping["java.lang.Iterable"] = "kotlin.collections.Iterable"
mapping["java.util.Collection"] = "kotlin.collections.MutableCollection"
mapping["java.util.Set"] = "kotlin.collections.MutableSet"
mapping["java.util.List"] = "kotlin.collections.MutableList"
mapping["java.util.ListIterator"] = "kotlin.collections.ListIterator"
mapping["java.util.Map"] = "kotlin.collections.MutableMap"
mapping["java.util.Map.Entry"] = "kotlin.collections.MutableEntry"
}
fun swapWithKotlinType(javaType: String): String = mapping[javaType] ?: javaType
fun getPrimitiveJavaTypeName(kotlinType: String) = kotlinTypeToJavaPrimitiveMapping[kotlinType]
fun isJavaPrimitiveType(qName: String) = javaPrimitiveQNames.contains(qName)
}