Skip to content

Commit 79afbb2

Browse files
committed
扩展代码生成模块,添加对 Java 语言及多种框架的支持,引入多个生成器(JavaTemplates、MainClassGenerator 和 EventHandlerGenerator),并重构 UI 以支持语言和样式选择功能。修复下载逻辑中的错误处理,优化生成体验。
1 parent 5fdfecb commit 79afbb2

File tree

16 files changed

+1244
-266
lines changed

16 files changed

+1244
-266
lines changed

composeApp/build.gradle.kts

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@ repositories {
1616
}
1717
google()
1818
mavenCentral()
19-
// maven {
20-
// // https://ktor.io/eap/
21-
// url = uri("https://maven.pkg.jetbrains.space/public/p/ktor/eap")
22-
// }
2319
maven {
2420
url = rootDir.resolve("libs").toURI()
2521
mavenContent {
@@ -71,6 +67,7 @@ kotlin {
7167
// implementation(libs.androidx.lifecycle)
7268
implementation(libs.kotlinpoet)
7369
implementation(libs.codegentle.kotlin)
70+
implementation(libs.codegentle.java)
7471
implementation(libs.kotlin.coroutine)
7572

7673
implementation(libs.kotlin.serialization.core)
@@ -82,27 +79,10 @@ kotlin {
8279
}
8380

8481
wasmJsMain.dependencies {
85-
// implementation(project(":common"))
86-
// implementation(project(":jszip-kotlin"))
8782
implementation(kotlinWrappers.jszip)
8883
implementation(project(":file-saver-kotlin"))
89-
// implementation("io.ktor:ktor-client-core:3.0.0-beta-2")
90-
// implementation("io.ktor:ktor-client-js:3.0.0-beta-2")
91-
92-
// implementation(npm(File(projectDir, "simbot-codegen-code-generator")))
93-
94-
// val dir = rootProject.project("code-generator").projectDir
95-
// .resolve("build/dist/js/productionLibrary")
96-
97-
// val dir = File(
98-
// rootProject.project(":code-generator").projectDir,
99-
// "build/dist/js/productionLibrary"
100-
// )
101-
102-
// implementation(project(":code-generator"))
103-
// implementation(npm(dir))
10484
}
105-
85+
10686
wasmJsTest.dependencies {
10787
implementation(libs.kotlin.test)
10888
}

composeApp/src/wasmJsMain/kotlin/love/forte/simbot/codegen/codegen/naming/SpringNames.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,13 @@ object SpringNames {
3333
val requestParamAno = ClassName(springBindPkg, "RequestParam")
3434

3535
// Spring Boot annotations
36+
private val subPackageAutoconfigureCondition = "autoconfigure.condition".parseToPackageName()
37+
private val springBootAutoconfigureCondition = springBootPkg + subPackageAutoconfigureCondition
38+
3639
val springBootApplicationAno = ClassName(springBootPkg, "SpringBootApplication")
3740
val enableAutoConfigurationAno = ClassName(springBootPkg, "EnableAutoConfiguration")
38-
val conditionalOnMissingBeanAno = ClassName(springBootPkg + "autoconfigure.condition", "ConditionalOnMissingBean")
39-
val conditionalOnBeanAno = ClassName(springBootPkg + "autoconfigure.condition", "ConditionalOnBean")
40-
val conditionalOnPropertyAno = ClassName(springBootPkg + "autoconfigure.condition", "ConditionalOnProperty")
41-
val conditionalOnClassAno = ClassName(springBootPkg + "autoconfigure.condition", "ConditionalOnClass")
41+
val conditionalOnMissingBeanAno = ClassName(springBootAutoconfigureCondition, "ConditionalOnMissingBean")
42+
val conditionalOnBeanAno = ClassName(springBootAutoconfigureCondition, "ConditionalOnBean")
43+
val conditionalOnPropertyAno = ClassName(springBootAutoconfigureCondition, "ConditionalOnProperty")
44+
val conditionalOnClassAno = ClassName(springBootAutoconfigureCondition, "ConditionalOnClass")
4245
}

composeApp/src/wasmJsMain/kotlin/love/forte/simbot/codegen/gen/GradleProject.kt

Lines changed: 54 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import androidx.compose.runtime.setValue
77
import androidx.lifecycle.ViewModel
88
import js.date.Date
99
import jszip.JSZip
10-
import love.forte.codegentle.common.code.CodePart
11-
import love.forte.codegentle.common.naming.PackageName
12-
import love.forte.codegentle.common.writer.InternalWriterApi
10+
import love.forte.codegentle.common.code.*
1311
import love.forte.codegentle.kotlin.KotlinFile
1412
import love.forte.codegentle.kotlin.writeToKotlinString
1513
import love.forte.simbot.codegen.gen.SimbotComponent.*
14+
import love.forte.simbot.codegen.gen.core.JavaStyle
15+
import love.forte.simbot.codegen.gen.core.ProgrammingLanguage
1616
import org.jetbrains.compose.resources.ExperimentalResourceApi
1717
import simbot_codegen.composeapp.generated.resources.Res
1818

@@ -52,6 +52,12 @@ class GradleProjectViewModel : ViewModel() {
5252

5353
var simbotVersion: String? by mutableStateOf(null)
5454
var kotlinVersion: String by mutableStateOf("2.1.20") // TODO initial able?
55+
56+
// 编程语言选择
57+
var programmingLanguage: ProgrammingLanguage by mutableStateOf(ProgrammingLanguage.Kotlin("2.1.20"))
58+
59+
// Java 样式选择(仅在选择 Java 语言时有效)
60+
var javaStyle: JavaStyle by mutableStateOf(JavaStyle.BLOCKING)
5561

5662
// TODO generate
5763
// var withSpring: Boolean by mutableStateOf(false)
@@ -118,50 +124,65 @@ fun genGradleBuildScript(
118124
plugins: Iterable<GradleCatalogPlugin>,
119125
dependencies: Iterable<GradleCatalogVersionDependency>,
120126
): String {
121-
// TODO
122-
KotlinFile {
123-
// TODO
124-
}
125-
126-
127-
return fileScriptSpec("build.gradle") {
128-
inControlFlow("plugins") {
129-
plugins.forEach { plugin ->
130-
addStatement("alias(libs.plugins.%L)", plugin.libRefPath)
127+
return KotlinFile {
128+
addCode {
129+
inControlFlow("plugins") {
130+
plugins.forEach { plugin ->
131+
addStatement("alias(libs.plugins.%V)") {
132+
emitLiteral(plugin.libRefPath)
133+
}
134+
}
131135
}
132136
}
133137

134-
addStatement("group = %S", pkg)
135-
addStatement("version = %S", "1.0-SNAPSHOT")
138+
addStatement("group = %V") { emitString(pkg) }
139+
addStatement("version = %V") { emitString("0.0.1-SNAPSHOT") }
136140
addStatement("")
137141

138-
inControlFlow("java") {
139-
addStatement("sourceCompatibility = JavaVersion.VERSION_21")
142+
// Java config
143+
addCode {
144+
inControlFlow("java") {
145+
inControlFlow("toolchain") {
146+
addStatement("languageVersion = JavaLanguageVersion.of(21)")
147+
}
148+
}
140149
}
141150

142151
// repositories
143-
inControlFlow("repositories") {
144-
addStatement("mavenCentral()")
152+
addCode {
153+
inControlFlow("repositories") {
154+
addStatement("mavenCentral()")
155+
}
145156
}
146157

147158
// dependencies
148-
inControlFlow("dependencies") {
149-
dependencies.forEach { dependency ->
150-
addStatement("%L(libs.%L)", dependency.configName, dependency.libRefPath)
159+
addCode {
160+
inControlFlow("dependencies") {
161+
dependencies.forEach { dependency ->
162+
addStatement("%V(libs.%V)") {
163+
emitLiteral(dependency.configName)
164+
emitLiteral(dependency.libRefPath)
165+
}
166+
}
151167
}
152168
}
153169

154-
inControlFlow("kotlin") {
155-
inControlFlow("compilerOptions") {
156-
addStatement("freeCompilerArgs.addAll(%S)", "-Xjsr305=strict")
170+
addCode {
171+
inControlFlow("kotlin") {
172+
inControlFlow("compilerOptions") {
173+
addStatement("freeCompilerArgs.addAll(%V)") {
174+
emitString("-Xjsr305=strict")
175+
}
176+
}
157177
}
158178
}
159179

160-
inControlFlow("tasks.withType<Test>") {
161-
addStatement("useJUnitPlatform()")
180+
addCode {
181+
inControlFlow("tasks.withType<Test>") {
182+
addStatement("useJUnitPlatform()")
183+
}
162184
}
163-
164-
}.toString()
185+
}.writeToKotlinString()
165186
}
166187

167188
fun genGradleSettingsScript(
@@ -179,7 +200,10 @@ fun genREADME(
179200
): String {
180201
return buildString {
181202
appendLine("# $name")
182-
appendLine("这是一个 [Simple Robot](https://github.com/simple-robot) 项目, 通过 [Simbot Codegen](https://codegen.simbot.forte.love/) 构建生成。")
203+
appendLine(
204+
"这是一个 [Simple Robot](https://github.com/simple-robot) 项目, " +
205+
"通过 [Simbot Codegen](https://codegen.simbot.forte.love/) 构建生成。"
206+
)
183207
appendLine()
184208
// 组件说明
185209
appendLine("## 组件")

composeApp/src/wasmJsMain/kotlin/love/forte/simbot/codegen/gen/Showcases.kt

Lines changed: 8 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ fun emitSpringShowcases(
5858
resources.file("application.yml", genSpringApplicationConfig())
5959
}
6060

61-
fun genSpringMainFile(
61+
fun genKotlinSpringMainFile(
6262
name: String,
6363
projectPackage: String
6464
): KotlinFile {
@@ -82,43 +82,24 @@ fun genSpringMainFile(
8282
}
8383
}
8484

85-
// val mainFile = fileSpec(projectPackage, name) {
86-
// // Main Application class
87-
// addClass(name) {
88-
// val simbotAno = ClassName("love.forte.simbot.spring", "EnableSimbot")
89-
// addAnnotation(simbotAno)
90-
// addAnnotation(ClassName("org.springframework.boot.autoconfigure", "SpringBootApplication"))
91-
// addKdoc("Spring程序的入口注解类。添加 [%T] 注解来标记启用 simbot 相关的功能。", simbotAno)
92-
// }
93-
//
94-
// // Main function
95-
// addFunction("main") {
96-
// addParameter("args", ARRAY.parameterizedBy(STRING))
97-
// val ram = MemberName("org.springframework.boot", "runApplication")
98-
// addStatement("%M<%L>(*args)", ram, name)
99-
// }
100-
//
101-
// }
102-
10385
return mainFile
10486
}
10587

10688
fun emitSpringMainFile(
10789
projectPackage: String,
10890
sourceSets: JSZip
10991
) {
110-
val file = genSpringMainFile(projectPackage, "MainApplication")
92+
val file = genKotlinSpringMainFile("MainApplication", projectPackage)
11193
sourceSets.file(file.toRelativePath(), file.writeToKotlinString())
11294
}
11395

114-
fun genSpringListenerShowcases(
96+
fun genKotlinSpringListenerShowcases(
11597
projectPackage: String,
11698
components: Collection<SimbotComponent>
11799
): KotlinFile {
118100
var showcaseCount = 1
119101
val handlePackage = "$projectPackage.handle"
120102

121-
// TODO
122103
val myHandleFile = KotlinFile(handlePackage) {
123104
// Text + Message
124105
addStaticImport("love.forte.simbot.message.plus")
@@ -186,10 +167,10 @@ fun genSpringListenerShowcases(
186167

187168
addParameter("event", SimbotNames.contactMsgEventClassName)
188169
addComment("基于事件回复一句\"你好\"")
189-
addStatement("event.reply(%S)", CodePart.string("你好"))
170+
addStatement("event.reply(%V)", CodePart.string("你好"))
190171
addStatement("")
191172
addComment("或直接根据 content 发送一句\"你又好\"")
192-
addStatement("event.content().send(%S)", CodePart.string("你又好"))
173+
addStatement("event.content().send(%V)", CodePart.string("你又好"))
193174
addStatement("")
194175
addComment("可以发送文本(字符串)、消息元素/消息链和事件中的消息正文。")
195176
addStatement("")
@@ -200,8 +181,8 @@ fun genSpringListenerShowcases(
200181
addComment("更多有关消息链和可用的消息元素,请参考文档:")
201182
addComment("https://simbot.forte.love/basic-messages.html")
202183
addStatement(
203-
"val messages = %M { %S } + " +
204-
"%M(%S).%M()"
184+
"val messages = %V { %V } + " +
185+
"%V(%V).%V()"
205186
) {
206187
emitType(MemberName("love.forte.simbot.message", "Text"))
207188
emitString("图片: ")
@@ -214,95 +195,6 @@ fun genSpringListenerShowcases(
214195
}
215196
}
216197

217-
// val myHandleFile = fileSpec(handlePackage, "MyEventHandles") {
218-
// addClass("MyEventHandles") {
219-
// // addAnnotation(componentAno)
220-
// // addKdoc("一个用于承载监听函数的事件处理器类。\n\n")
221-
// // addKdoc("将它标记为 [%T] 以交由Spring进行管理,\n", componentAno)
222-
// // addKdoc("simbot-spring 会解析其中标记了 [%T] 的函数们。", listenerAno)
223-
// //
224-
// // // 1, 监听所有事件,然后控制台输出
225-
// // addFunction("handleAllAndPrint") {
226-
// // addAnnotation(listenerAno)
227-
// // addModifiers(KModifier.SUSPEND)
228-
// // addKdoc("示例${showcaseCount++}: 监听所有的事件,然后将它们输出到控制台。\n\n")
229-
// // addKdoc("@param event 你要监听的事件的类型。\n")
230-
// // addKdoc("必须是一个 [%T] 类型的子类", eventClassName)
231-
// //
232-
// // addParameter("event", eventClassName)
233-
// // addStatement("println(%P)", "收到事件: \$event")
234-
// // }
235-
// //
236-
// // // 2, 过滤消息事件
237-
// // addFunction("handleMessageEvent") {
238-
// // addAnnotation(listenerAno)
239-
// // addAnnotation(AnnotationSpec.builder(filterAno).apply {
240-
// // addMember("%S", "你好.*")
241-
// // }.build())
242-
// // addAnnotation(contentTrimAno)
243-
// // addModifiers(KModifier.SUSPEND)
244-
// // addKdoc("示例${showcaseCount++}: 监听所有 **文本内容** 开头为 `\"你好\"` 的消息事件,\n")
245-
// // addKdoc("然后在控制台输出它的消息链内容。\n\n")
246-
// // addKdoc("这里通过 [%T] 来以注解的风格便捷的匹配消息内容并过滤, \n", filterAno)
247-
// // addKdoc("并配合使用 [%T] 在匹配前优先处理掉匹配文本的前后空字符,避免匹配失效。\n", contentTrimAno)
248-
// //
249-
// // addParameter("event", msgEventClassName)
250-
// // addStatement("println(%P)", "收到消息事件: \$event")
251-
// // addStatement("")
252-
// //
253-
// // addCode(CodeBlock.builder().apply {
254-
// // inControlFlow("for·((index,·element)·in·event.messageContent.messages.withIndex())") {
255-
// // addStatement("println(%P)", "\\t消息元素[\$index]: \$element")
256-
// // }
257-
// // }.build())
258-
// // }
259-
// //
260-
// // // 3, 组件专属
261-
// // // 挑其中一个组件
262-
// // val oneOfComponent = components.firstOrNull()
263-
// // if (oneOfComponent != null) {
264-
// // addFunction(componentShowcase(showcaseCount++, oneOfComponent))
265-
// // }
266-
//
267-
// // 4, 回复消息
268-
// addFunction("handleAndReply") {
269-
// addAnnotation(listenerAno)
270-
// addModifiers(KModifier.SUSPEND)
271-
//
272-
// addKdoc("示例${showcaseCount++}: 监听所有 **文本内容** 开头为 `\"你好\"` 的消息事件,\n")
273-
//
274-
// addParameter("event", contactMsgEventClassName)
275-
// addComment("基于事件回复一句\"你好\"")
276-
// addStatement("event.reply(%S)", "你好")
277-
// addStatement("")
278-
// addComment("或直接根据 content 发送一句\"你好\"")
279-
// addStatement("event.content().send(%S)", "你好")
280-
// addStatement("")
281-
// addComment("可以发送文本(字符串)、消息元素/消息链和事件中的消息正文。")
282-
// addStatement("")
283-
//
284-
// addComment("下面的示例是发送一个消息链,其中包括一个文字消息和一个图片, ")
285-
// addComment("它们二者直接使用 + 拼接。")
286-
// addComment("你也可以使用 buildMessages { ... } 来构建消息链。")
287-
// addComment("更多有关消息链和可用的消息元素,请参考文档:")
288-
// addComment("https://simbot.forte.love/basic-messages.html")
289-
// addStatement(
290-
// "val messages = %M { %S } + " +
291-
// "%M(%S).%M()",
292-
// MemberName("love.forte.simbot.message", "Text"),
293-
// "图片: ",
294-
// MemberName("kotlin.io.path", "Path"),
295-
// "image.png",
296-
// MemberName("love.forte.simbot.message.OfflinePathImage.Companion", "toOfflineImage")
297-
// )
298-
// addStatement("event.reply(messages)")
299-
// }
300-
//
301-
// // Text + Image 消息拼接的操作符
302-
// addImport("love.forte.simbot.message", "plus")
303-
// }
304-
// }
305-
306198
return myHandleFile
307199
}
308200

@@ -364,7 +256,7 @@ fun emitSpringListenerShowcases(
364256
components: Collection<SimbotComponent>,
365257
sourceSets: JSZip
366258
) {
367-
val file = genSpringListenerShowcases(projectPackage, components)
259+
val file = genKotlinSpringListenerShowcases(projectPackage, components)
368260
sourceSets.file(file.toRelativePath(), file.writeToKotlinString())
369261
}
370262

composeApp/src/wasmJsMain/kotlin/love/forte/simbot/codegen/gen/bridge/ViewModelBridge.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class ViewModelBridge(
3737
val context = createGenerationContext {
3838
projectName = viewModel.projectName
3939
packageName = viewModel.projectPackage
40-
language = ProgrammingLanguage.Kotlin(viewModel.kotlinVersion)
40+
language = viewModel.programmingLanguage
4141
framework = if (viewModel.withSpring) {
4242
Framework.Spring("3.3.3") // 使用默认版本,后续可以从视图模型中获取
4343
} else {

0 commit comments

Comments
 (0)