Skip to content

Commit 9546855

Browse files
committed
Add support for nested classes and enums
1 parent d96272a commit 9546855

File tree

5 files changed

+71
-37
lines changed

5 files changed

+71
-37
lines changed

src/main/kotlin/Main.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ fun main(args: Array<String>) {
3636

3737
parsedClasses.forEach { parsedClass ->
3838
val luaOutput = luaEmitter.emit(parsedClass)
39-
val outputFile = File(outputDir, "${parsedClass.packageName}.${parsedClass.name}.lua")
39+
val outputFile = File(outputDir, "${parsedClass.fqcn}.lua")
4040
outputFile.writeText(luaOutput)
4141
println("Generated Lua stubs for ${parsedClass.name} in ${outputFile.absolutePath}")
4242
}

src/main/kotlin/generator/LuaEmitter.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ class LuaEmitter {
88
fun emit(parsedClass: ParsedClass): String {
99
val sb = StringBuilder()
1010
sb.appendLine("---@meta")
11-
sb.appendLine("-- ${parsedClass.packageName}.${parsedClass.name}")
11+
sb.appendLine("-- ${parsedClass.fqcn}")
1212
sb.appendLine(
13-
"---@class ${parsedClass.packageName}.${parsedClass.name}${
13+
"---@class ${parsedClass.fqcn}${
1414
if (parsedClass.extendedTypes.isNotEmpty() || parsedClass.implementedTypes.isNotEmpty())
1515
": " + (parsedClass.extendedTypes + parsedClass.implementedTypes).joinToString(", ")
1616
else ""

src/main/kotlin/parser/JavaSourceParser.kt

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -91,48 +91,80 @@ class JavaSourceParser(private val jarFiles: List<File>) : ClassParser {
9191

9292
// Handle enum
9393
cu.findFirst(EnumDeclaration::class.java).ifPresent { enumDecl ->
94-
parsedClass = ParsedClass(
95-
name = enumDecl.nameAsString,
96-
packageName = pkgName,
97-
fields = enumDecl.entries.map {
98-
ParsedField(
99-
name = it.nameAsString,
100-
type = enumDecl.fullyQualifiedName.get(),
101-
visibility = Visibility.PUBLIC,
102-
comment = extractMainComment(it.javadoc.getOrNull())
103-
)
104-
},
105-
methods = emptyList(),
106-
classComment = extractMainComment(enumDecl.javadoc.getOrNull()),
107-
isEnum = true
108-
)
109-
parsedClasses[enumDecl.fullyQualifiedName.toString()] = parsedClass!!
94+
parsedClass = parseEnum(enumDecl, pkgName)
95+
parsedClasses[enumDecl.fullyQualifiedName.get()] = parsedClass!!
11096
}
11197

11298
// Handle class or interface
11399
cu.findFirst(ClassOrInterfaceDeclaration::class.java).ifPresent { cls ->
114-
val methods = cls.methods.map { parseMethod(it, cls.nameAsString) }
115-
val fields = cls.fields.flatMap { parseField(it) }
116-
117-
// Gather all constructors and parse them
118-
119-
parsedClass = ParsedClass(
120-
name = cls.nameAsString,
121-
packageName = pkgName,
122-
fields = fields,
123-
methods = methods, // Combine methods
124-
classComment = extractMainComment(cls.javadoc.getOrNull()),
125-
extendedTypes = cls.extendedTypes.map { getFullyQualifiedName(it) },
126-
implementedTypes = cls.implementedTypes.map { getFullyQualifiedName(it) },
127-
constructors = cls.constructors.map { parseConstructor(it, cls.fullyQualifiedName.get()) },
128-
isEnum = false
129-
)
130-
parsedClasses[cls.fullyQualifiedName.toString()] = parsedClass!!
100+
parsedClass = parseClassOrInterface(cls, pkgName)
101+
parsedClasses[cls.fullyQualifiedName.get()] = parsedClass!!
131102
}
132103

133104
return parsedClass
134105
}
135106

107+
private fun parseEnum(enumDecl: EnumDeclaration, pkgName: String): ParsedClass {
108+
return ParsedClass(
109+
name = enumDecl.nameAsString,
110+
packageName = pkgName,
111+
fqcn = enumDecl.fullyQualifiedName.get(),
112+
fields = enumDecl.entries.map {
113+
ParsedField(
114+
name = it.nameAsString,
115+
type = enumDecl.fullyQualifiedName.get(),
116+
visibility = Visibility.PUBLIC,
117+
comment = extractMainComment(it.javadoc.getOrNull())
118+
)
119+
},
120+
methods = emptyList(),
121+
classComment = extractMainComment(enumDecl.javadoc.getOrNull()),
122+
isEnum = true
123+
)
124+
}
125+
126+
private fun parseClassOrInterface(cls: ClassOrInterfaceDeclaration, pkgName: String): ParsedClass {
127+
val methods = cls.methods.map { parseMethod(it, cls.nameAsString) }
128+
val fields = cls.fields.flatMap { parseField(it) }
129+
130+
// Parse nested classes and enums, add as fields and also parse them recursively
131+
val nestedClassFields = cls.members.filterIsInstance<ClassOrInterfaceDeclaration>().map { nested ->
132+
val nestedParsed = parseClassOrInterface(nested, pkgName)
133+
parsedClasses[nested.fullyQualifiedName.get()] = nestedParsed
134+
ParsedField(
135+
name = nested.nameAsString,
136+
type = nested.fullyQualifiedName.orElse(nested.nameAsString),
137+
visibility = Visibility.fromString(nested.accessSpecifier.toString().uppercase()),
138+
comment = extractMainComment(nested.javadoc.getOrNull()),
139+
isNestedClass = true
140+
)
141+
}
142+
val nestedEnumFields = cls.members.filterIsInstance<EnumDeclaration>().map { nestedEnum ->
143+
val nestedParsed = parseEnum(nestedEnum, pkgName)
144+
parsedClasses[nestedEnum.fullyQualifiedName.get()] = nestedParsed
145+
ParsedField(
146+
name = nestedEnum.nameAsString,
147+
type = nestedEnum.fullyQualifiedName.orElse(nestedEnum.nameAsString),
148+
visibility = Visibility.PUBLIC,
149+
comment = extractMainComment(nestedEnum.javadoc.getOrNull()),
150+
isNestedClass = true
151+
)
152+
}
153+
154+
return ParsedClass(
155+
name = cls.nameAsString,
156+
packageName = pkgName,
157+
fqcn = cls.fullyQualifiedName.get(),
158+
fields = fields + nestedClassFields + nestedEnumFields,
159+
methods = methods,
160+
classComment = extractMainComment(cls.javadoc.getOrNull()),
161+
extendedTypes = cls.extendedTypes.map { getFullyQualifiedName(it) },
162+
implementedTypes = cls.implementedTypes.map { getFullyQualifiedName(it) },
163+
constructors = cls.constructors.map { parseConstructor(it, cls.fullyQualifiedName.get()) },
164+
isEnum = false
165+
)
166+
}
167+
136168
private fun parseConstructor(constructor: ConstructorDeclaration, className: String): ParsedMethod {
137169
return ParsedMethod(
138170
name = constructor.nameAsString,

src/main/kotlin/parser/ParsedClass.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package parser
33
data class ParsedClass(
44
val name: String,
55
val packageName: String,
6+
val fqcn: String,
67
val methods: List<ParsedMethod>,
78
val fields: List<ParsedField>,
89
val classComment: String?,

src/main/kotlin/parser/ParsedField.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ data class ParsedField(
44
val name: String,
55
val type: String,
66
val visibility: Visibility,
7-
val comment: String?
7+
val comment: String?,
8+
val isNestedClass: Boolean = false
89
)

0 commit comments

Comments
 (0)