Skip to content

Commit

Permalink
fix(generator-accessor): break down mapping builder with lambdas
Browse files Browse the repository at this point in the history
  • Loading branch information
zlataovce committed Jun 3, 2024
1 parent 0987662 commit 3ab74c7
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -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.
* <p>
* <strong>This is only for use in generated code.</strong>
*
* @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<FieldMapping> builder) {
final List<FieldMapping> 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.
* <p>
* <strong>This is only for use in generated code.</strong>
*
* @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<ConstructorMapping> 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.
* <p>
* <strong>This is only for use in generated code.</strong>
*
* @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<MethodMapping> builder) {
final List<MethodMapping> 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;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Original file line number Diff line number Diff line change
Expand Up @@ -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()")
}
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down

0 comments on commit 3ab74c7

Please sign in to comment.