diff --git a/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/CollectionBuilderUtils.java b/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/CollectionBuilderUtils.java index cc09178a..a530d0dc 100644 --- a/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/CollectionBuilderUtils.java +++ b/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/CollectionBuilderUtils.java @@ -42,10 +42,6 @@ class CollectionBuilderUtils { private boolean needsSetShim; private boolean needsCollectionShim; - private boolean needsListMutableMaker; - private boolean needsMapMutableMaker; - private boolean needsSetMutableMaker; - private static final Class listType = List.class; private static final Class mapType = Map.class; private static final Class setType = Set.class; @@ -93,7 +89,6 @@ class CollectionBuilderUtils { } enum SingleItemsMetaDataMode { - STANDARD, STANDARD_FOR_SETTER, EXCLUDE_WILDCARD_TYPES } @@ -122,8 +117,6 @@ Optional singleItemsMetaData(RecordClassType component, Sin var hasWildcardTypeArguments = hasWildcardTypeArguments(parameterizedTypeName, typeArgumentQty); if (collectionClass != null) { return switch (mode) { - case STANDARD -> singleItemsMetaDataWithWildType(parameterizedTypeName, collectionClass, wildcardClass, typeArgumentQty); - case STANDARD_FOR_SETTER -> { if (hasWildcardTypeArguments) { yield Optional.of(new SingleItemsMetaData(collectionClass, parameterizedTypeName.typeArguments, component.typeName())); @@ -160,18 +153,15 @@ boolean isSet(RecordClassType component) { } void addShimCall(CodeBlock.Builder builder, RecordClassType component) { - if (useImmutableCollections) { + if (useImmutableCollections || addSingleItemCollectionBuilders) { if (isList(component)) { needsListShim = true; - needsListMutableMaker = true; builder.add("$L($L)", listShimName, component.name()); } else if (isMap(component)) { needsMapShim = true; - needsMapMutableMaker = true; builder.add("$L($L)", mapShimName, component.name()); } else if (isSet(component)) { needsSetShim = true; - needsSetMutableMaker = true; builder.add("$L($L)", setShimName, component.name()); } else if (component.rawTypeName().equals(collectionTypeName)) { needsCollectionShim = true; @@ -211,10 +201,6 @@ String mutableMakerName(RecordClassType component) { } void addShims(TypeSpec.Builder builder) { - if (!useImmutableCollections) { - return; - } - if (needsListShim) { builder.addMethod(buildShimMethod(listShimName, listTypeName, collectionType, parameterizedListType, tType)); } @@ -227,24 +213,19 @@ void addShims(TypeSpec.Builder builder) { if (needsCollectionShim) { builder.addMethod(buildCollectionsShimMethod()); } - } - - void addMutableMakers(TypeSpec.Builder builder) { - if (!useImmutableCollections) { - return; - } - - if (needsListMutableMaker) { - builder.addMethod(buildMutableMakerMethod(listMakerMethodName, mutableListSpec.name, parameterizedListType, tType)); - builder.addType(mutableListSpec); - } - if (needsSetMutableMaker) { - builder.addMethod(buildMutableMakerMethod(setMakerMethodName, mutableSetSpec.name, parameterizedSetType, tType)); - builder.addType(mutableSetSpec); - } - if (needsMapMutableMaker) { - builder.addMethod(buildMutableMakerMethod(mapMakerMethodName, mutableMapSpec.name, parameterizedMapType, kType, vType)); - builder.addType(mutableMapSpec); + if (addSingleItemCollectionBuilders) { + if (needsListShim) { + builder.addType(mutableListSpec); + builder.addMethod(buildMutableMakerMethod(listMakerMethodName, mutableListSpec.name, parameterizedListType, tType)); + } + if (needsSetShim) { + builder.addType(mutableSetSpec); + builder.addMethod(buildMutableMakerMethod(setMakerMethodName, mutableSetSpec.name, parameterizedSetType, tType)); + } + if (needsMapShim) { + builder.addType(mutableMapSpec); + builder.addMethod(buildMutableMakerMethod(mapMakerMethodName, mutableMapSpec.name, parameterizedMapType, kType, vType)); + } } } diff --git a/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/InternalRecordBuilderProcessor.java b/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/InternalRecordBuilderProcessor.java index 6bf79e29..c448d606 100644 --- a/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/InternalRecordBuilderProcessor.java +++ b/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/InternalRecordBuilderProcessor.java @@ -15,12 +15,8 @@ */ package io.soabase.recordbuilder.processor; -import static io.soabase.recordbuilder.processor.CollectionBuilderUtils.SingleItemsMetaDataMode.EXCLUDE_WILDCARD_TYPES; -import static io.soabase.recordbuilder.processor.CollectionBuilderUtils.SingleItemsMetaDataMode.STANDARD_FOR_SETTER; -import static io.soabase.recordbuilder.processor.ElementUtils.getBuilderName; -import static io.soabase.recordbuilder.processor.ElementUtils.getWithMethodName; -import static io.soabase.recordbuilder.processor.RecordBuilderProcessor.generatedRecordBuilderAnnotation; -import static io.soabase.recordbuilder.processor.RecordBuilderProcessor.recordBuilderGeneratedAnnotation; +import com.squareup.javapoet.*; +import io.soabase.recordbuilder.core.RecordBuilder; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.*; @@ -33,8 +29,12 @@ import java.util.stream.IntStream; import java.util.stream.Stream; -import com.squareup.javapoet.*; -import io.soabase.recordbuilder.core.RecordBuilder; +import static io.soabase.recordbuilder.processor.CollectionBuilderUtils.SingleItemsMetaDataMode.EXCLUDE_WILDCARD_TYPES; +import static io.soabase.recordbuilder.processor.CollectionBuilderUtils.SingleItemsMetaDataMode.STANDARD_FOR_SETTER; +import static io.soabase.recordbuilder.processor.ElementUtils.getBuilderName; +import static io.soabase.recordbuilder.processor.ElementUtils.getWithMethodName; +import static io.soabase.recordbuilder.processor.RecordBuilderProcessor.generatedRecordBuilderAnnotation; +import static io.soabase.recordbuilder.processor.RecordBuilderProcessor.recordBuilderGeneratedAnnotation; class InternalRecordBuilderProcessor { private final RecordBuilder.Options metaData; @@ -107,11 +107,9 @@ class InternalRecordBuilderProcessor { if (metaData.addConcreteSettersForOptional()) { add1ConcreteOptionalSetterMethod(component); } - var collectionMetaData = collectionBuilderUtils.singleItemsMetaData(component, EXCLUDE_WILDCARD_TYPES); - collectionMetaData.ifPresent(meta -> add1CollectionBuilders(meta, component)); + collectionBuilderUtils.singleItemsMetaData(component, EXCLUDE_WILDCARD_TYPES).ifPresent(meta -> add1CollectionBuilders(meta, component)); }); collectionBuilderUtils.addShims(builder); - collectionBuilderUtils.addMutableMakers(builder); builderType = builder.build(); } @@ -806,13 +804,13 @@ private String capitalize(String s) { private void add1CollectionBuilders(CollectionBuilderUtils.SingleItemsMetaData meta, RecordClassType component) { if (collectionBuilderUtils.isList(component) || collectionBuilderUtils.isSet(component)) { - add1ListBuilder(meta, component); + add1SingleItemsListBuilder(meta, component); } else if (collectionBuilderUtils.isMap(component)) { - add1MapBuilder(meta, component); + add1SingleItemsMapBuilder(meta, component); } } - private void add1MapBuilder(CollectionBuilderUtils.SingleItemsMetaData meta, RecordClassType component) { + private void add1SingleItemsMapBuilder(CollectionBuilderUtils.SingleItemsMetaData meta, RecordClassType component) { /* For a single map record component, add a methods similar to: @@ -836,15 +834,7 @@ public T addP(Iterable i) { */ for (var i = 0; i < 3; ++i) { var codeBlockBuilder = CodeBlock.builder(); - if (collectionBuilderUtils.isImmutableCollection(component)) { - codeBlockBuilder - .addStatement("this.$L = $L($L)", component.name(), collectionBuilderUtils.mutableMakerName(component), component.name()); - } else { - codeBlockBuilder - .beginControlFlow("if (this.$L == null)", component.name()) - .addStatement("this.$L = new $T<>()", component.name(), meta.singleItemCollectionClass()) - .endControlFlow(); - } + codeBlockBuilder.addStatement("this.$L = $L($L)", component.name(), collectionBuilderUtils.mutableMakerName(component), component.name()); var methodSpecBuilder = MethodSpec.methodBuilder(metaData.singleItemBuilderPrefix() + capitalize(component.name())) .addJavadoc("Add to the internally allocated {@code HashMap} for {@code $L}\n", component.name()) .addModifiers(Modifier.PUBLIC) @@ -867,7 +857,7 @@ public T addP(Iterable i) { } } - private void add1ListBuilder(CollectionBuilderUtils.SingleItemsMetaData meta, RecordClassType component) { + private void add1SingleItemsListBuilder(CollectionBuilderUtils.SingleItemsMetaData meta, RecordClassType component) { /* For a single list or set record component, add methods similar to: @@ -901,15 +891,7 @@ public T addP(Iterable i) { parameter = ParameterizedTypeName.get(parameterClass, WildcardTypeName.subtypeOf(meta.typeArguments().get(0))); } var codeBlockBuilder = CodeBlock.builder(); - if (collectionBuilderUtils.isImmutableCollection(component)) { - codeBlockBuilder - .addStatement("this.$L = $L($L)", component.name(), collectionBuilderUtils.mutableMakerName(component), component.name()); - } else { - codeBlockBuilder - .beginControlFlow("if (this.$L == null)", component.name()) - .addStatement("this.$L = new $T<>()", component.name(), meta.singleItemCollectionClass()) - .endControlFlow(); - } + codeBlockBuilder.addStatement("this.$L = $L($L)", component.name(), collectionBuilderUtils.mutableMakerName(component), component.name()); codeBlockBuilder .add(addClockBlock.build()) .addStatement("return this"); diff --git a/record-builder-test/src/main/java/io/soabase/recordbuilder/test/issue129/CombinedFields.java b/record-builder-test/src/main/java/io/soabase/recordbuilder/test/issue129/CombinedFields.java new file mode 100644 index 00000000..b5cf9409 --- /dev/null +++ b/record-builder-test/src/main/java/io/soabase/recordbuilder/test/issue129/CombinedFields.java @@ -0,0 +1,26 @@ +/** + * Copyright 2019 Jordan Zimmerman + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.soabase.recordbuilder.test.issue129; + +import java.util.List; +import java.util.Map; + +@RecordStyle +public record CombinedFields( + Map kvMap, + String combinedField, + List lines) implements CombinedFieldsBuilder.Bean, CombinedFieldsBuilder.With { +} \ No newline at end of file diff --git a/record-builder-test/src/main/java/io/soabase/recordbuilder/test/issue129/RecordStyle.java b/record-builder-test/src/main/java/io/soabase/recordbuilder/test/issue129/RecordStyle.java new file mode 100644 index 00000000..1f384251 --- /dev/null +++ b/record-builder-test/src/main/java/io/soabase/recordbuilder/test/issue129/RecordStyle.java @@ -0,0 +1,33 @@ +/** + * Copyright 2019 Jordan Zimmerman + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.soabase.recordbuilder.test.issue129; + +import io.soabase.recordbuilder.core.RecordBuilder; + +import java.lang.annotation.*; + +@RecordBuilder.Template(options = @RecordBuilder.Options( + addSingleItemCollectionBuilders = true, + addFunctionalMethodsToWith = true, + booleanPrefix = "is", + setterPrefix = "set", + beanClassName = "Bean")) +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.TYPE) +@Inherited +public @interface RecordStyle { + +}