diff --git a/compiler/test/data/typescript/generic/usedOnlyInConstraint.d.kt b/compiler/test/data/typescript/generic/usedOnlyInConstraint.d.kt new file mode 100644 index 000000000..b71ae9679 --- /dev/null +++ b/compiler/test/data/typescript/generic/usedOnlyInConstraint.d.kt @@ -0,0 +1,21 @@ +// [test] usedOnlyInConstraint.kt +@file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS") + +import kotlin.js.* +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.* +import tsstdlib.ArrayLike + +external interface A { + fun > forEach(obj: U, iterator: (value: Any, key: Number, obj: U) -> Unit, context: Any = definedExternally): U +} \ No newline at end of file diff --git a/compiler/test/data/typescript/generic/usedOnlyInConstraint.d.ts b/compiler/test/data/typescript/generic/usedOnlyInConstraint.d.ts new file mode 100644 index 000000000..d04016ac2 --- /dev/null +++ b/compiler/test/data/typescript/generic/usedOnlyInConstraint.d.ts @@ -0,0 +1,7 @@ +declare interface A { + forEach>( + obj: U, + iterator: (value: U[number], key: number, obj: U) => void, + context?: any + ): U; +} \ No newline at end of file diff --git a/model-lowerings-common/src/org/jetbrains/dukat/model/commonLowerings/removeRedundantTypeParams.kt b/model-lowerings-common/src/org/jetbrains/dukat/model/commonLowerings/removeRedundantTypeParams.kt index 363dd830d..b20df7127 100644 --- a/model-lowerings-common/src/org/jetbrains/dukat/model/commonLowerings/removeRedundantTypeParams.kt +++ b/model-lowerings-common/src/org/jetbrains/dukat/model/commonLowerings/removeRedundantTypeParams.kt @@ -8,6 +8,7 @@ import org.jetbrains.dukat.astModel.MemberModel import org.jetbrains.dukat.astModel.MethodModel import org.jetbrains.dukat.astModel.ModuleModel import org.jetbrains.dukat.astModel.TypeModel +import org.jetbrains.dukat.astModel.TypeParameterModel import org.jetbrains.dukat.astModel.TypeParameterReferenceModel import org.jetbrains.dukat.astModel.TypeValueModel import org.jetbrains.dukat.ownerContext.NodeOwner @@ -18,15 +19,36 @@ private fun TypeModel.collectTypeParams(): List { is TypeParameterReferenceModel -> listOf(this.name) is TypeValueModel -> params.flatMap { it.type.collectTypeParams() } is FunctionTypeModel -> parameters.flatMap { it.type.collectTypeParams() } + type.collectTypeParams() + is TypeParameterModel -> type.collectTypeParams() else -> emptyList() } } class RemoveRedundantTypeParamsLowering: TopLevelModelLowering { + + private fun getTypeParamsDependencies(typeParam: NameEntity, allTypeParams: List): List { + return allTypeParams.find { (it.type as? TypeValueModel)?.value == typeParam }?.constraints?.flatMap { + it.collectTypeParams() + }.orEmpty() + } + + private fun getUsedTypeParams(methodModel: MethodModel, alreadyKnownUsed: List): List { + val dependencies = alreadyKnownUsed.flatMap { getTypeParamsDependencies(it, methodModel.typeParameters) }.distinct() + if (alreadyKnownUsed.containsAll(dependencies)) { + return alreadyKnownUsed + } + return getUsedTypeParams(methodModel, (alreadyKnownUsed + dependencies).distinct()) + } + + private fun getUsedTypeParams(methodModel: MethodModel): List { + val fromTypes = (methodModel.parameters.flatMap { it.type.collectTypeParams() } + methodModel.type.collectTypeParams()).distinct() + return getUsedTypeParams(methodModel, fromTypes) + } + private fun lowerMethodModel(ownerContext: NodeOwner): MethodModel { val methodModel = ownerContext.node - val usedTypeParams = (methodModel.parameters.flatMap { it.type.collectTypeParams() } + methodModel.type.collectTypeParams()) + val usedTypeParams = getUsedTypeParams(methodModel) val typeParamsResolved = methodModel.typeParameters.filter { typeParameterModel -> val type = typeParameterModel.type if (type is TypeValueModel) {