diff --git a/generator/accessor-runtime/src/main/java/me/kcra/takenaka/accessor/mapping/ClassMapping.java b/generator/accessor-runtime/src/main/java/me/kcra/takenaka/accessor/mapping/ClassMapping.java index ef7f4b52110..a8b20af2a72 100644 --- a/generator/accessor-runtime/src/main/java/me/kcra/takenaka/accessor/mapping/ClassMapping.java +++ b/generator/accessor-runtime/src/main/java/me/kcra/takenaka/accessor/mapping/ClassMapping.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.function.Consumer; import java.util.stream.Collectors; /** @@ -348,52 +349,61 @@ public ClassMapping(@NotNull String name) { } /** - * Puts a new field mapping into this {@link ClassMapping}. + * Puts a new field mapping into this {@link ClassMapping} and runs a builder action on it. *

* This is only for use in generated code. * * @param name the field name declared in the accessor model - * @return the new {@link FieldMapping} + * @param builder the builder action + * @return this {@link ClassMapping} */ @ApiStatus.Internal - public @NotNull FieldMapping putField(@NotNull String name) { + @Contract("_, _ -> this") + public @NotNull ClassMapping putField(@NotNull String name, @NotNull Consumer builder) { final List overloads = fields.computeIfAbsent(name, (k) -> new ArrayList<>()); final FieldMapping mapping = new FieldMapping(this, name, overloads.size()); + builder.accept(mapping); overloads.add(mapping); - return mapping; + return this; } /** - * Puts a new constructor mapping into this {@link ClassMapping}. + * Puts a new constructor mapping into this {@link ClassMapping} and runs a builder action on it. *

* This is only for use in generated code. * - * @return the new {@link ConstructorMapping} + * @param builder the builder action + * @return this {@link ClassMapping} */ @ApiStatus.Internal - public @NotNull ConstructorMapping putConstructor() { + @Contract("_ -> this") + public @NotNull ClassMapping putConstructor(@NotNull Consumer builder) { final ConstructorMapping mapping = new ConstructorMapping(this, constructors.size()); + builder.accept(mapping); constructors.add(mapping); - return mapping; + return this; } /** - * Puts a new method mapping into this {@link ClassMapping}. + * Puts a new method mapping into this {@link ClassMapping} and runs a builder action on it. *

* This is only for use in generated code. * * @param name the method name declared in the accessor model - * @return the new {@link MethodMapping} + * @param builder the builder action + * @return this {@link ClassMapping} */ @ApiStatus.Internal - public @NotNull MethodMapping putMethod(@NotNull String name) { + @Contract("_, _ -> this") + public @NotNull ClassMapping putMethod(@NotNull String name, @NotNull Consumer builder) { final List overloads = methods.computeIfAbsent(name, (k) -> new ArrayList<>()); final MethodMapping mapping = new MethodMapping(this, name, overloads.size()); + builder.accept(mapping); overloads.add(mapping); - return mapping; + return this; } /** diff --git a/generator/accessor-runtime/src/main/kotlin/me/kcra/takenaka/accessor/util/kotlin/builderExtensions.kt b/generator/accessor-runtime/src/main/kotlin/me/kcra/takenaka/accessor/util/kotlin/builderExtensions.kt index 0bb6dc23509..a9ad8c0e5a6 100644 --- a/generator/accessor-runtime/src/main/kotlin/me/kcra/takenaka/accessor/util/kotlin/builderExtensions.kt +++ b/generator/accessor-runtime/src/main/kotlin/me/kcra/takenaka/accessor/util/kotlin/builderExtensions.kt @@ -44,23 +44,23 @@ inline fun classMapping(name: String, block: ClassMapping.() -> Unit): ClassMapp * * @param name the field name declared in the accessor model * @param block the builder action - * @return the [FieldMapping] + * @return the [ClassMapping] */ -inline fun ClassMapping.field(name: String, block: FieldMapping.() -> Unit): FieldMapping = putField(name).apply(block) +fun ClassMapping.field(name: String, block: FieldMapping.() -> Unit): ClassMapping = putField(name, block) /** * Builds a new [ConstructorMapping] and appends it to the [ClassMapping]. * * @param block the builder action - * @return the [ConstructorMapping] + * @return the [ClassMapping] */ -inline fun ClassMapping.constructor(block: ConstructorMapping.() -> Unit): ConstructorMapping = putConstructor().apply(block) +fun ClassMapping.constructor(block: ConstructorMapping.() -> Unit): ClassMapping = putConstructor(block) /** * Builds a new [MethodMapping] and appends it to the [ClassMapping]. * * @param name the method name declared in the accessor model * @param block the builder action - * @return the [MethodMapping] + * @return the [ClassMapping] */ -inline fun ClassMapping.method(name: String, block: MethodMapping.() -> Unit): MethodMapping = putMethod(name).apply(block) +fun ClassMapping.method(name: String, block: MethodMapping.() -> Unit): ClassMapping = putMethod(name, block) diff --git a/generator/accessor/src/main/kotlin/me/kcra/takenaka/generator/accessor/context/impl/JavaGenerationContext.kt b/generator/accessor/src/main/kotlin/me/kcra/takenaka/generator/accessor/context/impl/JavaGenerationContext.kt index bf59c44e8f6..41b6fdeb62d 100644 --- a/generator/accessor/src/main/kotlin/me/kcra/takenaka/generator/accessor/context/impl/JavaGenerationContext.kt +++ b/generator/accessor/src/main/kotlin/me/kcra/takenaka/generator/accessor/context/impl/JavaGenerationContext.kt @@ -105,62 +105,64 @@ open class JavaGenerationContext( } resolvedAccessor.fields.forEach { (fieldAccessor, fieldNode) -> - add("\n.putField(\$S)", fieldAccessor.name) - withIndent { - groupFieldNames(fieldNode).forEach { (fieldKey, versions) -> - val (ns, name) = fieldKey + add( + "\n.putField(\$S, \$L)", + fieldAccessor.name, + buildJLambdaBlock("m") { + groupFieldNames(fieldNode).forEach { (fieldKey, versions) -> + val (ns, name) = fieldKey - add("\n.put(\$S, \$S, \$L)", ns, name, JCodeBlock.join(versions.map { JCodeBlock.of("\$S", it.id) }, ", ")) + addStatement("m.put(\$S, \$S, \$L)", ns, name, JCodeBlock.join(versions.map { JCodeBlock.of("\$S", it.id) }, ", ")) + } } - - add("\n.getParent()") - } + ) } resolvedAccessor.constructors.forEach { (_, ctorNode) -> - add("\n.putConstructor()") - withIndent { - groupConstructorNames(ctorNode).forEach { (ctorKey, versions) -> - val (ns, desc) = ctorKey + add( + "\n.putConstructor(\$L)", + buildJLambdaBlock("m") { + groupConstructorNames(ctorNode).forEach { (ctorKey, versions) -> + val (ns, desc) = ctorKey - add("\n.put(\$S, new \$T[] { \$L }", ns, SourceTypes.STRING, JCodeBlock.join(versions.map { JCodeBlock.of("\$S", it.id) }, ", ")) + add("m.put(\$S, new \$T[] { \$L }", ns, SourceTypes.STRING, JCodeBlock.join(versions.map { JCodeBlock.of("\$S", it.id) }, ", ")) - val args = Type.getArgumentTypes(desc) - .map { JCodeBlock.of("\$S", it.className) } + val args = Type.getArgumentTypes(desc) + .map { JCodeBlock.of("\$S", it.className) } - if (args.isNotEmpty()) { - add(", ") - add(JCodeBlock.join(args, ", ")) - } + if (args.isNotEmpty()) { + add(", ") + add(JCodeBlock.join(args, ", ")) + } - add(")") + add(");\n") + } } - - add("\n.getParent()") - } + ) } resolvedAccessor.methods.forEach { (methodAccessor, methodNode) -> - add("\n.putMethod(\$S)", methodAccessor.name) - withIndent { - groupMethodNames(methodNode).forEach { (methodKey, versions) -> - val (ns, name, desc) = methodKey + add( + "\n.putMethod(\$S, \$L)", + methodAccessor.name, + buildJLambdaBlock("m") { + groupMethodNames(methodNode).forEach { (methodKey, versions) -> + val (ns, name, desc) = methodKey - add("\n.put(\$S, new \$T[] { \$L }, \$S", ns, SourceTypes.STRING, JCodeBlock.join(versions.map { JCodeBlock.of("\$S", it.id) }, ", "), name) + add("m.put(\$S, new \$T[] { \$L }, \$S", ns, SourceTypes.STRING, JCodeBlock.join(versions.map { JCodeBlock.of("\$S", it.id) }, ", "), name) - val args = Type.getArgumentTypes(desc) - .map { JCodeBlock.of("\$S", it.className) } + val args = Type.getArgumentTypes(desc) + .map { JCodeBlock.of("\$S", it.className) } - if (args.isNotEmpty()) { - add(", ") - add(JCodeBlock.join(args, ", ")) - } + if (args.isNotEmpty()) { + add(", ") + add(JCodeBlock.join(args, ", ")) + } - add(")") + add(");\n") + } } - - add("\n.getParent()") - } + ) } } } diff --git a/generator/accessor/src/main/kotlin/me/kcra/takenaka/generator/accessor/context/impl/SourceTypes.kt b/generator/accessor/src/main/kotlin/me/kcra/takenaka/generator/accessor/context/impl/SourceTypes.kt index 97e1329035a..39f093aca56 100644 --- a/generator/accessor/src/main/kotlin/me/kcra/takenaka/generator/accessor/context/impl/SourceTypes.kt +++ b/generator/accessor/src/main/kotlin/me/kcra/takenaka/generator/accessor/context/impl/SourceTypes.kt @@ -73,6 +73,29 @@ inline fun com.squareup.kotlinpoet.PropertySpec.Builder.initializer(block: KCode fun com.squareup.kotlinpoet.FileSpec.Builder.addImport(memberName: MemberName): com.squareup.kotlinpoet.FileSpec.Builder = memberName.run { addImport("$packageName${enclosingClassName?.let { ".$it" } ?: ""}", simpleName) } +/** + * Builds a Java lambda block. + * + * @param parameters the lambda parameter names + * @param block the lambda code block builder action + * @return the built code block + */ +inline fun buildJLambdaBlock(vararg parameters: String, block: JCodeBlockBuilder.() -> Unit): JCodeBlock = buildJCodeBlock { + add( + parameters.joinToString( + prefix = "(".takeIf { parameters.size != 1 } ?: "", + postfix = ")".takeIf { parameters.size != 1 } ?: "" + ) + ) + add(" -> {\n") + + indent() + block() + unindent() + + add("}") +} + /** * JavaPoet/KotlinPoet types. */