Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge multiple lambda properties with same name and type, but different metadata #350

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,29 @@
// [test] optionalConflictingMethods.kt
@file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS")

import kotlin.js.*
import kotlin.js.Json
import org.khronos.webgl.*
import org.w3c.dom.*
import org.w3c.dom.events.*
import org.w3c.dom.parsing.*
import org.w3c.dom.svg.*
import org.w3c.dom.url.*
import org.w3c.fetch.*
import org.w3c.files.*
import org.w3c.notifications.*
import org.w3c.performance.*
import org.w3c.workers.*
import org.w3c.xhr.*

external interface WritableStateOptions {
val write: ((encoding: String /* "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex" */) -> Unit)?
get() = definedExternally
}

external interface RealConflict {
val conflictMethod: ((arg: String) -> Unit)?
get() = definedExternally
val conflictMethod: ((arg: Number) -> Unit)?
get() = definedExternally
}
@@ -0,0 +1,7 @@
interface WritableStateOptions {
write?(encoding: "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex" | string): void;
}

interface RealConflict {
conflictMethod?(arg: string | number): void;
}
Expand Up @@ -6,11 +6,14 @@ import org.jetbrains.dukat.astCommon.rightMost
import org.jetbrains.dukat.astModel.ClassLikeModel
import org.jetbrains.dukat.astModel.ClassModel
import org.jetbrains.dukat.astModel.FunctionModel
import org.jetbrains.dukat.astModel.FunctionTypeModel
import org.jetbrains.dukat.astModel.InterfaceModel
import org.jetbrains.dukat.astModel.LambdaParameterModel
import org.jetbrains.dukat.astModel.MemberModel
import org.jetbrains.dukat.astModel.MethodModel
import org.jetbrains.dukat.astModel.ModuleModel
import org.jetbrains.dukat.astModel.ParameterModel
import org.jetbrains.dukat.astModel.PropertyModel
import org.jetbrains.dukat.astModel.TypeModel
import org.jetbrains.dukat.astModel.TypeParameterModel
import org.jetbrains.dukat.astModel.TypeValueModel
Expand All @@ -19,6 +22,11 @@ import org.jetbrains.dukat.ownerContext.NodeOwner
private fun TypeModel.withoutMeta(): TypeModel {
return when (this) {
is TypeValueModel -> copy(metaDescription = null, params = params.map { param -> param.copy(type = param.type.withoutMeta()) })
is FunctionTypeModel -> copy(
metaDescription = null,
parameters = parameters.map { it.copy(type = it.type.withoutMeta()) },
type = type.withoutMeta()
)
else -> this
}
}
Expand All @@ -45,6 +53,8 @@ private fun mergeTypeModels(a: TypeModel, b: TypeModel): TypeModel {
}
}
a.copy(metaDescription = metaDescription, params = mergeTypeParams(a.params, b.params))
} else if ((a is FunctionTypeModel) && (b is FunctionTypeModel)) {
a.copy(type = mergeTypeModels(a.type, b.type), parameters = mergeLambdaParams(a.parameters, b.parameters))
} else {
a
}
Expand All @@ -57,6 +67,12 @@ private fun mergeTypeModelsAsReturn(a: TypeModel, b: TypeModel): TypeModel {
} else {
TypeValueModel(IdentifierEntity("dynamic"), listOf(), listOfNotNull(a.fqName?.rightMost(), b.fqName?.rightMost()).joinToString(" | ") { it.toString() }, null)
}
} else if ((a is FunctionTypeModel) && (b is FunctionTypeModel)) {
if (a.withoutMeta() == b.withoutMeta()) {
mergeTypeModels(a, b)
} else {
TypeValueModel(IdentifierEntity("dynamic"), listOf(), null, null)
}
} else {
TypeValueModel(IdentifierEntity("dynamic"), listOf(), null, null)
}
Expand All @@ -68,12 +84,22 @@ private fun mergeTypeParams(a: List<TypeParameterModel>, b: List<TypeParameterMo
}
}

private fun mergeLambdaParams(a: List<LambdaParameterModel>, b: List<LambdaParameterModel>): List<LambdaParameterModel> {
return a.zip(b).map { (paramA, paramB) ->
paramA.copy(type = mergeTypeModels(paramA.type, paramB.type))
}
}

private fun mergeParams(a: List<ParameterModel>, b: List<ParameterModel>): List<ParameterModel> {
return a.zip(b).map { (paramA, paramB) ->
paramA.copy(type = mergeTypeModels(paramA.type, paramB.type))
}
}

private fun mergePropertyModels(a: PropertyModel, b: PropertyModel): PropertyModel {
return a.copy(type = mergeTypeModelsAsReturn(a.type, b.type))
}

private fun mergeMethodModels(a: MethodModel, b: MethodModel): MethodModel {
return a.copy(parameters = mergeParams(a.parameters, b.parameters), type = mergeTypeModelsAsReturn(a.type, b.type))
}
Expand All @@ -85,18 +111,28 @@ private fun mergeFunctionModels(a: FunctionModel, b: FunctionModel): FunctionMod
typealias CallableKey = Triple<NameEntity, List<TypeModel>, List<TypeModel>>

private fun ClassLikeModel.resolveMembers(): List<MemberModel> {
val keyCache = mutableMapOf<MethodModel, CallableKey>()
val methodsKeyCache = mutableMapOf<MethodModel, CallableKey>()
val propertiesKeyCache = mutableMapOf<PropertyModel, CallableKey>()

val methodsBucket = members.filterIsInstance(MethodModel::class.java).groupBy { methodModel ->
val key = methodModel.getKey()
keyCache.put(methodModel, key)
methodsKeyCache.put(methodModel, key)
key
}.toMutableMap()

val propertiesBucket = members.filterIsInstance<PropertyModel>().groupBy { propertyModel ->
val key = propertyModel.getKey()
propertiesKeyCache[propertyModel] = key
key
}.toMutableMap()

return members.mapNotNull { memberModel ->
when (memberModel) {
is MethodModel -> {
methodsBucket.remove(keyCache[memberModel])?.reduce { a, b -> mergeMethodModels(a, b) }
methodsBucket.remove(methodsKeyCache[memberModel])?.reduce { a, b -> mergeMethodModels(a, b) }
}
is PropertyModel -> {
propertiesBucket.remove(propertiesKeyCache[memberModel])?.reduce { a, b -> mergePropertyModels(a, b) }
}
else -> memberModel
}
Expand All @@ -111,6 +147,10 @@ private fun MethodModel.getKey(): CallableKey {
return Triple(name, parameters.map { it.type.withoutMeta() }, typeParameters.map { it.type.withoutMeta() })
}

private fun PropertyModel.getKey(): CallableKey {
return Triple(name, listOf(type.withoutMeta()), typeParameters.map { it.type.withoutMeta() })
}

class RemoveConflictingOverloads : ModelLowering {
override fun lower(module: ModuleModel): ModuleModel {
val keyCache = mutableMapOf<FunctionModel, CallableKey>()
Expand Down