Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ external interface BaseEvent {
fun getDelegateTarget(): Shape
fun getElement(): Element
fun <T : Shape> transform(shape: T = definedExternally): T
var prop: Any
val prop: Any
fun queryByReturnType(query: String, parameters: Array<Any> = definedExternally): InvariantBox<Any>
var thisIsNullable: String?
}
Expand All @@ -49,7 +49,7 @@ external interface NumberEvent : BaseEvent {
}

external open class ParentClass {
open var prop: Any
open val prop: Any
open fun ping(message: String)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,5 @@ external interface BaseEvent {
fun getElement(): Element
fun <T : Shape> transform(shape: T = definedExternally): T
fun getSortOfEventTarget(): SortOfEventTarget
var prop: Any
val prop: Any
}
2 changes: 1 addition & 1 deletion compiler/test/data/typescript/class/override/simple.d.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import org.w3c.xhr.*
external open class Foo {
open fun bar()
open fun bar(a: Number)
open var baz: Any
open val baz: Any
}

external open class Boo : Foo {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import org.w3c.xhr.*
external interface Foo {
fun bar()
fun bar(a: Number)
var baz: Any
val baz: Any
}

external interface Boo : Foo {
Expand Down
30 changes: 30 additions & 0 deletions compiler/test/data/typescript/override/varConflict.d.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// [test] varConflict.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 open class B {
open val x: Boolean
}

external interface C {
val x: Boolean?
get() = definedExternally
}

external open class A : B, C {
override var x: Boolean
}
11 changes: 11 additions & 0 deletions compiler/test/data/typescript/override/varConflict.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
declare class B {
x: boolean
}

declare interface C {
x?: boolean
}

declare class A extends B implements C {
x: boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// [test] varConflictWithoutPropertyInChild.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 open class B {
open val x: Boolean
}

external interface C {
val x: Boolean?
get() = definedExternally
}

external open class A : B, C {
override val x: Boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
declare class B {
x: boolean
}

declare interface C {
x?: boolean
}

declare class A extends B implements C {

}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ class DescriptorTests {
"misc/stringTypeInAlias",
"qualifiedNames/extendingEntityFromParentModule",
"stdlib/convertTsStdlib",
"typePredicate/simple"
"typePredicate/simple",
"override/varConflict",
"override/varConflictWithoutPropertyInChild"
).map { it.replace("/", System.getProperty("file.separator")) }

@JvmStatic
Expand Down
1 change: 1 addition & 0 deletions model-lowerings-common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ dependencies {
implementation(project(":ast-common"))
implementation(project(":ast-model"))
implementation(project(":graphs"))
implementation(project(":itertools"))
implementation(project(":logging"))
implementation(project(":ownerContext"))
implementation(project(":panic"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import org.jetbrains.dukat.astModel.SourceSetModel
import org.jetbrains.dukat.graphs.Graph
import org.jetbrains.dukat.model.commonLowerings.overrides.InheritanceContext

private fun ModelContext.buildInheritanceGraph(): Graph<ClassLikeModel> {
internal fun ModelContext.buildInheritanceGraph(): Graph<ClassLikeModel> {
val graph = Graph<ClassLikeModel>()

getClassLikeIterable().forEach { classLike ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,36 +18,6 @@ import org.jetbrains.dukat.astModel.PropertyModel
import org.jetbrains.dukat.astModel.TypeAliasModel
import org.jetbrains.dukat.astModel.VariableModel
import org.jetbrains.dukat.astModel.LambdaParameterModel
import org.jetbrains.dukat.astModel.expressions.AsExpressionModel
import org.jetbrains.dukat.astModel.expressions.BinaryExpressionModel
import org.jetbrains.dukat.astModel.expressions.CallExpressionModel
import org.jetbrains.dukat.astModel.expressions.ConditionalExpressionModel
import org.jetbrains.dukat.astModel.expressions.ExpressionModel
import org.jetbrains.dukat.astModel.expressions.IdentifierExpressionModel
import org.jetbrains.dukat.astModel.expressions.IndexExpressionModel
import org.jetbrains.dukat.astModel.expressions.NonNullExpressionModel
import org.jetbrains.dukat.astModel.expressions.PropertyAccessExpressionModel
import org.jetbrains.dukat.astModel.expressions.SuperExpressionModel
import org.jetbrains.dukat.astModel.expressions.ThisExpressionModel
import org.jetbrains.dukat.astModel.expressions.UnaryExpressionModel
import org.jetbrains.dukat.astModel.expressions.literals.BooleanLiteralExpressionModel
import org.jetbrains.dukat.astModel.expressions.literals.LiteralExpressionModel
import org.jetbrains.dukat.astModel.expressions.templates.ExpressionTemplateTokenModel
import org.jetbrains.dukat.astModel.expressions.templates.StringTemplateTokenModel
import org.jetbrains.dukat.astModel.expressions.templates.TemplateExpressionModel
import org.jetbrains.dukat.astModel.expressions.templates.TemplateTokenModel
import org.jetbrains.dukat.astModel.statements.AssignmentStatementModel
import org.jetbrains.dukat.astModel.statements.BlockStatementModel
import org.jetbrains.dukat.astModel.statements.BreakStatementModel
import org.jetbrains.dukat.astModel.statements.CaseModel
import org.jetbrains.dukat.astModel.statements.ContinueStatementModel
import org.jetbrains.dukat.astModel.statements.ExpressionStatementModel
import org.jetbrains.dukat.astModel.statements.IfStatementModel
import org.jetbrains.dukat.astModel.statements.ReturnStatementModel
import org.jetbrains.dukat.astModel.statements.RunBlockStatementModel
import org.jetbrains.dukat.astModel.statements.StatementModel
import org.jetbrains.dukat.astModel.statements.WhenStatementModel
import org.jetbrains.dukat.astModel.statements.WhileStatementModel
import org.jetbrains.dukat.logger.Logging
import org.jetbrains.dukat.ownerContext.NodeOwner
import org.jetbrains.dukat.ownerContext.wrap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ internal class OverrideTypeChecker(
private val context: ModelContext,
private val inheritanceContext: InheritanceContext,
private val declaration: ClassLikeModel,
private val parent: ClassLikeModel
private val parent: ClassLikeModel?
) {

private fun TypeModel.isDynamic(): Boolean {
Expand Down Expand Up @@ -154,7 +154,7 @@ internal class OverrideTypeChecker(
}
}

private fun TypeModel.isOverridingReturnType(otherParameterType: TypeModel, box: TypeValueModel? = null): Boolean {
fun TypeModel.isOverridingReturnType(otherParameterType: TypeModel, box: TypeValueModel? = null): Boolean {
val inbox = (box == null || box.value == IdentifierEntity("Array"))

if (isEquivalent(otherParameterType) && inbox) {
Expand Down Expand Up @@ -192,7 +192,7 @@ internal class OverrideTypeChecker(
}
}
} else {
return fqName == otherParameterType.fqName
return fqName == otherParameterType.fqName && !(otherParameterType.nullable && !nullable)
}
}

Expand Down Expand Up @@ -287,6 +287,9 @@ internal class OverrideTypeChecker(
}

private fun TypeParameterReferenceModel.isEquivalent(otherTypeParameter: TypeParameterReferenceModel): Boolean {
if (parent == null) {
return false
}
val otherTypeParameterIndex = parent.typeParameters.indexOfFirst {
val type = it.type
type is TypeValueModel && type.value == otherTypeParameter.name
Expand All @@ -297,7 +300,7 @@ internal class OverrideTypeChecker(
return this == relevantHeritage?.typeParams?.getOrNull(otherTypeParameterIndex)
}

private fun TypeModel.isEquivalent(otherParameterType: TypeModel): Boolean {
fun TypeModel.isEquivalent(otherParameterType: TypeModel): Boolean {
if (this == otherParameterType) {
return true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,27 @@ import org.jetbrains.dukat.astModel.ClassLikeModel
import org.jetbrains.dukat.astModel.ClassModel
import org.jetbrains.dukat.astModel.EnumModel
import org.jetbrains.dukat.astModel.FunctionModel
import org.jetbrains.dukat.astModel.FunctionTypeModel
import org.jetbrains.dukat.astModel.InterfaceModel
import org.jetbrains.dukat.astModel.MemberModel
import org.jetbrains.dukat.astModel.ModuleModel
import org.jetbrains.dukat.astModel.ObjectModel
import org.jetbrains.dukat.astModel.ParameterModel
import org.jetbrains.dukat.astModel.TopLevelModel
import org.jetbrains.dukat.astModel.TypeAliasModel
import org.jetbrains.dukat.astModel.TypeModel
import org.jetbrains.dukat.astModel.TypeParameterModel
import org.jetbrains.dukat.astModel.TypeValueModel
import org.jetbrains.dukat.astModel.VariableModel
import org.jetbrains.dukat.astModel.LambdaParameterModel
import org.jetbrains.dukat.ownerContext.NodeOwner
import org.jetbrains.dukat.panic.raiseConcern

interface TopLevelModelLowering : ModelStatementLowering {
override fun lowerVariableModel(ownerContext: NodeOwner<VariableModel>, parentModule: ModuleModel?): VariableModel = ownerContext.node
fun lowerFunctionModel(ownerContext: NodeOwner<FunctionModel>, parentModule: ModuleModel): FunctionModel = ownerContext.node
fun lowerClassModel(ownerContext: NodeOwner<ClassModel>, parentModule: ModuleModel): ClassModel? = ownerContext.node
fun lowerInterfaceModel(ownerContext: NodeOwner<InterfaceModel>, parentModule: ModuleModel): InterfaceModel? = ownerContext.node
fun lowerClassModel(ownerContext: NodeOwner<ClassModel>, parentModule: ModuleModel): ClassModel = ownerContext.node
fun lowerInterfaceModel(ownerContext: NodeOwner<InterfaceModel>, parentModule: ModuleModel): InterfaceModel = ownerContext.node
fun lowerTypeAliasModel(ownerContext: NodeOwner<TypeAliasModel>, parentModule: ModuleModel): TypeAliasModel = ownerContext.node

fun lowerObjectModel(ownerContext: NodeOwner<ObjectModel>, parentModule: ModuleModel): ObjectModel = ownerContext.node
fun lowerEnumModel(ownerContext: NodeOwner<EnumModel>, parentModule: ModuleModel): EnumModel = ownerContext.node


fun lowerClassLikeModel(ownerContext: NodeOwner<ClassLikeModel>, parentModule: ModuleModel): ClassLikeModel? {
fun lowerClassLikeModel(ownerContext: NodeOwner<ClassLikeModel>, parentModule: ModuleModel): ClassLikeModel {
return when (val declaration = ownerContext.node) {
is InterfaceModel -> lowerInterfaceModel(NodeOwner(declaration, ownerContext), parentModule)
is ClassModel -> lowerClassModel(NodeOwner(declaration, ownerContext), parentModule)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import org.jetbrains.dukat.stdlib.KLIBROOT
import org.jetbrains.dukat.stdlib.TSLIBROOT
import org.jetbrains.dukat.stdlibGenerator.generated.stdlibClassMethodsMap

private data class MemberData(val fqName: NameEntity?, val memberModel: MemberModel, val ownerModel: ClassLikeModel)
internal data class MemberData(val fqName: NameEntity?, val memberModel: MemberModel, val ownerModel: ClassLikeModel)

internal enum class MemberOverrideStatus {
IS_OVERRIDE,
Expand All @@ -37,19 +37,28 @@ internal enum class MemberOverrideStatus {
IS_IMPOSSIBLE
}

private fun ModelContext.buildInheritanceGraph(): Graph<ClassLikeModel> {
val graph = Graph<ClassLikeModel>()
internal fun ClassLikeModel.getKnownParents(context: ModelContext): List<ResolvedClassLike<out ClassLikeModel>> {
return context.getAllParents(this)
}

internal fun ClassLikeModel.allParentMembers(context: ModelContext): Map<NameEntity?, List<MemberData>> {
val memberMap = mutableMapOf<NameEntity?, MutableList<MemberData>>()

getClassLikeIterable().forEach { classLike ->
getAllParents(classLike).forEach { resolvedClassLike ->
graph.addEdge(classLike, resolvedClassLike.classLike)
getKnownParents(context).forEach { resolvedClassLike ->
resolvedClassLike.classLike.members.forEach {
when (it) {
is NamedModel -> {
if (!resolvedClassLike.existsOnlyInTsStdlib(it)) {
memberMap.getOrPut(it.name) { mutableListOf() }.add(MemberData(resolvedClassLike.fqName, it, resolvedClassLike.classLike))
}
}
}
}
}

return graph
return memberMap
}


private fun <T : ClassLikeModel> ResolvedClassLike<T>.existsOnlyInTsStdlib(member: NamedModel): Boolean {
return (fqName?.startsWith(TSLIBROOT) == true && (stdlibClassMethodsMap.containsKey(classLike.name)) && (stdlibClassMethodsMap[classLike.name]?.contains(member.name) == false))
}
Expand Down Expand Up @@ -114,10 +123,6 @@ private class ClassLikeOverrideResolver(
)
}

private fun ClassLikeModel.getKnownParents(): List<ResolvedClassLike<out ClassLikeModel>> {
return context.getAllParents(this)
}

private fun MethodModel.removeDefaultParamValues(override: NameEntity?): MethodModel {
return copy(override = override, parameters = parameters.map { it.copy(initializer = null) })
}
Expand Down Expand Up @@ -236,24 +241,6 @@ private class ClassLikeOverrideResolver(
}
}

private fun ClassLikeModel.allParentMembers(): Map<NameEntity?, List<MemberData>> {
val memberMap = mutableMapOf<NameEntity?, MutableList<MemberData>>()

getKnownParents().forEach { resolvedClassLike ->
resolvedClassLike.classLike.members.forEach {
when (it) {
is NamedModel -> {
if (!resolvedClassLike.existsOnlyInTsStdlib(it)) {
memberMap.getOrPut(it.name) { mutableListOf() }.add(MemberData(resolvedClassLike.fqName, it, resolvedClassLike.classLike))
}
}
}
}
}

return memberMap
}

private fun MethodModel.isSpecialCase(): Boolean {
val returnType = type

Expand All @@ -277,7 +264,7 @@ private class ClassLikeOverrideResolver(
}

fun resolve(): ClassLikeModel {
val parentMembers = classLike.allParentMembers()
val parentMembers = classLike.allParentMembers(context)

val membersLowered = classLike.members.flatMap { member ->
member.lowerOverrides(parentMembers)
Expand Down
Loading