summaryrefslogtreecommitdiff
path: root/src/main/kotlin/DefMain.kt
blob: 843b2a2c8939996bc4865a0917d59977046df038 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.*
import java.io.File
import java.io.PrintWriter

@Serializable
data class LModule(
    val Name: String? = null,
    val Namespace: String? = null,
    val Functions: List<LFunction> = listOf(),
    val Tables: List<LTable> = listOf(),
    val Type: String = "System"
)

@Serializable
data class LTypeUse(
    val Type: String,
    val InnerType: String? = null,
    val Name: String,
    val Nilable: Boolean,
)

@Serializable
data class LEnumValue(
    val Type: String,
    val Name: String,
    val EnumValue: Long,
)

@Serializable
data class LFunction(
    val Returns: List<LTypeUse> = listOf(),
    val Name: String,
    val Arguments: List<LTypeUse> = listOf(),
)


@Serializable(with = LTable.Serializer::class)
sealed class LTable {
    object Serializer : JsonContentPolymorphicSerializer<LTable>(LTable::class) {
        override fun selectDeserializer(element: JsonElement): DeserializationStrategy<LTable> {
            element as JsonObject
            return when ((element["Type"] as JsonPrimitive).content) {
                "Structure" -> LStructure.serializer()
                "Enumeration" -> LEnumeration.serializer()
                else -> {
                    println("Unknown type " + element["Type"])
                    LUnknownObject.serializer()
                }
            }
        }
    }
}

@Serializable
data class LStructure(
    val Name: String,
    val Fields: List<LTypeUse>,
) : LTable()

@Serializable
data object LUnknownObject : LTable()

@Serializable
data class LEnumeration(
    val Name: String,
    val MinValue: Long,
    val NumValues: Long,
    val MaxValue: Long,
    val Fields: List<LEnumValue>,
) : LTable()

fun String?.postFixedWithOrEmpty(text: String): String {
    return if (this.isNullOrBlank()) ""
    else this + text
}

fun compositeTypeStr(module: LModule, field: LTypeUse): String {
    return if (field.InnerType == null) field.Type else module.Namespace.postFixedWithOrEmpty(
        "."
    ) + field.InnerType + "[]"
}

fun main() {
    val json1 = Json { ignoreUnknownKeys = true }
    val luaMeta = PrintWriter(File("definitions.lua"))
    luaMeta.println("---@meta")
    luaMeta.println()

    luaMeta.println("---@alias bool boolean")
    luaMeta.println("---@alias BigInteger number")
    luaMeta.println("---@alias BigUInteger number")
    luaMeta.println("---@alias cstring string")
    luaMeta.println("---@alias CalendarEventID string")
    luaMeta.println("---@alias ClubId string")
    luaMeta.println("---@alias ClubInvitationId string")
    luaMeta.println("---@alias ClubStreamId string")
    luaMeta.println("---@alias FileAsset string")
    luaMeta.println("---@alias fileID number")
    luaMeta.println("---@alias GarrisonFollower string")
    luaMeta.println("---@alias IDOrLink string|number")
    luaMeta.println("---@alias kstringClubMessage string")
    luaMeta.println("---@alias kstringLfgListApplicant string")
    luaMeta.println("---@alias kstringLfgListSearch string")
    luaMeta.println("---@alias luaIndex number")
    luaMeta.println("---@alias ModelAsset string")
    luaMeta.println("---@alias normalizedValue string")
    luaMeta.println("---@alias RecruitAcceptanceID string")
    luaMeta.println("---@alias ScriptRegion SimpleScriptRegion")
    luaMeta.println("---@alias SimpleButtonStateToken string")
    luaMeta.println("---@alias SingleColorValue number")
    luaMeta.println("---@alias size number")
    luaMeta.println("---@alias TBFFlags string")
    luaMeta.println("---@alias TBFStyleFlags string")
    luaMeta.println("---@alias textureAtlas string")
    luaMeta.println("---@alias textureKit string")
    luaMeta.println("---@alias time_t number")
    luaMeta.println("---@alias uiAddon string")
    luaMeta.println("---@alias uiFontHeight number")
    luaMeta.println("---@alias uiMapID number")
    luaMeta.println("---@alias uiUnit number")
    luaMeta.println("---@alias UnitToken string")
    luaMeta.println("---@alias WeeklyRewardItemDBID string")
    luaMeta.println("---@alias WOWGUID string")
    luaMeta.println("---@alias WOWMONEY string")

    for (module in json1.decodeFromString<List<LModule>>(File("generated.json").readText())) {
        luaMeta.println()
        if (module.Type == "ScriptObject") {
            val interfaceName = module.Name!!.removeSuffix("API")
            luaMeta.println("---@class $interfaceName")
            luaMeta.println("$interfaceName = {}")
            luaMeta.println()
            for (function in module.Functions) {
                luaMeta.println("---@param self $interfaceName")
                for (par in function.Arguments) {
                    luaMeta.println("---@param ${par.Name}${if (par.Nilable) "?" else ""} ${compositeTypeStr(module, par)}")
                    require(par.Name != "self")
                }
                for (ret in function.Returns) {
                    luaMeta.println(
                        "---@return ${
                            compositeTypeStr(
                                module,
                                ret
                            )
                        }${if (ret.Nilable) "|nil" else ""} ${ret.Name}"
                    )
                }
                luaMeta.println("function $interfaceName.${function.Name}(${(listOf("self") + function.Arguments.map { it.Name }).joinToString()}) end")
                luaMeta.println()
            }
            continue
        }
        if (module.Namespace != null) {
            luaMeta.println("${module.Namespace} = {}")
            luaMeta.println()
        }
        for (table in module.Tables) {
            when (table) {
                is LEnumeration -> {
                    luaMeta.println("---@enum ${table.Name}")
                    luaMeta.println("${table.Name} = {")
                    for (field in table.Fields) {
                        luaMeta.println("    ${field.Name} = ${field.EnumValue};")
                    }
                    luaMeta.println("}")
                    luaMeta.println()
                }

                is LStructure -> {
                    luaMeta.println("---@class ${module.Namespace.postFixedWithOrEmpty(".")}${table.Name}")
                    for (field in table.Fields) {
                        luaMeta.println(
                            "---@field ${field.Name} ${
                                compositeTypeStr(
                                    module,
                                    field
                                )
                            }${if (field.Nilable) "|nil" else ""}"
                        )
                    }
                    luaMeta.println()
                }

                LUnknownObject -> {
                }
            }
        }
        for (func in module.Functions) {
            for (ret in func.Returns) {
                luaMeta.println(
                    "---@return ${
                        compositeTypeStr(
                            module,
                            ret
                        )
                    }${if (ret.Nilable) "|nil" else ""} ${ret.Name}"
                )
            }
            for (par in func.Arguments) {
                luaMeta.println("---@param ${par.Name}${if (par.Nilable) "?" else ""} ${compositeTypeStr(module, par)}")
            }
            luaMeta.println("function ${module.Namespace.postFixedWithOrEmpty(".")}${func.Name}(${func.Arguments.joinToString { it.Name }}) end")
            luaMeta.println()
        }
    }
    luaMeta.close()
}