diff --git a/.github/semantic.yml b/.github/semantic.yml
new file mode 100644
index 0000000..052d4d5
--- /dev/null
+++ b/.github/semantic.yml
@@ -0,0 +1 @@
+titleAndCommits: true
\ No newline at end of file
diff --git a/README.md b/README.md
index ab5e3c8..a846e24 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ It provides an easy way to avoid writing repetitive boilerplate code. It generat
* [builders](https://github.com/pawellabaj/auto-record/wiki/Record-Builder) - incorporating [Randgalt/record-builder](https://github.com/Randgalt/record-builder) library
* [memoization](https://github.com/pawellabaj/auto-record/wiki/Memoization)
* [ignoring fields](https://github.com/pawellabaj/auto-record/wiki/Ignored-components) in `hashCode()` and `equals()` methods
-* generated _common_ methods if the record has an [array component](https://github.com/pawellabaj/auto-record/wiki/Array-components)
+* generated _common_ methods if the record has an [array recordComponent](https://github.com/pawellabaj/auto-record/wiki/Array-components)
* exclusion from [JaCoCo test coverage](https://github.com/pawellabaj/auto-record/wiki/JaCoCo-exclusion) analysis
AutoRecord allows users to customize record generation process by:
diff --git a/extensions/immutable-collections/pom.xml b/extensions/immutable-collections/pom.xml
new file mode 100644
index 0000000..815803e
--- /dev/null
+++ b/extensions/immutable-collections/pom.xml
@@ -0,0 +1,92 @@
+
+
+ 4.0.0
+
+ pl.com.labaj
+ auto-record-project
+
+ 2.1.1-SNAPSHOT
+ ../../pom.xml
+
+
+ auto-record-immutable-collections
+ 1.0.0-SNAPSHOT
+
+
+ 32.1.1-jre
+
+ ${project.basedir}/../../.build/lic-header.txt
+
+
+
+
+ pl.com.labaj
+ auto-record
+
+
+
+ com.google.guava
+ guava
+ runtime
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+ com.google.testing.compile
+ compile-testing
+ test
+
+
+
+
+
+
+ pl.com.labaj
+ auto-record
+ ${project.parent.version}
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+
+
+
+
+
+ com.mycila
+ license-maven-plugin
+
+
+
+ ${license-maven-plugin.header}
+
+
+
+
+
+
+
+
+
+ verify
+
+
+ ${project.basedir}/../../target/site/jacoco-aggregate/jacoco.xml
+
+
+
+
\ No newline at end of file
diff --git a/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/AdditionalMethodsGenerator.java b/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/AdditionalMethodsGenerator.java
new file mode 100644
index 0000000..44a243d
--- /dev/null
+++ b/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/AdditionalMethodsGenerator.java
@@ -0,0 +1,220 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterSpec;
+import com.squareup.javapoet.ParameterizedTypeName;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeVariableName;
+import pl.com.labaj.autorecord.context.Logger;
+import pl.com.labaj.autorecord.context.StaticImports;
+
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.Types;
+import java.util.ArrayDeque;
+import java.util.EnumMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+
+import static java.util.Comparator.reverseOrder;
+import static java.util.Objects.isNull;
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.collectingAndThen;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toMap;
+import static java.util.stream.Collectors.toSet;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.STATIC;
+import static pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension.PROCESSED_TYPES;
+import static pl.com.labaj.autorecord.extension.compact.ProcessedType.allProcessedTypes;
+
+class AdditionalMethodsGenerator {
+ private static final EnumMap METHOD_GENERATORS = allProcessedTypes().stream()
+ .collect(toMap(
+ identity(),
+ AdditionalMethodsGenerator::builderFor,
+ (b1, b2) -> b1,
+ () -> new EnumMap<>(ProcessedType.class)
+ ));
+
+ private final Types typeUtils;
+
+ private final StaticImports staticImports;
+ private final Logger logger;
+
+ AdditionalMethodsGenerator(Types typeUtils,
+ StaticImports staticImports,
+ Logger logger) {
+ this.typeUtils = typeUtils;
+ this.staticImports = staticImports;
+ this.logger = logger;
+ }
+
+ List generateAdditionalMethods(List componentsToProcess, ProcessedTypesStructure structure) {
+ var pTypesToGenerate = collectPTypesToGenerate(componentsToProcess, structure);
+
+ return ProcessedType.allProcessedTypes().stream()
+ .filter(pTypesToGenerate::contains)
+ .sorted(reverseOrder())
+ .map(METHOD_GENERATORS::get)
+ .map(methodGenerator -> methodGenerator.generateMethod(typeUtils, structure, staticImports, logger))
+ .toList();
+ }
+
+ private HashSet collectPTypesToGenerate(List componentsToProcess, ProcessedTypesStructure structure) {
+ var pTypesToCheck = componentsToProcess.stream()
+ .map(RecordComponent::pType)
+ .collect(collectingAndThen(toSet(), ArrayDeque::new));
+
+ var pTypesToGenerate = new HashSet();
+
+ while (!pTypesToCheck.isEmpty()) {
+ var pType = pTypesToCheck.removeFirst();
+ if (structure.needsAdditionalMethod(pType)) {
+ pTypesToGenerate.add(pType);
+ }
+
+ pType.directSubTypes().stream()
+ .filter(subType -> !pTypesToCheck.contains(subType) && !pTypesToGenerate.contains(subType))
+ .forEach(pTypesToCheck::addLast);
+ }
+
+ return pTypesToGenerate;
+ }
+
+ private static MethodGenerator builderFor(ProcessedType pType) {
+ return (typeUtils, structure, staticImports, logger) -> {
+ var methodBuilder = getMethodBuilder(typeUtils, pType);
+
+ immutableTypesBlock(structure, pType)
+ .ifPresent(methodBuilder::addCode);
+ subTypesBlocks(pType, structure)
+ .forEach(methodBuilder::addCode);
+
+ var returnStatement = isNull(pType.factoryClassName())
+ ? CodeBlock.of("return $L", pType.argumentName())
+ : CodeBlock.of("return $T.$L($L)", pType.factoryClassName(), pType.factoryMethodName(), pType.argumentName());
+ methodBuilder.addStatement(returnStatement);
+
+ return methodBuilder.build();
+ };
+ }
+
+ private static MethodSpec.Builder getMethodBuilder(Types typeUtils, ProcessedType pType) {
+ var typeVariableNames = pType.genericNames().stream()
+ .map(TypeVariableName::get)
+ .toList();
+ var typeName = getTypeName(typeUtils, pType, typeVariableNames);
+ var parameterSpec = ParameterSpec.builder(typeName, pType.argumentName()).build();
+
+ var builder = MethodSpec.methodBuilder("_" + pType.factoryMethodName())
+ .addModifiers(PRIVATE, STATIC)
+ .returns(typeName)
+ .addParameter(parameterSpec);
+
+ typeVariableNames.forEach(builder::addTypeVariable);
+
+ return builder;
+ }
+
+ private static TypeName getTypeName(Types typeUtils, ProcessedType pType, List typeVariableNames) {
+ var collectionType = PROCESSED_TYPES.get(pType);
+
+ if (typeVariableNames.isEmpty()) {
+ return TypeName.get(collectionType);
+ }
+
+ var className = ClassName.get((TypeElement) typeUtils.asElement(collectionType));
+
+ return ParameterizedTypeName.get(className, typeVariableNames.toArray(TypeVariableName[]::new));
+ }
+
+ private static Optional immutableTypesBlock(ProcessedTypesStructure structure, ProcessedType pType) {
+ var immutableTypes = structure.getImmutableTypes(pType);
+ if (immutableTypes.isEmpty()) {
+ return Optional.empty();
+ }
+
+ var ifFormat = new StringBuilder("if (");
+ var i = 0;
+ for (var iterator = immutableTypes.iterator(); iterator.hasNext(); i++) {
+ iterator.next();
+ String name = pType.argumentName();
+
+ ifFormat.append(name).append(" instanceof $T");
+ if (!pType.genericNames().isEmpty()) {
+ var genericClause = pType.genericNames().stream()
+ .collect(joining(",", "<", ">"));
+ ifFormat.append(genericClause);
+ }
+
+ if (iterator.hasNext()) {
+ ifFormat.append(i == 0 ? "\n$>$>|| " : "\n|| ");
+ }
+ }
+ ifFormat.append(")");
+
+ var size = immutableTypes.size();
+ var block = CodeBlock.builder()
+ .beginControlFlow(ifFormat.toString(), immutableTypes.toArray())
+ .addStatement(size > 1 ? "$<$ subTypesBlocks(ProcessedType pType, ProcessedTypesStructure structure) {
+ return pType.directSubTypes().stream()
+ .filter(structure::needsAdditionalMethod)
+ .sorted(reverseOrder())
+ .map(subPType -> subTypeBlock(subPType, pType, structure))
+ .toList();
+ }
+
+ private static CodeBlock subTypeBlock(ProcessedType pType, ProcessedType parent, ProcessedTypesStructure structure) {
+ var argumentName = pType.argumentName();
+ var factoryClassName = pType.factoryClassName();
+ var factoryMethodName = pType.factoryMethodName();
+
+ var parentGenericNames = parent.genericNames();
+ var genericClause = parentGenericNames.isEmpty() || !pType.checkGenericInInstanceOf()
+ ? ""
+ : parentGenericNames.stream().collect(joining(",", "<", ">"));
+ var statement = structure.needsAdditionalMethod(pType)
+ ? CodeBlock.of("return _$L($L)", factoryMethodName, argumentName)
+ : CodeBlock.of("return $T.$L($L)", factoryClassName, factoryMethodName, argumentName);
+
+ return CodeBlock.builder()
+ .beginControlFlow("if ($L instanceof $T$L $L)", parent.argumentName(), PROCESSED_TYPES.get(pType), genericClause, argumentName)
+ .addStatement(statement)
+ .endControlFlow()
+ .build();
+ }
+
+ @FunctionalInterface
+ private interface MethodGenerator {
+ MethodSpec generateMethod(Types typeUtils,
+ ProcessedTypesStructure structure,
+ StaticImports staticImports,
+ Logger logger);
+ }
+}
diff --git a/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/ImmutableCollectionsExtension.java b/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/ImmutableCollectionsExtension.java
new file mode 100644
index 0000000..4e96175
--- /dev/null
+++ b/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/ImmutableCollectionsExtension.java
@@ -0,0 +1,145 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.MethodSpec;
+import pl.com.labaj.autorecord.context.Context;
+import pl.com.labaj.autorecord.context.Logger;
+import pl.com.labaj.autorecord.context.StaticImports;
+import pl.com.labaj.autorecord.extension.CompactConstructorExtension;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import static java.util.Objects.isNull;
+import static java.util.Objects.nonNull;
+import static java.util.stream.Collectors.toSet;
+import static javax.lang.model.type.TypeKind.ARRAY;
+import static pl.com.labaj.autorecord.extension.compact.Names.PREDEFINED_IMMUTABLE_NAMES;
+import static pl.com.labaj.autorecord.extension.compact.ProcessedType.allProcessedTypes;
+import static pl.com.labaj.autorecord.extension.compact.RecordComponent.debugInfo;
+
+public class ImmutableCollectionsExtension implements CompactConstructorExtension {
+
+ private static Types typeUtilsFromPreviousRun = null;
+ private static final Map IMMUTABLE_TYPES = new HashMap<>();
+ static final EnumMap PROCESSED_TYPES = new EnumMap<>(ProcessedType.class);
+
+ private Types typeUtils;
+ private Elements elementUtils;
+ private Logger logger;
+ private Set immutableTypes;
+ private List componentsToProcess;
+ private ProcessedTypesStructure structure;
+
+ @Override
+ public void init(ProcessingEnvironment processingEnv, String[] parameters) {
+ typeUtils = processingEnv.getTypeUtils();
+ elementUtils = processingEnv.getElementUtils();
+
+ if (!nonNull(typeUtilsFromPreviousRun) || typeUtilsFromPreviousRun != typeUtils) {
+ typeUtilsFromPreviousRun = typeUtils;
+ IMMUTABLE_TYPES.clear();
+ PROCESSED_TYPES.clear();
+ }
+
+ var immutableNames = new HashSet();
+ immutableNames.addAll(PREDEFINED_IMMUTABLE_NAMES);
+ immutableNames.addAll(Arrays.asList(parameters));
+
+ immutableNames.forEach(name -> IMMUTABLE_TYPES.computeIfAbsent(name, this::loadType));
+ allProcessedTypes().forEach(name -> PROCESSED_TYPES.computeIfAbsent(name, this::loadType));
+
+ immutableTypes = immutableNames.stream()
+ .map(IMMUTABLE_TYPES::get)
+ .collect(toSet());
+
+ var structreBuilder = new ProcessedTypesStructure.Builder(typeUtils, immutableTypes);
+ structure = structreBuilder.buildStructure();
+ }
+
+ @Override
+ public boolean shouldGenerateCompactConstructor(boolean isGeneratedByProcessor, Context context) {
+ logger = context.logger();
+
+ var componentBuilder = new RecordComponent.Builder(typeUtils, immutableTypes, logger);
+ var declaredComponents = context.components()
+ .stream()
+ .filter(recordComponent -> !recordComponent.type().getKind().isPrimitive())
+ .filter(recordComponent -> recordComponent.type().getKind() != ARRAY)
+ .toList();
+ if (declaredComponents.isEmpty()) {
+ return false;
+ }
+
+ componentsToProcess = declaredComponents.stream()
+ .map(componentBuilder::toExtensionRecordComponent)
+ .filter(Objects::nonNull)
+ .toList();
+
+ return !componentsToProcess.isEmpty();
+ }
+
+ @Override
+ public CodeBlock suffixCompactConstructorContent(Context context, StaticImports staticImports) {
+ if (true) { //TODO: debugger info
+ logger.debug("Components to process:\n" + debugInfo(componentsToProcess));
+ logger.note("Types structure:\n" + structure.debugInfo());
+ }
+
+ var codeBuilder = CodeBlock.builder();
+
+ var statementGenerator = new StatementGenerator(typeUtils, structure, staticImports, logger);
+
+ componentsToProcess.stream()
+ .map(statementGenerator::generateStatement)
+ .forEach(codeBuilder::addStatement);
+
+ return codeBuilder.build();
+ }
+
+ @Override
+ public List additionalMethodsToSupportCompactConstructor(Context context, StaticImports staticImports) {
+ var additionalMethodsGenerator = new AdditionalMethodsGenerator(typeUtils, staticImports, logger);
+ return additionalMethodsGenerator.generateAdditionalMethods(componentsToProcess, structure);
+ }
+
+ private TypeMirror loadType(String className) {
+ var typeElement = elementUtils.getTypeElement(className);
+ if (isNull(typeElement)) {
+ return null;
+ }
+
+ var type = typeElement.asType();
+ return typeUtils.erasure(type);
+ }
+
+ private TypeMirror loadType(ProcessedType className) {
+ return loadType(className.className());
+ }
+}
diff --git a/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/Names.java b/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/Names.java
new file mode 100644
index 0000000..89c5ec1
--- /dev/null
+++ b/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/Names.java
@@ -0,0 +1,44 @@
+
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import com.squareup.javapoet.ClassName;
+
+import java.util.Set;
+
+final class Names {
+ private static final String GUAVA_PACKAGE = "com.google.common.collect";
+ private static final String IMMUTABLE_SET = "ImmutableSet";
+ private static final String IMMUTABLE_SORTED_SET = "ImmutableSortedSet";
+ private static final String IMMUTABLE_LIST = "ImmutableList";
+ private static final String IMMUTABLE_MAP = "ImmutableMap";
+
+ static final ClassName GUAVA_IMMUTABLE_SET_CLASS_NAME = ClassName.get(GUAVA_PACKAGE, IMMUTABLE_SET);
+ static final ClassName GUAVA_IMMUTABLE_SORTED_SET_CLASS_NAME = ClassName.get(GUAVA_PACKAGE, IMMUTABLE_SORTED_SET);
+ static final ClassName GUAVA_IMMUTABLE_LIST_CLASS_NAME = ClassName.get(GUAVA_PACKAGE, IMMUTABLE_LIST);
+ static final ClassName GUAVA_IMMUTABLE_MAP_CLASS_NAME = ClassName.get(GUAVA_PACKAGE, IMMUTABLE_MAP);
+
+ static final Set PREDEFINED_IMMUTABLE_NAMES = Set.of(
+ GUAVA_PACKAGE + "." + IMMUTABLE_SET,
+ GUAVA_PACKAGE + "." + IMMUTABLE_SORTED_SET,
+ GUAVA_PACKAGE + "." + IMMUTABLE_LIST,
+ GUAVA_PACKAGE + "." + IMMUTABLE_MAP
+ );
+
+ private Names() {}
+}
diff --git a/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/ProcessedType.java b/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/ProcessedType.java
new file mode 100644
index 0000000..bfda15e
--- /dev/null
+++ b/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/ProcessedType.java
@@ -0,0 +1,125 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import com.squareup.javapoet.ClassName;
+
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toMap;
+import static org.apache.commons.lang3.StringUtils.capitalize;
+import static pl.com.labaj.autorecord.extension.compact.Names.GUAVA_IMMUTABLE_LIST_CLASS_NAME;
+import static pl.com.labaj.autorecord.extension.compact.Names.GUAVA_IMMUTABLE_MAP_CLASS_NAME;
+import static pl.com.labaj.autorecord.extension.compact.Names.GUAVA_IMMUTABLE_SET_CLASS_NAME;
+import static pl.com.labaj.autorecord.extension.compact.Names.GUAVA_IMMUTABLE_SORTED_SET_CLASS_NAME;
+
+@SuppressWarnings("java:S1192")
+enum ProcessedType {
+ MAP("java.util.Map", Set.of(), GUAVA_IMMUTABLE_MAP_CLASS_NAME, "copyOf"){
+ @Override List genericNames() {return List.of("K", "V");}
+ },
+ LIST("java.util.List", Set.of(), GUAVA_IMMUTABLE_LIST_CLASS_NAME, "copyOf"),
+ NAVIGABLE_SET("java.util.NavigableSet", Set.of(), GUAVA_IMMUTABLE_SORTED_SET_CLASS_NAME, "copyOfSorted"),
+ SORTED_SET("java.util.SortedSet", Set.of(NAVIGABLE_SET), GUAVA_IMMUTABLE_SORTED_SET_CLASS_NAME, "copyOfSorted"),
+ SET("java.util.Set", Set.of(SORTED_SET), GUAVA_IMMUTABLE_SET_CLASS_NAME, "copyOf"),
+ OBJECT("java.lang.Object", Set.of(SET, LIST, MAP), null, "copyOfObject") {
+ @Override List genericNames() {return List.of();}
+ };
+
+ private static final Set ALL_TYPES = EnumSet.allOf(ProcessedType.class);
+ private static final Map NAME_TO_TYPES = ALL_TYPES.stream()
+ .collect(toMap(ProcessedType::className, identity()));
+ private final String className;
+
+ private final Set directSubTypes;
+ private final ClassName factoryClassName;
+ private final String factoryMethodName;
+ private final String camelCaseName;
+
+ ProcessedType(String className,
+ Set directSubTypes,
+ ClassName factoryClassName,
+ String factoryMethodName) {
+ this.className = className;
+ this.directSubTypes = directSubTypes;
+ this.factoryClassName = factoryClassName;
+ this.factoryMethodName = factoryMethodName;
+
+ camelCaseName = toCamelCase();
+ }
+
+ static Set allProcessedTypes() {
+ return ALL_TYPES;
+ }
+
+ static Optional pTypeOf(String className) {
+ return Optional.ofNullable(NAME_TO_TYPES.get(className));
+ }
+
+ static boolean sameFactory(ProcessedType pType, ProcessedType subPType) {
+ return subPType.factoryClassName().equals(pType.factoryClassName()) && subPType.factoryMethodName().equals(pType.factoryMethodName());
+ }
+
+ String className() {
+ return className;
+ }
+
+ String argumentName() {
+ return camelCaseName;
+ }
+
+ Set directSubTypes() {
+ return directSubTypes;
+ }
+
+ boolean checkGenericInInstanceOf() {
+ return true;
+ }
+
+ ClassName factoryClassName() {
+ return factoryClassName;
+ }
+
+ String factoryMethodName() {
+ return factoryMethodName;
+ }
+
+ List genericNames() {
+ return List.of("E");
+ }
+
+ @Override
+ public String toString() {
+ return className;
+ }
+
+ private String toCamelCase() {
+ var parts = name().split("_");
+ var camelCase = new StringBuilder(parts[0].toLowerCase());
+
+ for (int i = 1; i < parts.length; i++) {
+ camelCase.append(capitalize(parts[i].toLowerCase()));
+ }
+
+ return camelCase.toString();
+ }
+}
diff --git a/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/ProcessedTypesStructure.java b/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/ProcessedTypesStructure.java
new file mode 100644
index 0000000..538f859
--- /dev/null
+++ b/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/ProcessedTypesStructure.java
@@ -0,0 +1,154 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Types;
+import java.util.Collection;
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Stream;
+
+import static java.util.Comparator.comparing;
+import static java.util.Objects.nonNull;
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toCollection;
+import static java.util.stream.Collectors.toMap;
+import static java.util.stream.Collectors.toSet;
+import static org.apache.commons.lang3.StringUtils.substringAfterLast;
+import static pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension.PROCESSED_TYPES;
+import static pl.com.labaj.autorecord.extension.compact.ProcessedType.OBJECT;
+import static pl.com.labaj.autorecord.extension.compact.ProcessedType.allProcessedTypes;
+
+final class ProcessedTypesStructure {
+ private final Map> immutableTypes;
+ private final Map additionalMethodNeeded;
+
+ private ProcessedTypesStructure(EnumMap> immutableTypes, Map additionalMethodNeeded) {
+ this.immutableTypes = immutableTypes;
+ this.additionalMethodNeeded = additionalMethodNeeded;
+ }
+
+ String debugInfo() {
+ return immutableTypes.entrySet().stream()
+ .map(item -> {
+ var types = item.getValue()
+ .stream()
+ .map(TypeMirror::toString)
+ .map(name -> substringAfterLast(name, "."))
+ .collect(joining(", ", "(", ")"));
+ var className = substringAfterLast(item.getKey().className(), ".");
+ var needsAdditionalMethod = additionalMethodNeeded.get(item.getKey());
+
+ return className + " : " + needsAdditionalMethod + " -> " + types;
+ })
+ .collect(joining("\n"));
+ }
+
+ boolean needsAdditionalMethod(ProcessedType processedType) {
+ return additionalMethodNeeded.containsKey(processedType) && additionalMethodNeeded.get(processedType);
+ }
+
+ Set getImmutableTypes(ProcessedType pType) {
+ return immutableTypes.get(pType);
+ }
+
+ static class Builder {
+ private final Types typeUtils;
+ private final Set immutableTypes;
+
+ Builder(Types typeUtils, Set immutableTypes) {
+ this.typeUtils = typeUtils;
+ this.immutableTypes = immutableTypes;
+ }
+
+ ProcessedTypesStructure buildStructure() {
+ var structure = allProcessedTypes().stream()
+ .collect(toMap(
+ identity(),
+ pType -> immutableTypes
+ .stream()
+ .filter(immutableType -> typeUtils.isSubtype(immutableType, PROCESSED_TYPES.get(pType)))
+ .collect(toCollection(() -> new TreeSet<>(comparing(TypeMirror::toString)))),
+ (s1, s2) -> {
+ s1.addAll(s2);
+ return s1;
+ },
+ () -> new EnumMap<>(ProcessedType.class)
+ ));
+
+ optimizeStructure(OBJECT, structure);
+
+ var additionalMethodNeeded = new EnumMap(ProcessedType.class);
+ collectNeedsInfo(null, OBJECT, structure, additionalMethodNeeded);
+
+ return new ProcessedTypesStructure(structure, additionalMethodNeeded);
+ }
+
+ @SuppressWarnings("SortedCollectionWithNonComparableKeys")
+ private Set optimizeStructure(ProcessedType pType, EnumMap> structure) {
+ var typeMirrors = structure.get(pType);
+
+ if (pType.directSubTypes().isEmpty()) {
+ return typeMirrors;
+ }
+
+ var toRemove = pType.directSubTypes().stream()
+ .map(subType -> optimizeStructure(subType, structure))
+ .flatMap(Collection::stream)
+ .collect(toSet());
+
+ structure.get(pType).removeAll(toRemove);
+
+ return Stream.concat(toRemove.stream(), typeMirrors.stream()).collect(toSet());
+ }
+
+ private boolean collectNeedsInfo(ProcessedType parent, ProcessedType pType,
+ EnumMap> structure,
+ EnumMap additionalMethodNeeded) {
+
+
+ if (pType.directSubTypes().isEmpty()) {
+ var result = !structure.get(pType).isEmpty();
+ additionalMethodNeeded.put(pType, result);
+ return result;
+ }
+
+ var needs = new AtomicBoolean();
+ var subNeededInfo = pType.directSubTypes().stream()
+ .collect(toMap(
+ identity(),
+ subType -> collectNeedsInfo(pType, subType, structure, additionalMethodNeeded)
+ ));
+
+ var someSubNeeds = subNeededInfo.values().stream()
+ .reduce(false, (b1, b2) -> b1 || b2);
+ needs.set(someSubNeeds);
+
+ if (!needs.get()) {
+ needs.set(!nonNull(parent));
+ }
+
+ additionalMethodNeeded.put(pType, needs.get());
+ return needs.get();
+ }
+ }
+}
diff --git a/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/RecordComponent.java b/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/RecordComponent.java
new file mode 100644
index 0000000..b2c2a05
--- /dev/null
+++ b/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/RecordComponent.java
@@ -0,0 +1,109 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import pl.com.labaj.autorecord.context.Logger;
+
+import javax.annotation.Nullable;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Types;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static java.util.stream.Collectors.joining;
+import static javax.lang.model.type.TypeKind.ERROR;
+import static pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension.PROCESSED_TYPES;
+import static pl.com.labaj.autorecord.extension.compact.ProcessedType.pTypeOf;
+
+record RecordComponent(String name, boolean isNullable, TypeMirror declaredType, ProcessedType pType) {
+
+ static String debugInfo(List recordComponents) {
+ return recordComponents.stream()
+ .map(RecordComponent::toString)
+ .collect(joining("\n"));
+ }
+
+ @Override
+ public String toString() {
+ return name + " : " + declaredType;
+ }
+
+ static class Builder {
+ private final Types typeUtils;
+ private final Set immutableTypes;
+ private final Set collectionTypes;
+ private final Logger logger;
+ private final Map toBeProcessedCache = new HashMap<>();
+
+ Builder(Types typeUtils, Set immutableTypes, Logger logger) {
+ this.typeUtils = typeUtils;
+ this.immutableTypes = immutableTypes;
+ collectionTypes = Set.copyOf(PROCESSED_TYPES.values());
+ this.logger = logger;
+ }
+
+ @Nullable
+ RecordComponent toExtensionRecordComponent(pl.com.labaj.autorecord.context.RecordComponent component) {
+ var isNullable = component.isAnnotatedWith(Nullable.class);
+ var componentType = component.type();
+ var declaredType = typeUtils.erasure(componentType);
+ var shouldBeProcessed = toBeProcessedCache.computeIfAbsent(declaredType.toString(), name -> shouldBeProcessed(declaredType));
+
+ if (!shouldBeProcessed) {
+ return null;
+ }
+
+ var pType = pTypeOf(declaredType.toString())
+ .orElseGet(() -> {
+ logger.mandatoryWarning("Unrecognized type for processing " + declaredType);
+ return null;
+ });
+
+ return new RecordComponent(component.name(), isNullable, declaredType, pType);
+ }
+
+ private boolean shouldBeProcessed(TypeMirror componentType) {
+ if (componentType.getKind() == ERROR) {
+ return true;
+ }
+
+ var isImmutableType = immutableTypes.stream()
+ .anyMatch(immutableType -> typeUtils.isSameType(componentType, immutableType));
+ if (isImmutableType) {
+ logger.debug(componentType + " is immutable");
+ return false;
+ }
+
+ var hasImmutableSuperType = immutableTypes.stream()
+ .anyMatch(immutableType -> typeUtils.isSubtype(componentType, immutableType));
+ if (hasImmutableSuperType) {
+ logger.debug(componentType + " has immutable super type");
+ return false;
+ }
+
+ var isCollection = collectionTypes.stream()
+ .anyMatch(collectionType -> typeUtils.isSameType(componentType, collectionType));
+ if (isCollection) {
+ logger.debug(componentType + " is collection");
+ }
+
+ return isCollection;
+ }
+ }
+}
diff --git a/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/StatementGenerator.java b/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/StatementGenerator.java
new file mode 100644
index 0000000..7ad9f5c
--- /dev/null
+++ b/extensions/immutable-collections/src/main/java/pl/com/labaj/autorecord/extension/compact/StatementGenerator.java
@@ -0,0 +1,91 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import com.squareup.javapoet.CodeBlock;
+import pl.com.labaj.autorecord.context.Logger;
+import pl.com.labaj.autorecord.context.StaticImports;
+
+import javax.annotation.Nullable;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Types;
+import java.util.EnumMap;
+import java.util.Objects;
+
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toMap;
+import static pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension.PROCESSED_TYPES;
+import static pl.com.labaj.autorecord.extension.compact.ProcessedType.allProcessedTypes;
+
+final class StatementGenerator {
+
+ private static final EnumMap RECORD_STATEMENT_GENERATORS = allProcessedTypes().stream()
+ .collect(toMap(
+ identity(),
+ StatementGenerator::builderFor,
+ (b1, b2) -> b1,
+ () -> new EnumMap<>(ProcessedType.class)
+ ));
+
+ private final Types typeUtils;
+ private final ProcessedTypesStructure structure;
+ private final StaticImports staticImports;
+ private final Logger logger;
+
+ StatementGenerator(Types typeUtils,
+ ProcessedTypesStructure structure,
+ StaticImports staticImports, Logger logger) {
+ this.typeUtils = typeUtils;
+ this.structure = structure;
+ this.staticImports = staticImports;
+ this.logger = logger;
+ }
+
+ CodeBlock generateStatement(RecordComponent recordComponent) {
+ var pType = recordComponent.pType();
+ return RECORD_STATEMENT_GENERATORS.get(pType)
+ .generateStatement(typeUtils, PROCESSED_TYPES, recordComponent, staticImports, structure, logger);
+ }
+
+ private static RecordStatementGenerator builderFor(ProcessedType pType) {
+ return (typeUtils, pTypes, component, staticImports, structure, logger) -> {
+ var nullable = component.isNullable();
+ if (nullable) {
+ staticImports.add(Objects.class, "isNull");
+ }
+
+ if (structure.needsAdditionalMethod(pType)) {
+ var format = nullable ? "$1L = isNull($1L) ? null : _$2L($1L)" : "$1L = _$2L($1L)";
+ return CodeBlock.of(format, component.name(), pType.factoryMethodName());
+ }
+
+ var format = nullable ? "$1L = isNull($1L) ? null : $2T.$3L($1L)" : "$1L = $2T.$3L($1L)";
+ return CodeBlock.of(format, component.name(), pType.factoryClassName(), pType.factoryMethodName());
+ };
+ }
+
+ @FunctionalInterface
+ private interface RecordStatementGenerator {
+ @Nullable
+ CodeBlock generateStatement(Types typeUtils,
+ EnumMap pTypes,
+ RecordComponent recordComponent,
+ StaticImports staticImports,
+ ProcessedTypesStructure structure,
+ Logger logger);
+ }
+}
diff --git a/extensions/immutable-collections/src/test/java/pl/com/labaj/autorecord/extension/compact/ImmutableCollectionsExtensionTest.java b/extensions/immutable-collections/src/test/java/pl/com/labaj/autorecord/extension/compact/ImmutableCollectionsExtensionTest.java
new file mode 100644
index 0000000..c873b18
--- /dev/null
+++ b/extensions/immutable-collections/src/test/java/pl/com/labaj/autorecord/extension/compact/ImmutableCollectionsExtensionTest.java
@@ -0,0 +1,158 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import com.google.common.collect.ImmutableSet;
+import com.google.testing.compile.Compiler;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.function.Executable;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import pl.com.labaj.autorecord.AutoRecord;
+import pl.com.labaj.autorecord.processor.AutoRecordProcessor;
+
+import javax.annotation.Nullable;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Stream;
+
+import static com.google.testing.compile.CompilationSubject.assertThat;
+import static com.google.testing.compile.Compiler.javac;
+import static com.google.testing.compile.JavaFileObjects.forResource;
+import static java.util.Objects.isNull;
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toCollection;
+import static java.util.stream.Collectors.toMap;
+import static org.apache.commons.lang3.StringUtils.removeStart;
+import static org.apache.commons.lang3.StringUtils.substringBefore;
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.fail;
+
+class ImmutableCollectionsExtensionTest {
+ private static final String[] NAMES = {
+ "ItemWithObject",
+ "ItemWithListsNoUserDefinedCollections",
+ "ItemWithLists",
+ "ItemWithSetsNoUserDefinedCollections",
+ "ItemWithSets",
+ };
+
+ static Stream names() {
+ return Arrays.stream(NAMES);
+ }
+
+ private Compiler compiler;
+
+ @BeforeEach
+ void setUp() {
+ compiler = javac().withClasspath(prepareClasspath());
+ }
+
+ @ParameterizedTest(name = "{0}.java")
+ @MethodSource("names")
+ void shouldGenerateSingleRecord(String name) {
+ //given
+ var generatedPath = "pl/com/labaj/autorecord/extension/compact/";
+
+ var inputs = List.of(
+ forResource("in/" + name + ".java"),
+ forResource("UserCollections.java")
+ );
+
+ var expectedOutput = forResource("out/" + name + "Record.java");
+
+ //when
+ var compilation = compiler
+ .withProcessors(new AutoRecordProcessor())
+ .compile(inputs);
+
+ //then
+ assertAll(
+ () -> assertThat(compilation).generatedSourceFile(generatedPath + name + "Record")
+ .hasSourceEquivalentTo(expectedOutput),
+ () -> assertThat(compilation).succeeded()
+ );
+ }
+
+ @Test
+ void shouldGenerateCorrectAllRecordsTogether() {
+ //given
+ var generatedPath = "pl/com/labaj/autorecord/extension/compact/";
+
+ var inputs = Arrays.stream(NAMES)
+ .map(name -> forResource("in/" + name + ".java"))
+ .collect(toCollection(ArrayList::new));
+
+ inputs.add(forResource("UserCollections.java"));
+
+ var expectedOutputs = Arrays.stream(NAMES)
+ .collect(toMap(
+ identity(),
+ name -> forResource("out/" + name + "Record.java")
+ ));
+
+ //when
+ var compilation = compiler
+ .withProcessors(new AutoRecordProcessor())
+ .compile(inputs);
+
+ //then
+ var assertions = Arrays.stream(NAMES)
+ .map(name -> (Executable) () -> assertThat(compilation).generatedSourceFile(generatedPath + name + "Record")
+ .hasSourceEquivalentTo(expectedOutputs.get(name)))
+ .collect(toCollection(ArrayList::new));
+
+ assertions.add(() -> assertThat(compilation).succeeded());
+
+ assertAll(assertions);
+ }
+
+ @SuppressWarnings("DataFlowIssue")
+ private static List prepareClasspath() {
+ var autoRecordJar = findClasspathFile(AutoRecord.class);
+ var guavaJar = findClasspathFile(ImmutableSet.class);
+ var nullableJar = findClasspathFile(Nullable.class);
+ var targetClassesFolder = findClasspathFile(ImmutableCollectionsExtension.class);
+
+ return List.of(
+ autoRecordJar,
+ guavaJar,
+ nullableJar,
+ targetClassesFolder
+ );
+ }
+
+ private static File findClasspathFile(Class> aClass) {
+ var url = aClass.getResource(aClass.getSimpleName() + ".class");
+ var fileInFolderWithoutExtension = aClass.getName().replace('.', '/');
+
+ if (isNull(url)) {
+ fail("Cannot get URL for " + aClass.getName());
+ return null;
+ }
+ var path = url.getPath();
+ path = removeStart(path, "jar:");
+ path = removeStart(path, "file:");
+ path = substringBefore(path, fileInFolderWithoutExtension);
+ path = substringBefore(path, "!");
+
+ return new File(path);
+ }
+}
diff --git a/extensions/immutable-collections/src/test/resources/UserCollections.java b/extensions/immutable-collections/src/test/resources/UserCollections.java
new file mode 100644
index 0000000..62ecb75
--- /dev/null
+++ b/extensions/immutable-collections/src/test/resources/UserCollections.java
@@ -0,0 +1,69 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import java.util.AbstractList;
+import java.util.AbstractSet;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NavigableSet;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+class UserCollections {
+
+ interface UserSet extends Set {}
+
+ interface UserNavigableSet extends NavigableSet {}
+
+ interface UserSortedSet extends SortedSet {}
+
+ interface UserList extends List {}
+
+ interface UserMap extends Map {}
+
+ interface UserQueue extends Queue {}
+
+ static class UserSetImpl extends AbstractSet implements UserSet {
+ @Override public Iterator iterator() {return null;}
+ @Override public int size() {return 0;}
+ }
+
+ static class SortedSetImpl extends AbstractSet implements SortedSet {
+ @Override public Iterator iterator() {return null;}
+ @Override public int size() {return 0;}
+ @Override public Comparator super E> comparator() {return null;}
+ @Override public SortedSet subSet(E fromElement, E toElement) {return null;}
+ @Override public SortedSet headSet(E toElement) {return null;}
+ @Override public SortedSet tailSet(E fromElement) {return null;}
+ @Override public E first() {return null;}
+ @Override public E last() {return null;}
+ }
+
+ static class UserSortedSetImpl extends SortedSetImpl implements UserSortedSet {}
+
+ static class UserNavigableSeImpl extends TreeSet implements UserNavigableSet {}
+
+ static class UserListImpl extends AbstractList implements UserList{
+ @Override public E get(int index) {return null;}
+ @Override public int size() {return 0;}
+ }
+}
diff --git a/extensions/immutable-collections/src/test/resources/in/ItemWithLists.java b/extensions/immutable-collections/src/test/resources/in/ItemWithLists.java
new file mode 100644
index 0000000..67d727b
--- /dev/null
+++ b/extensions/immutable-collections/src/test/resources/in/ItemWithLists.java
@@ -0,0 +1,46 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import com.google.common.collect.ImmutableList;
+import pl.com.labaj.autorecord.AutoRecord;
+
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+@AutoRecord
+@AutoRecord.Extension(
+ extensionClass = "pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension",
+ parameters = {
+ "pl.com.labaj.autorecord.extension.compact.UserCollections.UserList"
+ })
+interface ItemWithLists {
+ List list();
+ LinkedList linkedList();
+ ArrayList arrayList();
+ UserCollections.UserList userList();
+ UserCollections.UserListImpl userListImpl();
+ ImmutableList immutableList();
+ @Nullable List nullableList();
+ @Nullable LinkedList nullableLinkedList();
+ @Nullable ArrayList nullableArrayList();
+ @Nullable UserCollections.UserList nullableUserList();
+ @Nullable UserCollections.UserListImpl nullableUserListImpl();
+ @Nullable ImmutableList nullableImmutableList();
+}
diff --git a/extensions/immutable-collections/src/test/resources/in/ItemWithListsNoUserDefinedCollections.java b/extensions/immutable-collections/src/test/resources/in/ItemWithListsNoUserDefinedCollections.java
new file mode 100644
index 0000000..5c01533
--- /dev/null
+++ b/extensions/immutable-collections/src/test/resources/in/ItemWithListsNoUserDefinedCollections.java
@@ -0,0 +1,42 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import com.google.common.collect.ImmutableList;
+import pl.com.labaj.autorecord.AutoRecord;
+
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+@AutoRecord
+@AutoRecord.Extension(extensionClass = "pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension")
+interface ItemWithListsNoUserDefinedCollections {
+ List list();
+ LinkedList linkedList();
+ ArrayList arrayList();
+ UserCollections.UserList userList();
+ UserCollections.UserListImpl userListImpl();
+ ImmutableList immutableList();
+ @Nullable List nullableList();
+ @Nullable LinkedList nullableLinkedList();
+ @Nullable ArrayList nullableArrayList();
+ @Nullable UserCollections.UserList nullableUserList();
+ @Nullable UserCollections.UserListImpl nullableUserListImpl();
+ @Nullable ImmutableList nullableImmutableList();
+}
diff --git a/extensions/immutable-collections/src/test/resources/in/ItemWithObject.java b/extensions/immutable-collections/src/test/resources/in/ItemWithObject.java
new file mode 100644
index 0000000..6852920
--- /dev/null
+++ b/extensions/immutable-collections/src/test/resources/in/ItemWithObject.java
@@ -0,0 +1,28 @@
+
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+import pl.com.labaj.autorecord.AutoRecord;
+
+import javax.annotation.Nullable;
+
+@AutoRecord
+@AutoRecord.Extension(extensionClass = "pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension")
+interface ItemWithObject {
+ Object object();
+ @Nullable Object nullableObject();
+}
\ No newline at end of file
diff --git a/extensions/immutable-collections/src/test/resources/in/ItemWithSets.java b/extensions/immutable-collections/src/test/resources/in/ItemWithSets.java
new file mode 100644
index 0000000..1674aef
--- /dev/null
+++ b/extensions/immutable-collections/src/test/resources/in/ItemWithSets.java
@@ -0,0 +1,67 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import com.google.common.collect.ImmutableSet;
+import pl.com.labaj.autorecord.AutoRecord;
+
+import javax.annotation.Nullable;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.NavigableSet;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+@AutoRecord
+@AutoRecord.Extension(
+ extensionClass = "pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension",
+ parameters = {
+ "pl.com.labaj.autorecord.extension.compact.UserCollections.UserSet",
+ "pl.com.labaj.autorecord.extension.compact.UserCollections.UserSortedSet",
+ "pl.com.labaj.autorecord.extension.compact.UserCollections.UserNavigableSet"
+ })
+interface ItemWithSets {
+ Set set();
+ HashSet hashSet();
+ LinkedHashSet linkedHashSet();
+ SortedSet sortedSet();
+ UserCollections.SortedSetImpl sortedSetImpl();
+ NavigableSet navigableSet();
+ TreeSet treeSet();
+ UserCollections.UserSet userSet();
+ UserCollections.UserSetImpl userSetImpl();
+ UserCollections.UserSortedSet userSortedSet();
+ UserCollections.UserSortedSetImpl userSortedSetImpl();
+ UserCollections.UserNavigableSet userNavigableSet();
+ UserCollections.UserNavigableSeImpl userNavigableSetImpl();
+ ImmutableSet immutableSet();
+ @Nullable Set nullableSet();
+ @Nullable HashSet nullableHashSet();
+ @Nullable LinkedHashSet nullableLinkedHashSet();
+ @Nullable SortedSet nullableSortedSet();
+ @Nullable UserCollections.SortedSetImpl nullableSortedSetImpl();
+ @Nullable NavigableSet nullableNavigableSet();
+ @Nullable TreeSet nullableTreeSet();
+ @Nullable UserCollections.UserSet nullableUserSet();
+ @Nullable UserCollections.UserSetImpl nullableUserSetImpl();
+ @Nullable UserCollections.UserSortedSet nullableUserSortedSet();
+ @Nullable UserCollections.UserSortedSetImpl nullableUserSortedSetImpl();
+ @Nullable UserCollections.UserNavigableSet nullableUserNavigableSet();
+ @Nullable UserCollections.UserNavigableSeImpl nullableUserNavigableSetImpl();
+ @Nullable ImmutableSet nullableImmutableSet();
+}
diff --git a/extensions/immutable-collections/src/test/resources/in/ItemWithSetsNoUserDefinedCollections.java b/extensions/immutable-collections/src/test/resources/in/ItemWithSetsNoUserDefinedCollections.java
new file mode 100644
index 0000000..3d50cb1
--- /dev/null
+++ b/extensions/immutable-collections/src/test/resources/in/ItemWithSetsNoUserDefinedCollections.java
@@ -0,0 +1,61 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import com.google.common.collect.ImmutableSet;
+import pl.com.labaj.autorecord.AutoRecord;
+
+import javax.annotation.Nullable;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.NavigableSet;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+@AutoRecord
+@AutoRecord.Extension(extensionClass = "pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension")
+interface ItemWithSetsNoUserDefinedCollections> {
+ Set set();
+ HashSet hashSet();
+ LinkedHashSet linkedHashSet();
+ SortedSet sortedSet();
+ UserCollections.SortedSetImpl sortedSetImpl();
+ NavigableSet navigableSet();
+ TreeSet treeSet();
+ UserCollections.UserSet userSet();
+ UserCollections.UserSetImpl userSetImpl();
+ UserCollections.UserSortedSet userSortedSet();
+ UserCollections.UserSortedSetImpl userSortedSetImpl();
+ UserCollections.UserNavigableSet userNavigableSet();
+ UserCollections.UserNavigableSeImpl userNavigableSetImpl();
+ ImmutableSet immutableSet();
+ @Nullable Set nullableSet();
+ @Nullable HashSet nullableHashSet();
+ @Nullable LinkedHashSet nullableLinkedHashSet();
+ @Nullable SortedSet nullableSortedSet();
+ @Nullable UserCollections.SortedSetImpl nullableSortedSetImpl();
+ @Nullable NavigableSet nullableNavigableSet();
+ @Nullable TreeSet nullableTreeSet();
+ @Nullable UserCollections.UserSet nullableUserSet();
+ @Nullable UserCollections.UserSetImpl nullableUserSetImpl();
+ @Nullable UserCollections.UserSortedSet nullableUserSortedSet();
+ @Nullable UserCollections.UserSortedSetImpl nullableUserSortedSetImpl();
+ @Nullable UserCollections.UserNavigableSet nullableUserNavigableSet();
+ @Nullable UserCollections.UserNavigableSeImpl nullableUserNavigableSetImpl();
+ @Nullable ImmutableSet nullableImmutableSet();
+}
diff --git a/extensions/immutable-collections/src/test/resources/out/ItemWithListsNoUserDefinedCollectionsRecord.java b/extensions/immutable-collections/src/test/resources/out/ItemWithListsNoUserDefinedCollectionsRecord.java
new file mode 100644
index 0000000..7da2e97
--- /dev/null
+++ b/extensions/immutable-collections/src/test/resources/out/ItemWithListsNoUserDefinedCollectionsRecord.java
@@ -0,0 +1,65 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import static java.util.Objects.isNull;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import javax.annotation.Nullable;
+import javax.annotation.processing.Generated;
+import pl.com.labaj.autorecord.GeneratedWithAutoRecord;
+
+@Generated("pl.com.labaj.autorecord.AutoRecord")
+@GeneratedWithAutoRecord
+record ItemWithListsNoUserDefinedCollectionsRecord(List list,
+ LinkedList linkedList,
+ ArrayList arrayList,
+ UserCollections.UserList userList,
+ UserCollections.UserListImpl userListImpl,
+ ImmutableList immutableList,
+ @Nullable List nullableList,
+ @Nullable LinkedList nullableLinkedList,
+ @Nullable ArrayList nullableArrayList,
+ @Nullable UserCollections.UserList nullableUserList,
+ @Nullable UserCollections.UserListImpl nullableUserListImpl,
+ @Nullable ImmutableList nullableImmutableList) implements ItemWithListsNoUserDefinedCollections {
+ ItemWithListsNoUserDefinedCollectionsRecord {
+ // pl.com.labaj.autorecord.processor.AutoRecordProcessor
+ requireNonNull(list, "list must not be null");
+ requireNonNull(linkedList, "linkedList must not be null");
+ requireNonNull(arrayList, "arrayList must not be null");
+ requireNonNull(userList, "userList must not be null");
+ requireNonNull(userListImpl, "userListImpl must not be null");
+ requireNonNull(immutableList, "immutableList must not be null");
+
+ // pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension
+ list = _copyOf(list);
+ nullableList = isNull(nullableList) ? null : _copyOf(nullableList);
+ }
+
+ @Generated("pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension")
+ private static List _copyOf(List list) {
+ if (list instanceof ImmutableList) {
+ return list;
+ }
+ return ImmutableList.copyOf(list);
+ }
+}
\ No newline at end of file
diff --git a/extensions/immutable-collections/src/test/resources/out/ItemWithListsRecord.java b/extensions/immutable-collections/src/test/resources/out/ItemWithListsRecord.java
new file mode 100644
index 0000000..2d489ac
--- /dev/null
+++ b/extensions/immutable-collections/src/test/resources/out/ItemWithListsRecord.java
@@ -0,0 +1,66 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import static java.util.Objects.isNull;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import javax.annotation.Nullable;
+import javax.annotation.processing.Generated;
+import pl.com.labaj.autorecord.GeneratedWithAutoRecord;
+
+@Generated("pl.com.labaj.autorecord.AutoRecord")
+@GeneratedWithAutoRecord
+record ItemWithListsRecord(List list,
+ LinkedList linkedList,
+ ArrayList arrayList,
+ UserCollections.UserList userList,
+ UserCollections.UserListImpl userListImpl,
+ ImmutableList immutableList,
+ @Nullable List nullableList,
+ @Nullable LinkedList nullableLinkedList,
+ @Nullable ArrayList nullableArrayList,
+ @Nullable UserCollections.UserList nullableUserList,
+ @Nullable UserCollections.UserListImpl nullableUserListImpl,
+ @Nullable ImmutableList nullableImmutableList) implements ItemWithLists {
+ ItemWithListsRecord {
+ // pl.com.labaj.autorecord.processor.AutoRecordProcessor
+ requireNonNull(list, "list must not be null");
+ requireNonNull(linkedList, "linkedList must not be null");
+ requireNonNull(arrayList, "arrayList must not be null");
+ requireNonNull(userList, "userList must not be null");
+ requireNonNull(userListImpl, "userListImpl must not be null");
+ requireNonNull(immutableList, "immutableList must not be null");
+
+ // pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension
+ list = _copyOf(list);
+ nullableList = isNull(nullableList) ? null : _copyOf(nullableList);
+ }
+
+ @Generated("pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension")
+ private static List _copyOf(List list) {
+ if (list instanceof ImmutableList
+ || list instanceof UserCollections.UserList) {
+ return list;
+ }
+ return ImmutableList.copyOf(list);
+ }
+}
\ No newline at end of file
diff --git a/extensions/immutable-collections/src/test/resources/out/ItemWithObjectRecord.java b/extensions/immutable-collections/src/test/resources/out/ItemWithObjectRecord.java
new file mode 100644
index 0000000..73df502
--- /dev/null
+++ b/extensions/immutable-collections/src/test/resources/out/ItemWithObjectRecord.java
@@ -0,0 +1,105 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import static java.util.Objects.isNull;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSortedSet;
+import java.lang.Object;
+import java.util.List;
+import java.util.Map;
+import java.util.NavigableSet;
+import java.util.Set;
+import java.util.SortedSet;
+import javax.annotation.Nullable;
+import javax.annotation.processing.Generated;
+import pl.com.labaj.autorecord.GeneratedWithAutoRecord;
+
+@Generated("pl.com.labaj.autorecord.AutoRecord")
+@GeneratedWithAutoRecord
+record ItemWithObjectRecord(Object object, @Nullable Object nullableObject) implements ItemWithObject {
+ ItemWithObjectRecord {
+ // pl.com.labaj.autorecord.processor.AutoRecordProcessor
+ requireNonNull(object, "object must not be null");
+
+ // pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension
+ object = _copyOfObject(object);
+ nullableObject = isNull(nullableObject) ? null : _copyOfObject(nullableObject);
+ }
+
+ @Generated("pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension")
+ private static Object _copyOfObject(Object object) {
+ if (object instanceof Set set) {
+ return _copyOf(set);
+ }
+ if (object instanceof List list) {
+ return _copyOf(list);
+ }
+ if (object instanceof Map map) {
+ return _copyOf(map);
+ }
+ return object;
+ }
+
+ @Generated("pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension")
+ private static Set _copyOf(Set set) {
+ if (set instanceof ImmutableSet) {
+ return set;
+ }
+ if (set instanceof SortedSet sortedSet) {
+ return _copyOfSorted(sortedSet);
+ }
+ return ImmutableSet.copyOf(set);
+ }
+
+ @Generated("pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension")
+ private static SortedSet _copyOfSorted(SortedSet sortedSet) {
+ if (sortedSet instanceof NavigableSet navigableSet) {
+ return _copyOfSorted(navigableSet);
+ }
+ return ImmutableSortedSet.copyOfSorted(sortedSet);
+ }
+
+ @Generated("pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension")
+ private static NavigableSet _copyOfSorted(NavigableSet navigableSet) {
+ if (navigableSet instanceof ImmutableSortedSet) {
+ return navigableSet;
+ }
+ return ImmutableSortedSet.copyOfSorted(navigableSet);
+ }
+
+ @Generated("pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension")
+ private static List _copyOf(List list) {
+ if (list instanceof ImmutableList) {
+ return list;
+ }
+ return ImmutableList.copyOf(list);
+ }
+
+ @Generated("pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension")
+ private static Map _copyOf(Map map) {
+ if (map instanceof ImmutableMap) {
+ return map;
+ }
+ return ImmutableMap.copyOf(map);
+ }
+
+}
\ No newline at end of file
diff --git a/extensions/immutable-collections/src/test/resources/out/ItemWithSetsNoUserDefinedCollectionsRecord.java b/extensions/immutable-collections/src/test/resources/out/ItemWithSetsNoUserDefinedCollectionsRecord.java
new file mode 100644
index 0000000..d993576
--- /dev/null
+++ b/extensions/immutable-collections/src/test/resources/out/ItemWithSetsNoUserDefinedCollectionsRecord.java
@@ -0,0 +1,117 @@
+package pl.com.labaj.autorecord.extension.compact;
+
+/*-
+ * Copyright © 2023 Auto Record
+ *
+ * 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.
+ */
+
+import static java.util.Objects.isNull;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSortedSet;
+import java.lang.Enum;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.NavigableSet;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import javax.annotation.Nullable;
+import javax.annotation.processing.Generated;
+import pl.com.labaj.autorecord.GeneratedWithAutoRecord;
+
+@Generated("pl.com.labaj.autorecord.AutoRecord")
+@GeneratedWithAutoRecord
+record ItemWithSetsNoUserDefinedCollectionsRecord>(Set set,
+ HashSet hashSet,
+ LinkedHashSet linkedHashSet,
+ SortedSet sortedSet,
+ UserCollections.SortedSetImpl sortedSetImpl,
+ NavigableSet navigableSet,
+ TreeSet treeSet,
+ UserCollections.UserSet userSet,
+ UserCollections.UserSetImpl userSetImpl,
+ UserCollections.UserSortedSet userSortedSet,
+ UserCollections.UserSortedSetImpl userSortedSetImpl,
+ UserCollections.UserNavigableSet userNavigableSet,
+ UserCollections.UserNavigableSeImpl userNavigableSetImpl,
+ ImmutableSet immutableSet,
+ @Nullable Set nullableSet,
+ @Nullable HashSet nullableHashSet,
+ @Nullable LinkedHashSet nullableLinkedHashSet,
+ @Nullable SortedSet nullableSortedSet,
+ @Nullable UserCollections.SortedSetImpl nullableSortedSetImpl,
+ @Nullable NavigableSet nullableNavigableSet,
+ @Nullable TreeSet nullableTreeSet,
+ @Nullable UserCollections.UserSet nullableUserSet,
+ @Nullable UserCollections.UserSetImpl nullableUserSetImpl,
+ @Nullable UserCollections.UserSortedSet nullableUserSortedSet,
+ @Nullable UserCollections.UserSortedSetImpl nullableUserSortedSetImpl,
+ @Nullable UserCollections.UserNavigableSet nullableUserNavigableSet,
+ @Nullable UserCollections.UserNavigableSeImpl nullableUserNavigableSetImpl,
+ @Nullable ImmutableSet nullableImmutableSet) implements ItemWithSetsNoUserDefinedCollections {
+ ItemWithSetsNoUserDefinedCollectionsRecord {
+ // pl.com.labaj.autorecord.processor.AutoRecordProcessor
+ requireNonNull(set, "set must not be null");
+ requireNonNull(hashSet, "hashSet must not be null");
+ requireNonNull(linkedHashSet, "linkedHashSet must not be null");
+ requireNonNull(sortedSet, "sortedSet must not be null");
+ requireNonNull(sortedSetImpl, "sortedSetImpl must not be null");
+ requireNonNull(navigableSet, "navigableSet must not be null");
+ requireNonNull(treeSet, "treeSet must not be null");
+ requireNonNull(userSet, "userSet must not be null");
+ requireNonNull(userSetImpl, "userSetImpl must not be null");
+ requireNonNull(userSortedSet, "userSortedSet must not be null");
+ requireNonNull(userSortedSetImpl, "userSortedSetImpl must not be null");
+ requireNonNull(userNavigableSet, "userNavigableSet must not be null");
+ requireNonNull(userNavigableSetImpl, "userNavigableSetImpl must not be null");
+ requireNonNull(immutableSet, "immutableSet must not be null");
+
+ // pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension
+ set = _copyOf(set);
+ sortedSet = _copyOfSorted(sortedSet);
+ navigableSet = _copyOfSorted(navigableSet);
+ nullableSet = isNull(nullableSet) ? null : _copyOf(nullableSet);
+ nullableSortedSet = isNull(nullableSortedSet) ? null : _copyOfSorted(nullableSortedSet);
+ nullableNavigableSet = isNull(nullableNavigableSet) ? null : _copyOfSorted(nullableNavigableSet);
+ }
+
+ @Generated("pl.com.labaj.autorecord.extension.compact.ImmutableCollectionsExtension")
+ private static Set _copyOf(Set set) {
+ if (set instanceof ImmutableSet