com.lightningkite.khrysalis.replacements.Replacements.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-plugin-common Show documentation
Show all versions of kotlin-compiler-plugin-common Show documentation
Common translational tools between Typescript and Swift.
The newest version!
package com.lightningkite.khrysalis.replacements
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.lightningkite.khrysalis.util.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.supertypes
import java.io.File
import java.io.InputStream
import java.util.*
import kotlin.collections.HashMap
import kotlin.collections.HashSet
class Replacements(var mapper: ObjectMapper) {
val functions: HashMap> = HashMap()
val gets: HashMap> = HashMap()
val sets: HashMap> = HashMap()
val types: HashMap> = HashMap()
val typeRefs: HashMap> = HashMap()
val typeReifieds: HashMap> = HashMap()
val casts: HashMap, TreeSet> = HashMap()
val direct: HashMap = HashMap()
fun getCall(
call: ResolvedCall,
descriptor: CallableDescriptor = call.candidateDescriptor,
alreadyChecked: HashSet = HashSet()
): FunctionReplacement? {
if (!alreadyChecked.add(descriptor)) return null
val result = descriptor.fqNamesToCheck
.flatMap {
functions[it]?.asSequence() ?: sequenceOf()
}
.find {
it.passes(
call = call,
descriptor = descriptor
)
} ?: (descriptor as? CallableMemberDescriptor)?.allOverridden()
?.map {
getCall(
call = call,
descriptor = it,
alreadyChecked = alreadyChecked
)
}
?.firstOrNull()
return result
}
fun getCall(
descriptor: CallableDescriptor,
receiverType: KotlinType? = null,
alreadyChecked: HashSet = HashSet()
): FunctionReplacement? {
if (!alreadyChecked.add(descriptor)) return null
val result = descriptor.fqNamesToCheck
.flatMap {
functions[it]?.asSequence() ?: sequenceOf()
}
.find {
it.passes(
descriptor = descriptor,
receiverType = receiverType
)
} ?: (descriptor as? CallableMemberDescriptor)?.allOverridden()
?.map {
getCall(
descriptor = it,
receiverType = receiverType,
alreadyChecked = alreadyChecked
)
}
?.firstOrNull()
return result
}
fun getGet(propertyDescriptor: PropertyDescriptor, receiverType: KotlinType? = null): GetReplacement? =
propertyDescriptor.fqNamesToCheck
.flatMap {
gets[it]?.asSequence() ?: sequenceOf()
}
.find {
it.passes(propertyDescriptor, receiverType)
} ?: propertyDescriptor.overriddenDescriptors.asSequence().map { getGet(it, receiverType) }.firstOrNull()
?: (propertyDescriptor as? SyntheticJavaPropertyDescriptor)?.getMethod?.let {
val accessName = it.name.asString()
val propName = propertyDescriptor.name.asString()
val all = sequenceOf(it) + it.allOverridden()
all.mapNotNull {
gets[it.simpleFqName.replace(accessName, propName)]?.find {
it.passes(
propertyDescriptor,
receiverType
)
}
?: gets[it.simplerFqName.replace(accessName, propName)]?.find {
it.passes(
propertyDescriptor,
receiverType
)
}
}.firstOrNull()
}
fun getGet(objectDescriptor: DeclarationDescriptor): GetReplacement? =
gets[objectDescriptor.simpleFqName]?.firstOrNull()
fun getSet(propertyDescriptor: PropertyDescriptor, receiverType: KotlinType? = null): SetReplacement? {
return propertyDescriptor.fqNamesToCheck
.flatMap {
sets[it]?.asSequence() ?: sequenceOf()
}
.find {
it.passes(propertyDescriptor, receiverType)
} ?: propertyDescriptor.overriddenDescriptors.asSequence().map { getSet(it, receiverType) }.firstOrNull()
?: (propertyDescriptor as? SyntheticJavaPropertyDescriptor)?.setMethod?.let {
val accessName = it.name.asString()
val propName = propertyDescriptor.name.asString()
val all = sequenceOf(it) + it.allOverridden()
all.mapNotNull {
sets[it.simpleFqName.replace(accessName, propName)]?.find {
it.passes(
propertyDescriptor,
receiverType
)
}
?: sets[it.simplerFqName.replace(accessName, propName)]?.find {
it.passes(
propertyDescriptor,
receiverType
)
}
}.firstOrNull()
}
}
fun getType(type: DeclarationDescriptor): TypeReplacement? =
type.fqNamesToCheck
.flatMap {
types[it]?.asSequence() ?: sequenceOf()
}
.find {
it.passes(type)
}
fun getType(type: KotlinType): TypeReplacement? =
if (type.constructor.declarationDescriptor is TypeParameterDescriptor) null else types[type.fqNameWithoutTypeArgs]?.find { it.passes(type) }
fun getTypeRef(type: KotlinType): TypeRefReplacement? =
typeRefs[type.fqNameWithoutTypeArgs]?.find { it.passes(type) }
fun getTypeRef(type: DeclarationDescriptor): TypeRefReplacement? =
type.fqNamesToCheck
.flatMap {
typeRefs[it]?.asSequence() ?: sequenceOf()
}
.find {
it.passes(type)
}
fun getTypeReified(type: DeclarationDescriptor): TypeReifiedReplacement? =
type.fqNamesToCheck
.flatMap {
typeReifieds[it]?.asSequence() ?: sequenceOf()
}
.find {
it.passes(type)
}
fun getTypeReified(type: KotlinType): TypeReifiedReplacement? =
if (type.constructor.declarationDescriptor is TypeParameterDescriptor) null else typeReifieds[type.fqNameWithoutTypeArgs]?.find { it.passes(type) }
fun getImplicitCast(from: KotlinType, to: KotlinType): CastRule? {
casts[from.fqNameWithoutTypeArgs to to.fqNameWithoutTypeArgs]
?.find { it.passes(from, to) }
?.let { return it }
val detailedPossibilities = from.supertypes().filter { it.supertypes().contains(to) }
for (d in detailedPossibilities) {
casts[d.fqNameWithoutTypeArgs to to.fqNameWithoutTypeArgs]
?.find { it.passes(d, to) }
?.let { return it }
}
return null
}
fun getExplicitCast(from: KotlinType, to: KotlinType): CastRule? {
casts[from.fqNameWithoutTypeArgs to to.fqNameWithoutTypeArgs]
?.find { it.passes(from, to) }
?.let { return it }
val detailedPossibilities = to.supertypes().filter { it.supertypes().contains(from) }
for (d in detailedPossibilities) {
casts[d.fqNameWithoutTypeArgs to to.fqNameWithoutTypeArgs]
?.find { it.passes(from, d) }
?.let { return it }
}
return null
}
fun requiresMutable(type: KotlinType): Boolean = (sequenceOf(type) + type.supertypes().asSequence())
.any { t -> types[t.fqNameWithoutTypeArgs]?.find { it.passes(t) }?.requiresMutable == true }
operator fun plusAssign(item: ReplacementRule) {
if(item.debug){
println("Debugging rule $item")
}
when (item) {
is FunctionReplacement -> functions.getOrPut(item.id) { TreeSet() }.merge(item)
is GetReplacement -> gets.getOrPut(item.id) { TreeSet() }.merge(item)
is SetReplacement -> sets.getOrPut(item.id) { TreeSet() }.merge(item)
is TypeReplacement -> types.getOrPut(item.id) { TreeSet() }.merge(item)
is TypeRefReplacement -> typeRefs.getOrPut(item.id) { TreeSet() }.merge(item)
is TypeReifiedReplacement -> typeReifieds.getOrPut(item.id) { TreeSet() }.merge(item)
is CastRule -> casts.getOrPut(item.from to item.to) { TreeSet() }.merge(item)
}
}
operator fun plusAssign(yaml: String) {
mapper.readValue>(yaml).forEach {
this += it
}
}
operator fun plusAssign(yaml: File) {
println("Loading replacement rules from $yaml")
mapper.readValue>(yaml).forEach {
this += it
}
}
operator fun plusAssign(yaml: MaybeZipFile) {
println("Loading replacement rules from ${yaml}")
mapper.readValue>(yaml.inputStream()).forEach {
this += it
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy