1
1
package org.jetbrains.dukat.model.commonLowerings
2
2
3
+ import org.jetbrains.dukat.astCommon.IdentifierEntity
4
+ import org.jetbrains.dukat.astCommon.NameEntity
5
+ import org.jetbrains.dukat.astCommon.rightMost
3
6
import org.jetbrains.dukat.astModel.ClassModel
4
7
import org.jetbrains.dukat.astModel.FunctionModel
5
8
import org.jetbrains.dukat.astModel.InterfaceModel
@@ -33,13 +36,6 @@ private fun MemberModel.normalize(): MemberModel {
33
36
}
34
37
}
35
38
36
- private fun TopLevelModel.normalize (): TopLevelModel {
37
- return when (this ) {
38
- is FunctionModel -> copy(parameters = parameters.map { it.withoutMeta() })
39
- else -> this
40
- }
41
- }
42
-
43
39
private fun filterOutConflictingOverloads (members : List <MemberModel >): List <MemberModel > {
44
40
return members.groupBy { it.normalize() }.map { (_, bucketMembers) ->
45
41
if (bucketMembers.size > 1 ) {
@@ -50,26 +46,71 @@ private fun filterOutConflictingOverloads(members: List<MemberModel>): List<Memb
50
46
}
51
47
}
52
48
53
- private class ConflictingOverloads () : ModelWithOwnerTypeLowering {
49
+ private class ConflictingOverloads : TopLevelModelLowering {
54
50
55
- override fun lowerInterfaceModel (ownerContext : NodeOwner <InterfaceModel >, parentModule : ModuleModel ): InterfaceModel {
51
+ override fun lowerInterfaceModel (ownerContext : NodeOwner <InterfaceModel >, parentModule : ModuleModel ): InterfaceModel ? {
56
52
val node = ownerContext.node.copy(members = filterOutConflictingOverloads(ownerContext.node.members))
57
53
return super .lowerInterfaceModel(ownerContext.copy(node = node), parentModule)
58
54
}
59
55
60
- override fun lowerClassModel (ownerContext : NodeOwner <ClassModel >, parentModule : ModuleModel ): ClassModel {
56
+ override fun lowerClassModel (ownerContext : NodeOwner <ClassModel >, parentModule : ModuleModel ): ClassModel ? {
61
57
val node = ownerContext.node.copy(members = filterOutConflictingOverloads(ownerContext.node.members))
62
58
return super .lowerClassModel(ownerContext.copy(node = node), parentModule)
63
59
}
64
60
}
65
61
62
+ private fun mergeTypeModels (a : TypeModel , b : TypeModel ): TypeModel {
63
+ return if ((a is TypeValueModel ) && (b is TypeValueModel )) {
64
+ a.copy(metaDescription = listOfNotNull(a.metaDescription, b.metaDescription).joinToString(" | " ))
65
+ } else {
66
+ a
67
+ }
68
+ }
69
+
70
+ private fun mergeTypeModelsAsReturn (a : TypeModel , b : TypeModel ): TypeModel {
71
+ return if ((a is TypeValueModel ) && (b is TypeValueModel )) {
72
+ a.copy(metaDescription = listOfNotNull(a.metaDescription, b.metaDescription).joinToString(" | " ))
73
+ if (a.withoutMeta() == b.withoutMeta()) {
74
+ mergeTypeModels(a, b)
75
+ } else {
76
+ TypeValueModel (IdentifierEntity (" dynamic" ), listOf (), listOfNotNull(a.fqName?.rightMost(), b.fqName?.rightMost()).joinToString(" | " ) { it.toString() }, null )
77
+ }
78
+ } else {
79
+ TypeValueModel (IdentifierEntity (" dynamic" ), listOf (), null , null )
80
+ }
81
+ }
82
+
83
+
84
+ private fun mergeFunctionModels (a : FunctionModel , b : FunctionModel ): FunctionModel {
85
+ val paramsMerged = a.parameters.zip(b.parameters).map { (paramA, paramB) ->
86
+ paramA.copy(type = mergeTypeModels(paramA.type, paramB.type))
87
+ }
88
+
89
+ return a.copy(parameters = paramsMerged, type = mergeTypeModelsAsReturn(a.type, b.type))
90
+ }
91
+
92
+ typealias FunctionModelKey = Triple <NameEntity , List <TypeModel >, List <TypeModel >>
93
+
94
+ private fun FunctionModel.getKey (): FunctionModelKey {
95
+ return Triple (name, parameters.map { it.type.withoutMeta() }, typeParameters.map { it.type.withoutMeta() })
96
+ }
97
+
66
98
class RemoveConflictingOverloads : ModelLowering {
67
99
override fun lower (module : ModuleModel ): ModuleModel {
68
- val declarationsResolved = module.declarations.groupBy { it.normalize() }.map { (_, bucketMembers) ->
69
- if (bucketMembers.size > 1 ) {
70
- bucketMembers.first().normalize()
71
- } else {
72
- bucketMembers.first()
100
+ val keyCache = mutableMapOf<FunctionModel , FunctionModelKey >()
101
+
102
+ val functionsBucket = module.declarations.filterIsInstance(FunctionModel ::class .java).groupBy { functionModel ->
103
+ val key = functionModel.getKey()
104
+ keyCache.put(functionModel, key)
105
+ key
106
+ }.toMutableMap()
107
+
108
+ val declarationsResolved = module.declarations.mapNotNull { topLevelModel ->
109
+ when (topLevelModel) {
110
+ is FunctionModel -> {
111
+ functionsBucket.remove(keyCache[topLevelModel])?.reduce { a, b -> mergeFunctionModels(a, b) }
112
+ }
113
+ else -> topLevelModel
73
114
}
74
115
}
75
116
0 commit comments