CodeValue 是代码片段的抽象表示,由一系列 CodePart 组成。它提供了类型安全的代码构建方式,使用 %V 作为占位符来插入各种代码元素。
interface CodeValue {
val parts: List<CodePart>
}CodeValue 使用 %V 作为统一占位符标记,用于标识需要插入参数的位置。
CodeValue("val x = %V") // %V 将被替换为提供的参数fun CodeValue(): CodeValue创建一个空的 CodeValue 实例:
val empty = CodeValue()
// empty.parts.isEmpty() == truefun CodeValue(parts: List<CodePart>): CodeValue
fun CodeValue(part: CodePart): CodeValue示例:
val parts = listOf(
CodePart.simple("val x = "),
CodePart.literal(42)
)
val code = CodeValue(parts)fun CodeValue(format: String, block: CodeValueSingleFormatBuilderDsl = {}): CodeValue使用格式化字符串和 DSL 块:
// 无参数
val simple = CodeValue("val x = 10")
// 单个参数
val withArg = CodeValue("val name = %V") {
addValue(CodePart.string("codegentle"))
}
// 多个参数
val multiple = CodeValue("fun %V(): %V = %V") {
addValue(CodePart.name("getName"))
addValue(CodePart.type(stringType))
addValue(CodePart.string("default"))
}fun CodeValue(format: String, vararg argumentParts: CodeArgumentPart): CodeValue
fun CodeValue(format: String, argumentParts: Iterable<CodeArgumentPart>): CodeValue直接传递参数:
val code = CodeValue(
"fun %V(): %V",
CodePart.name("test"),
CodePart.type(intType)
)fun CodeValue(block: CodeValueBuilderDsl): CodeValue使用 Builder 构建复杂代码:
val code = CodeValue {
addStatement("val x = %V", CodePart.literal(10))
addStatement("val y = %V", CodePart.literal(20))
inControlFlow("if (x > y)") {
addStatement("println(%V)", CodePart.string("x is greater"))
}
}CodeValueBuilder 是构建复杂 CodeValue 的主要工具。
添加代码片段:
// 添加其他 CodeValue
fun addCode(codeValue: CodeValue): CodeValueBuilder
// 添加简单字符串
fun addCode(format: String): CodeValueBuilder
// 添加格式化代码
fun addCode(format: String, vararg argumentParts: CodeArgumentPart): CodeValueBuilder
// 使用 DSL 添加格式化代码
fun addCode(format: String, block: CodeValueSingleFormatBuilder.() -> Unit): CodeValueBuilder示例:
CodeValue {
addCode("val x = ")
addCode("%V", CodePart.literal(42))
addCode("\n")
}添加语句(自动处理语句边界):
fun addStatement(format: String, vararg argumentParts: CodeArgumentPart): CodeValueBuilder
fun addStatement(codeValue: CodeValue): CodeValueBuilder
fun addStatement(format: String, block: CodeValueSingleFormatBuilderDsl = {}): CodeValueBuilder示例:
CodeValue {
addStatement("val name = %V", CodePart.string("test"))
addStatement("val count = %V", CodePart.literal(0))
}
// 输出(Java):
// val name = "test";
// val count = 0;fun indent(): CodeValueBuilder
fun unindent(): CodeValueBuilder示例:
CodeValue {
addCode("class Example {\n")
indent()
addStatement("val x = 1")
addStatement("val y = 2")
unindent()
addCode("}\n")
}fun clear(): CodeValueBuilder清空 Builder 中的所有内容,允许重用:
val builder = CodeValue.builder()
builder.addCode("first")
builder.clear()
builder.addCode("second")
val code = builder.build() // 只包含 "second"fun build(): CodeValue从 Builder 创建最终的 CodeValue:
val code = CodeValue.builder()
.addStatement("println(%V)", CodePart.string("Hello"))
.build()专门用于单一格式字符串的 Builder。
添加单个参数:
fun addValue(argument: CodeArgumentPart): CodeValueSingleFormatBuilder批量添加参数:
fun addValues(vararg arguments: CodeArgumentPart): CodeValueSingleFormatBuilder
fun addValues(arguments: Iterable<CodeArgumentPart>): CodeValueSingleFormatBuilder// 方式 1:使用 DSL
val code1 = CodeValue("val %V: %V = %V") {
addValue(CodePart.name("user"))
addValue(CodePart.type(userType))
addValue(CodePart.literal("null"))
}
// 方式 2:使用 builder
val code2 = CodeValue.builder("val %V: %V = %V")
.addValue(CodePart.name("user"))
.addValue(CodePart.type(userType))
.addValue(CodePart.literal("null"))
.build()Builder 会验证占位符和参数的匹配:
// 错误:缺少参数
CodeValue("val %V = %V") {
addValue(CodePart.name("x"))
// 抛出异常:Miss argument in index 2
}
// 错误:多余参数
CodeValue("val x = 1") {
addValue(CodePart.literal(42))
// 抛出异常:redundant argument
}fun CodeValue.isEmpty(): Boolean
fun CodeValue.isNotEmpty(): Boolean检查 CodeValue 是否为空:
val empty = CodeValue()
empty.isEmpty() // true
val notEmpty = CodeValue("code")
notEmpty.isNotEmpty() // trueoperator fun CodeValue.plus(codeValue: CodeValue): CodeValue合并两个 CodeValue:
val part1 = CodeValue("val x = 1\n")
val part2 = CodeValue("val y = 2\n")
val combined = part1 + part2
// 输出:
// val x = 1
// val y = 2fun CodeValueBuilder.beginControlFlow(codeValue: CodeValue): CodeValueBuilder
fun CodeValueBuilder.beginControlFlow(format: String, block: CodeValueSingleFormatBuilderDsl = {}): CodeValueBuilder
fun CodeValueBuilder.nextControlFlow(codeValue: CodeValue): CodeValueBuilder
fun CodeValueBuilder.nextControlFlow(format: String, block: CodeValueSingleFormatBuilderDsl = {}): CodeValueBuilder
fun CodeValueBuilder.endControlFlow(): CodeValueBuilder
fun CodeValueBuilder.endControlFlow(codeValue: CodeValue): CodeValueBuilder
fun CodeValueBuilder.endControlFlow(format: String, block: CodeValueSingleFormatBuilderDsl = {}): CodeValueBuilder示例:
// if-else
CodeValue {
beginControlFlow("if (condition)")
addStatement("doSomething()")
nextControlFlow("else")
addStatement("doOther()")
endControlFlow()
}
// do-while(Java 会自动添加分号)
CodeValue {
beginControlFlow("do")
addStatement("action()")
endControlFlow("while (running)")
}fun CodeValueBuilder.inControlFlow(
codeValue: CodeValue,
block: CodeValueBuilderDsl
): CodeValueBuilder
fun CodeValueBuilder.inControlFlow(
beginCode: CodeValue,
endCode: CodeValue,
block: CodeValueBuilderDsl
): CodeValueBuilder示例:
CodeValue {
inControlFlow("if (x > 0)") {
addStatement("println(%V)", CodePart.string("positive"))
}
}
// do-while 简化版
CodeValue {
inControlFlow(CodeValue("do"), CodeValue("while (running)")) {
addStatement("process()")
}
}fun CodeValueBuilder.ifControlFlow(format: String, block: CodeValueSingleFormatBuilderDsl = {}): CodeValueBuilder
fun CodeValueBuilder.elseIfControlFlow(format: String, block: CodeValueSingleFormatBuilderDsl = {}): CodeValueBuilder
fun CodeValueBuilder.elseControlFlow(): CodeValueBuilder示例:
CodeValue {
ifControlFlow("x > 0")
addStatement("println(%V)", CodePart.string("positive"))
elseIfControlFlow("x < 0")
addStatement("println(%V)", CodePart.string("negative"))
elseControlFlow()
addStatement("println(%V)", CodePart.string("zero"))
endControlFlow()
}fun CodeValueBuilder.whileControlFlow(format: String, block: CodeValueSingleFormatBuilderDsl = {}): CodeValueBuilder
fun CodeValueBuilder.doControlFlow(): CodeValueBuilder
fun CodeValueBuilder.doWhileEndControlFlow(format: String, block: CodeValueSingleFormatBuilderDsl = {}): CodeValueBuilder示例:
// while 循环
CodeValue {
whileControlFlow("i < 10")
addStatement("process(i)")
addStatement("i++")
endControlFlow()
}
// do-while 循环
CodeValue {
doControlFlow()
addStatement("action()")
doWhileEndControlFlow("running")
}fun CodeValueBuilder.tryControlFlow(): CodeValueBuilder
fun CodeValueBuilder.catchControlFlow(format: String, block: CodeValueSingleFormatBuilderDsl = {}): CodeValueBuilder
fun CodeValueBuilder.finallyControlFlow(): CodeValueBuilder示例:
CodeValue {
tryControlFlow()
addStatement("riskyOperation()")
catchControlFlow("IOException e")
addStatement("handleIOError()")
catchControlFlow("Exception e")
addStatement("handleError()")
finallyControlFlow()
addStatement("cleanup()")
endControlFlow()
}在 CodeValueBuilder 上下文中,可以使用字符串调用语法:
context(builder: CodeValueBuilder)
operator fun String.invoke(block: CodeValueSingleFormatBuilder.() -> Unit): CodeValueBuilder示例:
val builder = CodeValue.builder()
with(builder) {
"val %V = %V" {
addValue(CodePart.name("x"))
addValue(CodePart.literal(10))
}
}CodeValue {
beginControlFlow("try")
whileControlFlow("hasNext()")
ifControlFlow("item.isValid()")
addStatement("process(item)")
elseControlFlow()
addStatement("skip(item)")
endControlFlow()
endControlFlow() // while
catchControlFlow("Exception e")
addStatement("handleError(e)")
endControlFlow() // try
}// 简单代码:使用格式化字符串
val simple = CodeValue("val x = %V", CodePart.literal(42))
// 复杂逻辑:使用 Builder DSL
val complex = CodeValue {
addStatement("// Initialize")
addStatement("val x = %V", CodePart.literal(0))
inControlFlow("for (i in 1..10)") {
addStatement("x += i")
}
addStatement("return x")
}// 不推荐:过度嵌套
val nested = CodeValue {
addCode("%V", CodePart.otherCodeValue(
CodeValue("%V") {
addValue(CodePart.otherCodeValue(
CodeValue("value")
))
}
))
}
// 推荐:扁平化
val inner = CodeValue("value")
val outer = CodeValue("%V") {
addValue(CodePart.otherCodeValue(inner))
}// 推荐:使用 addStatement
CodeValue {
addStatement("val x = 1")
addStatement("val y = 2")
}
// 不推荐:手动添加分号和换行
CodeValue {
addCode("val x = 1;\n")
addCode("val y = 2;\n")
}CodeValue {
addCode("class Example {\n")
indent() // 增加缩进
addStatement("val field = 1")
addCode("fun method() {\n")
indent() // 再次增加缩进
addStatement("println(field)")
unindent() // 减少缩进
addCode("}\n")
unindent() // 减少缩进
addCode("}\n")
}// 定义可复用的代码片段
val logStatement = CodeValue("println(%V)") {
addValue(CodePart.string("Debug"))
}
// 在多处使用
CodeValue {
addCode(logStatement)
addStatement("doWork()")
addCode(logStatement)
}- 占位符匹配:占位符数量必须与参数数量严格匹配
- Builder 可变性:Builder 是可变的,build() 后仍可继续修改
- 线程安全:CodeValue 和 Builder 不是线程安全的
- 内存占用:大量嵌套会增加内存占用,考虑直接使用 Spec API
- 语言差异:Java 和 Kotlin 的 Writer 对相同 CodeValue 可能产生不同输出(如分号)