diff --git a/example-custom-generator/src/main/java/org/javahelpers/simple/builders/example/custom/StringValidationGenerator.java b/example-custom-generator/src/main/java/org/javahelpers/simple/builders/example/custom/StringValidationGenerator.java index 2e523ec7..ef197823 100644 --- a/example-custom-generator/src/main/java/org/javahelpers/simple/builders/example/custom/StringValidationGenerator.java +++ b/example-custom-generator/src/main/java/org/javahelpers/simple/builders/example/custom/StringValidationGenerator.java @@ -29,6 +29,7 @@ import org.javahelpers.simple.builders.processor.model.core.FieldDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; import org.javahelpers.simple.builders.processor.model.type.TypeName; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.generators.MethodGenerator; import org.javahelpers.simple.builders.processor.processing.ProcessingContext; @@ -81,10 +82,9 @@ public List generateMethods(FieldDto field, TypeName builderType, Pro MethodDto validationMethod = new MethodDto(methodName, builderType); validationMethod.setCode(methodBody); validationMethod.setJavadoc( - "Validates that the " + fieldInDto + " field is not null or empty.\n" + - "\n" + - "@return this builder instance for chaining\n" + - "@throws IllegalArgumentException if " + fieldInDto + " is null or empty" + new JavadocDto("Validates that the " + fieldInDto + " field is not null or empty.") + .addReturn("this builder instance for chaining") + .addThrows("IllegalArgumentException", "if " + fieldInDto + " is null or empty") ); return List.of(validationMethod); diff --git a/pom.xml b/pom.xml index 6cb6588f..1be6fd76 100644 --- a/pom.xml +++ b/pom.xml @@ -77,7 +77,7 @@ ${project.basedir}/core/target/site/jacoco/jacoco.xml,${project.basedir}/processor/target/site/jacoco/jacoco.xml **/example/** - **/*Mapper*.java,**/processor/dtos/**,**/generated/** + **/*Mapper*.java,**/processor/model/**,**/processor/exceptions/**,**/generated/** 3.13.0 diff --git a/processor/pom.xml b/processor/pom.xml index 38788390..9faa92f6 100644 --- a/processor/pom.xml +++ b/processor/pom.xml @@ -329,8 +329,8 @@ **/*Mapper*.class - - **/processor/dtos/** + + **/processor/model/** **/processor/exceptions/** diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/classgen/roaster/RoasterCodeGenerator.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/classgen/roaster/RoasterCodeGenerator.java index bd86c0f0..4360b33e 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/classgen/roaster/RoasterCodeGenerator.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/classgen/roaster/RoasterCodeGenerator.java @@ -55,6 +55,8 @@ import org.javahelpers.simple.builders.processor.model.core.FieldDto; import org.javahelpers.simple.builders.processor.model.integration.JacksonModuleDefinitionDto; import org.javahelpers.simple.builders.processor.model.integration.JacksonModuleEntryDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocTagDto; import org.javahelpers.simple.builders.processor.model.method.MethodCodePlaceholder; import org.javahelpers.simple.builders.processor.model.method.MethodCodeTypePlaceholder; import org.javahelpers.simple.builders.processor.model.method.MethodDto; @@ -207,11 +209,10 @@ private void appendField(JavaClassSource source, FieldDto fieldDto) { } private void applyJavaDocToField(JavaDocSource javaDoc, FieldDto fieldDto) { - javaDoc.setText( - "Tracked value for %s: %s." - .formatted( - fieldDto.getFieldNameInBuilder(), - StringUtils.defaultString(fieldDto.getJavaDoc()))); + JavadocDto trackedValueJavadoc = fieldDto.getJavaDoc(); + if (trackedValueJavadoc != null) { + javaDoc.setText(trackedValueJavadoc.getDescription()); + } } private void appendConstructors(JavaClassSource source, BuilderDefinitionDto builderDef) { @@ -234,7 +235,8 @@ private void appendEmptyConstructor( constructor.setBody(""); applyJavadoc( constructor, - "Empty constructor of builder for {@code %s}.".formatted(dtoClass.getFullQualifiedName())); + new JavadocDto( + "Empty constructor of builder for {@code %s}.", dtoClass.getFullQualifiedName())); } private void appendConstructorWithInstance( @@ -249,12 +251,10 @@ private void appendConstructorWithInstance( constructor.setBody(buildConstructorBody(fields)); applyJavadoc( constructor, - """ - Initialisation of builder for {@code %s} by a instance. - - @param instance object instance for initialisiation - """ - .formatted(dtoBaseClass.getFullQualifiedName())); + new JavadocDto( + "Initialisation of builder for {@code %s} by a instance.", + dtoBaseClass.getFullQualifiedName()) + .addParam("instance", "object instance for initialisiation")); } private String buildConstructorBody(List fields) { @@ -490,44 +490,29 @@ private void addGenericDeclarations( } private void applyJavadoc( - org.jboss.forge.roaster.model.source.JavaDocCapableSource source, String javadoc) { - if (StringUtils.isBlank(javadoc)) { + org.jboss.forge.roaster.model.source.JavaDocCapableSource source, JavadocDto javadoc) { + if (javadoc == null || !javadoc.hasContent()) { return; } - // Normalize line endings without regex to avoid ReDoS vulnerability - String normalized = javadoc.replace("\r\n", "\n").replace("\r", "\n"); - // Remove trailing newlines using StringUtils - normalized = StringUtils.stripEnd(normalized, "\n"); - String[] lines = normalized.split("\n", -1); - StringBuilder text = new StringBuilder(); + + // Note: source.getJavaDoc() never returns null - Roaster creates the JavaDoc if it doesn't + // exist + // The early return above ensures we only create JavaDoc when there's actual content to set + + // Set description text + if (StringUtils.isNotBlank(javadoc.getDescription())) { + source.getJavaDoc().setText(javadoc.getDescription()); + } + + // Remove existing tags and add new ones source.getJavaDoc().removeAllTags(); - boolean inTags = false; - for (String line : lines) { - if (!inTags && line.startsWith("@")) { - inTags = true; - } - if (inTags && line.startsWith("@")) { - processJavadocTag(source, line); + for (JavadocTagDto tag : javadoc.getTags()) { + if (tag.hasValue()) { + source.getJavaDoc().addTagValue(tag.getFullTagName(), tag.tagValue()); } else { - if (!text.isEmpty()) { - text.append('\n'); - } - text.append(line); + source.getJavaDoc().addTagValue(tag.getFullTagName(), ""); } } - source.getJavaDoc().setText(text.toString()); - } - - private void processJavadocTag( - org.jboss.forge.roaster.model.source.JavaDocCapableSource source, String line) { - int firstSpace = line.indexOf(' '); - if (firstSpace > 1) { - source - .getJavaDoc() - .addTagValue(line.substring(0, firstSpace), line.substring(firstSpace + 1)); - } else if (line.length() > 1) { - source.getJavaDoc().addTagValue(line, ""); - } } private void applyAnnotations( diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/ClassJavaDocEnhancer.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/ClassJavaDocEnhancer.java index a25a3d25..71ae20f9 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/ClassJavaDocEnhancer.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/ClassJavaDocEnhancer.java @@ -26,6 +26,7 @@ import org.javahelpers.simple.builders.processor.generators.BuilderEnhancer; import org.javahelpers.simple.builders.processor.model.core.BuilderDefinitionDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.type.TypeName; import org.javahelpers.simple.builders.processor.processing.ProcessingContext; @@ -86,7 +87,7 @@ public boolean appliesTo( @Override public void enhanceBuilder(BuilderDefinitionDto builderDto, ProcessingContext context) { TypeName targetType = builderDto.getBuildingTargetTypeName(); - String javadoc = createClassJavadoc(targetType); + JavadocDto javadoc = createClassJavadoc(targetType); builderDto.setClassJavadoc(javadoc); } @@ -94,18 +95,18 @@ public void enhanceBuilder(BuilderDefinitionDto builderDto, ProcessingContext co * Creates comprehensive JavaDoc for the builder class. * * @param targetType the target DTO type - * @return String containing the JavaDoc content + * @return JavadocDto containing the JavaDoc content */ - private String createClassJavadoc(TypeName targetType) { + private JavadocDto createClassJavadoc(TypeName targetType) { String qualifiedClassName = targetType.getFullQualifiedName(); - return String.format( + return new JavadocDto( """ Builder for {@code %s}.

This builder provides a fluent API for creating instances of %s with method chaining and validation. Use the static {@code create()} method to obtain a new builder instance, configure the desired properties using - the setter methods, and then call {@code build()} to create the final DTO. + the setter methods, and then call {@code build()} to create the final DTO.\ """, qualifiedClassName, qualifiedClassName); } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/ConditionalEnhancer.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/ConditionalEnhancer.java index 94dfac35..59267d1f 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/ConditionalEnhancer.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/ConditionalEnhancer.java @@ -29,6 +29,7 @@ import org.javahelpers.simple.builders.processor.generators.BuilderEnhancer; import org.javahelpers.simple.builders.processor.generators.util.MethodGeneratorUtil; import org.javahelpers.simple.builders.processor.model.core.BuilderDefinitionDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; import org.javahelpers.simple.builders.processor.model.method.MethodParameterDto; import org.javahelpers.simple.builders.processor.model.type.TypeName; @@ -135,14 +136,12 @@ private MethodDto createConditionalMethod(BuilderDefinitionDto builderDto) { """); method.setJavadoc( - """ - Conditionally applies builder modifications based on a condition evaluation. - - @param condition the condition to evaluate - @param trueCase the consumer to apply if condition is true - @param falseCase the consumer to apply if condition is false (can be null) - @return this builder instance - """); + new JavadocDto( + "Conditionally applies builder modifications based on a condition evaluation.") + .addParam("condition", "the condition to evaluate") + .addParam("trueCase", "the consumer to apply if condition is true") + .addParam("falseCase", "the consumer to apply if condition is false (can be null)") + .addReturn("this builder instance")); return method; } @@ -161,13 +160,10 @@ private MethodDto createConditionalPositiveOnlyMethod(BuilderDefinitionDto build method.setCode("return conditional(condition, yesCondition, null);"); method.setJavadoc( - """ - Conditionally applies builder modifications if the condition is true. - - @param condition the condition to evaluate - @param yesCondition the consumer to apply if condition is true - @return this builder instance - """); + new JavadocDto("Conditionally applies builder modifications if the condition is true.") + .addParam("condition", "the condition to evaluate") + .addParam("yesCondition", "the consumer to apply if condition is true") + .addReturn("this builder instance")); return method; } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/CoreMethodsEnhancer.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/CoreMethodsEnhancer.java index 6bfa592d..c7aeef7b 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/CoreMethodsEnhancer.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/CoreMethodsEnhancer.java @@ -32,6 +32,7 @@ import org.javahelpers.simple.builders.processor.model.annotation.AnnotationDto; import org.javahelpers.simple.builders.processor.model.core.BuilderDefinitionDto; import org.javahelpers.simple.builders.processor.model.core.FieldDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; import org.javahelpers.simple.builders.processor.model.type.GenericParameterDto; import org.javahelpers.simple.builders.processor.model.type.TypeName; @@ -193,7 +194,7 @@ protected MethodDto createBuildMethod(BuilderDefinitionDto builderDto) { method.addArgument("dtoBaseType", builderDto.getBuildingTargetTypeName()); method.addArgument("buildResultType", returnType); - method.setJavadoc("Builds the configured DTO instance."); + method.setJavadoc(new JavadocDto("Builds the configured DTO instance.")); return method; } @@ -226,12 +227,8 @@ protected MethodDto createStaticCreateMethod(BuilderDefinitionDto builderDto) { String targetFullName = builderDto.getBuildingTargetTypeName().getFullQualifiedName(); method.setJavadoc( - """ - Creating a new builder for {@code %s}. - - @return builder for {@code %s} - """ - .formatted(targetFullName, targetFullName)); + new JavadocDto("Creating a new builder for {@code %s}.", targetFullName) + .addReturn("builder for {@code %s}", targetFullName)); return method; } @@ -260,11 +257,9 @@ protected MethodDto createToStringMethod(BuilderDefinitionDto builderDto) { new TypeName("org.javahelpers.simple.builders.core.util", "BuilderToStringStyle")); method.setJavadoc( - """ - Returns a string representation of this builder, including only fields that have been set. - - @return string representation of the builder - """); + new JavadocDto( + "Returns a string representation of this builder, including only fields that have been set.") + .addReturn("string representation of the builder")); return method; } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/WithInterfaceEnhancer.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/WithInterfaceEnhancer.java index ba685b23..545472fd 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/WithInterfaceEnhancer.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/builder/WithInterfaceEnhancer.java @@ -27,6 +27,7 @@ import org.javahelpers.simple.builders.processor.generators.BuilderEnhancer; import org.javahelpers.simple.builders.processor.generators.util.MethodGeneratorUtil; import org.javahelpers.simple.builders.processor.model.core.BuilderDefinitionDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; import org.javahelpers.simple.builders.processor.model.method.MethodParameterDto; import org.javahelpers.simple.builders.processor.model.type.NestedTypeDto; @@ -114,7 +115,8 @@ private NestedTypeDto createWithInterface(BuilderDefinitionDto builderDto) { withInterface.setKind(NestedTypeDto.NestedTypeKind.INTERFACE); withInterface.setPublic(true); withInterface.setJavadoc( - "Interface that can be implemented by the DTO to provide fluent modification methods."); + new JavadocDto( + "Interface that can be implemented by the DTO to provide fluent modification methods.")); // Create the first method: DtoType with(Consumer b) MethodDto withConsumerMethod = createWithConsumerMethod(builderDto); @@ -166,12 +168,10 @@ private MethodDto createWithConsumerMethod(BuilderDefinitionDto builderDef) { "illegalargumentexception", JavaLangMapper.map2TypeName(IllegalArgumentException.class)); method.setJavadoc( - """ - Initializes a builder from an instance of this class, using methods of this builder to change values and returns the new built object. - - @param b the consumer to apply modifications - @return the modified instance - """); + new JavadocDto( + "Initializes a builder from an instance of this class, using methods of this builder to change values and returns the new built object.") + .addParam("b", "the consumer to apply modifications") + .addReturn("the modified instance")); return method; } @@ -202,11 +202,8 @@ private MethodDto createWithBuilderMethod(BuilderDefinitionDto builderDef) { "illegalargumentexception", JavaLangMapper.map2TypeName(IllegalArgumentException.class)); method.setJavadoc( - """ - Creates a builder initialized from this instance. - - @return a builder initialized with this instance's values - """); + new JavadocDto("Creates a builder initialized from this instance.") + .addReturn("a builder initialized with this instance's values")); return method; } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/AddToCollectionGenerator.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/AddToCollectionGenerator.java index 493387b7..3d91e0d9 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/AddToCollectionGenerator.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/AddToCollectionGenerator.java @@ -30,7 +30,9 @@ import java.util.List; import org.apache.commons.lang3.StringUtils; import org.javahelpers.simple.builders.processor.generators.MethodGenerator; +import org.javahelpers.simple.builders.processor.generators.util.JavadocConstants; import org.javahelpers.simple.builders.processor.model.core.FieldDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; import org.javahelpers.simple.builders.processor.model.method.MethodParameterDto; import org.javahelpers.simple.builders.processor.model.type.TypeName; @@ -178,13 +180,9 @@ private MethodDto createAddToCollectionMethod( methodDto.setPriority(MethodDto.PRIORITY_MEDIUM); methodDto.setJavadoc( - """ - Adds a single element to %s. - - @param element the element to add - @return current instance of builder - """ - .formatted(originalFieldName)); + new JavadocDto("Adds a single element to %s.", originalFieldName) + .addParam("element", "the element to add") + .addReturn(JavadocConstants.RETURN_BUILDER_INSTANCE)); return methodDto; } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/ArrayBuilderConsumerGenerator.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/ArrayBuilderConsumerGenerator.java index df492715..02f59310 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/ArrayBuilderConsumerGenerator.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/ArrayBuilderConsumerGenerator.java @@ -30,7 +30,9 @@ import java.util.List; import org.javahelpers.simple.builders.core.builders.ArrayListBuilder; import org.javahelpers.simple.builders.processor.generators.MethodGenerator; +import org.javahelpers.simple.builders.processor.generators.util.JavadocConstants; import org.javahelpers.simple.builders.processor.model.core.FieldDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; import org.javahelpers.simple.builders.processor.model.method.MethodParameterDto; import org.javahelpers.simple.builders.processor.model.type.TypeName; @@ -145,13 +147,10 @@ private MethodDto createFieldConsumerWithArrayBuilder( methodDto.addArgument("elementType", elementType); methodDto.setPriority(MethodDto.PRIORITY_MEDIUM); methodDto.setJavadoc( - """ - Sets the value for %s using the fluent builder consumer. - - @param %s consumer for %s - @return current instance of builder - """ - .formatted(fieldName, parameter.getParameterName(), field.getJavaDoc())); + new JavadocDto( + "Sets the value for %s using the fluent builder consumer.", fieldName) + .addParam(parameter.getParameterName(), "consumer for %s", fieldName) + .addReturn(JavadocConstants.RETURN_BUILDER_INSTANCE)); return methodDto; } } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/ArrayConversionGenerator.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/ArrayConversionGenerator.java index d045d9a8..927f06c7 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/ArrayConversionGenerator.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/ArrayConversionGenerator.java @@ -29,7 +29,9 @@ import java.util.List; import org.javahelpers.simple.builders.processor.generators.MethodGenerator; +import org.javahelpers.simple.builders.processor.generators.util.JavadocConstants; import org.javahelpers.simple.builders.processor.model.core.FieldDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; import org.javahelpers.simple.builders.processor.model.method.MethodParameterDto; import org.javahelpers.simple.builders.processor.model.type.TypeName; @@ -128,14 +130,11 @@ private MethodDto createFieldSetterForArrayFromList( methodDto.addArgument("builderFieldWrapper", TRACKED_VALUE_TYPE); methodDto.addArgument("elementType", elementType); methodDto.setPriority(MethodDto.PRIORITY_HIGH); + String fieldJavadocDesc = field.getJavaDocDescriptionOrFieldName(); methodDto.setJavadoc( - """ - Sets the value for %s. - - @param %s %s - @return current instance of builder - """ - .formatted(fieldName, parameter.getParameterName(), field.getJavaDoc())); + new JavadocDto("Sets the value for %s.", fieldName) + .addParam(parameter.getParameterName(), fieldJavadocDesc) + .addReturn(JavadocConstants.RETURN_BUILDER_INSTANCE)); return methodDto; } } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/StringBuilderConsumerGenerator.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/StringBuilderConsumerGenerator.java index 207afb19..7735031f 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/StringBuilderConsumerGenerator.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/StringBuilderConsumerGenerator.java @@ -30,7 +30,9 @@ import java.util.List; import org.javahelpers.simple.builders.processor.generators.MethodGenerator; +import org.javahelpers.simple.builders.processor.generators.util.JavadocConstants; import org.javahelpers.simple.builders.processor.model.core.FieldDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; import org.javahelpers.simple.builders.processor.model.method.MethodParameterDto; import org.javahelpers.simple.builders.processor.model.type.TypeName; @@ -112,7 +114,7 @@ public List generateMethods( createStringBuilderConsumer( field.getOriginalFieldName(), field.getFieldNameInBuilder(), - field.getJavaDoc(), + field.getJavaDocDescriptionOrFieldName(), transform, builderType, context); @@ -148,13 +150,11 @@ private MethodDto createStringBuilderConsumer( methodDto.setReturnType(builderType); methodDto.setPriority(MethodDto.PRIORITY_LOW); methodDto.setJavadoc( - """ - Sets the value for %s by executing the provided consumer. - - @param %s consumer providing an instance of %s - @return current instance of builder - """ - .formatted(fieldName, parameter.getParameterName(), fieldJavadoc)); + new JavadocDto( + "Sets the value for %s by executing the provided consumer.", fieldName) + .addParam( + parameter.getParameterName(), "consumer providing an instance of %s", fieldJavadoc) + .addReturn(JavadocConstants.RETURN_BUILDER_INSTANCE)); return methodDto; } } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/StringFormatHelperGenerator.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/StringFormatHelperGenerator.java index 17a538df..b6182c0b 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/StringFormatHelperGenerator.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/StringFormatHelperGenerator.java @@ -33,8 +33,10 @@ import java.util.List; import org.apache.commons.collections4.CollectionUtils; import org.javahelpers.simple.builders.processor.generators.MethodGenerator; +import org.javahelpers.simple.builders.processor.generators.util.JavadocConstants; import org.javahelpers.simple.builders.processor.model.annotation.AnnotationDto; import org.javahelpers.simple.builders.processor.model.core.FieldDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; import org.javahelpers.simple.builders.processor.model.method.MethodParameterDto; import org.javahelpers.simple.builders.processor.model.type.TypeName; @@ -189,15 +191,14 @@ private MethodDto createStringFormatMethodWithTransform( methodDto.addArgument("builderFieldWrapper", TRACKED_VALUE_TYPE); methodDto.setPriority(MethodDto.PRIORITY_HIGH); methodDto.setJavadoc( - """ - Sets the String value for %s by using String.format(format, args). - See {@link String#format(String, Object...)} for details. - - @param %s A format string - @param %s Arguments referenced by the format specifiers in the format string. - @return current instance of builder - """ - .formatted(fieldName, formatParam.getParameterName(), argsParam.getParameterName())); + new JavadocDto( + "Sets the String value for %s by using String.format(format, args).\nSee {@link String#format(String, Object...)} for details.", + fieldName) + .addParam(formatParam.getParameterName(), "A format string") + .addParam( + argsParam.getParameterName(), + "Arguments referenced by the format specifiers in the format string.") + .addReturn(JavadocConstants.RETURN_BUILDER_INSTANCE)); return methodDto; } } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/SupplierMethodGenerator.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/SupplierMethodGenerator.java index 5e64f022..8e8ef06d 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/SupplierMethodGenerator.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/field/SupplierMethodGenerator.java @@ -31,7 +31,9 @@ import java.util.List; import java.util.function.Supplier; import org.javahelpers.simple.builders.processor.generators.MethodGenerator; +import org.javahelpers.simple.builders.processor.generators.util.JavadocConstants; import org.javahelpers.simple.builders.processor.model.core.FieldDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; import org.javahelpers.simple.builders.processor.model.method.MethodParameterDto; import org.javahelpers.simple.builders.processor.model.type.TypeName; @@ -95,7 +97,7 @@ public List generateMethods( createFieldSupplier( field.getOriginalFieldName(), field.getFieldNameInBuilder(), - field.getJavaDoc(), + field.getJavaDocDescriptionOrFieldName(), field.getFieldType(), builderType, context); @@ -144,13 +146,10 @@ private MethodDto createFieldSupplier( methodDto.setPriority(MethodDto.PRIORITY_HIGH); methodDto.setJavadoc( - """ - Sets the value for %s by invoking the provided supplier. - - @param %s supplier for %s - @return current instance of builder - """ - .formatted(fieldName, parameter.getParameterName(), fieldJavaDoc)); + new JavadocDto( + "Sets the value for %s by invoking the provided supplier.", fieldName) + .addParam(parameterName, "supplier for %s", fieldJavaDoc) + .addReturn(JavadocConstants.RETURN_BUILDER_INSTANCE)); return methodDto; } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/util/JavadocConstants.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/util/JavadocConstants.java new file mode 100644 index 00000000..5b16b12a --- /dev/null +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/util/JavadocConstants.java @@ -0,0 +1,42 @@ +/* + * MIT License + * + * Copyright (c) 2026 Andreas Igel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.javahelpers.simple.builders.processor.generators.util; + +/** + * Constants for commonly used javadoc text in builder generation. + * + *

This class contains reusable javadoc descriptions and text snippets that are used across + * multiple builder method generators. + */ +public final class JavadocConstants { + + /** Common return description for builder methods that return the builder instance. */ + public static final String RETURN_BUILDER_INSTANCE = "current instance of builder"; + + /** Private constructor to prevent instantiation. */ + private JavadocConstants() { + throw new UnsupportedOperationException("Utility class"); + } +} diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/util/MethodGeneratorUtil.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/util/MethodGeneratorUtil.java index 981b282c..e58984b8 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/util/MethodGeneratorUtil.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/generators/util/MethodGeneratorUtil.java @@ -31,6 +31,7 @@ import org.apache.commons.lang3.StringUtils; import org.javahelpers.simple.builders.processor.analysis.JavaLangMapper; import org.javahelpers.simple.builders.processor.model.core.FieldDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; import org.javahelpers.simple.builders.processor.model.method.MethodParameterDto; import org.javahelpers.simple.builders.processor.model.type.GenericParameterDto; @@ -186,15 +187,11 @@ public static MethodDto createBuilderMethodForFieldWithTransform( methodDto.setPriority(transform == null ? MethodDto.PRIORITY_HIGHEST : MethodDto.PRIORITY_HIGH); + String fieldJavadocDesc = field.getJavaDocDescriptionOrFieldName(); methodDto.setJavadoc( - """ - Sets the value for %s. - - @param %s %s - @return current instance of builder - """ - .formatted( - field.getOriginalFieldName(), parameter.getParameterName(), field.getJavaDoc())); + new JavadocDto("Sets the value for %s.", field.getOriginalFieldName()) + .addParam(parameter.getParameterName(), fieldJavadocDesc) + .addReturn(JavadocConstants.RETURN_BUILDER_INSTANCE)); return methodDto; } @@ -246,15 +243,17 @@ public static MethodDto createFieldConsumerWithBuilder( additionalTemplateArguments.forEach(methodDto::addArgument); methodDto.addArgument("builderFieldWrapper", TRACKED_VALUE_TYPE); methodDto.setPriority(MethodDto.PRIORITY_MEDIUM); + String fieldJavadocDesc = field.getJavaDocDescriptionOrFieldName(); methodDto.setJavadoc( - """ - Sets the value for %s using a builder consumer that produces the value. + new JavadocDto( + "Sets the value for %s using a builder consumer that produces the value.", + field.getFieldNameInBuilder()) + .addParam( + parameter.getParameterName(), + "consumer providing an instance of a builder for %s", + fieldJavadocDesc) + .addReturn(JavadocConstants.RETURN_BUILDER_INSTANCE)); - @param %s consumer providing an instance of a builder for %s - @return current instance of builder - """ - .formatted( - field.getFieldNameInBuilder(), parameter.getParameterName(), field.getJavaDoc())); return methodDto; } @@ -375,15 +374,16 @@ public static MethodDto createSimpleFieldConsumer( methodDto.addArgument("builderFieldWrapper", TRACKED_VALUE_TYPE); methodDto.setPriority(MethodDto.PRIORITY_MEDIUM); + String fieldJavadocDesc = field.getJavaDocDescriptionOrFieldName(); methodDto.setJavadoc( - """ - Sets the value for %s by executing the provided consumer. - - @param %s consumer providing an instance of %s - @return current instance of builder - """ - .formatted( - field.getOriginalFieldName(), parameter.getParameterName(), field.getJavaDoc())); + new JavadocDto( + "Sets the value for %s by executing the provided consumer.", + field.getOriginalFieldName()) + .addParam( + parameter.getParameterName(), + "consumer providing an instance of %s", + fieldJavadocDesc) + .addReturn(JavadocConstants.RETURN_BUILDER_INSTANCE)); return methodDto; } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/model/core/BuilderDefinitionDto.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/model/core/BuilderDefinitionDto.java index 614709a0..e19df4da 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/model/core/BuilderDefinitionDto.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/model/core/BuilderDefinitionDto.java @@ -30,6 +30,7 @@ import java.util.Set; import org.javahelpers.simple.builders.processor.model.annotation.AnnotationDto; import org.javahelpers.simple.builders.processor.model.annotation.InterfaceName; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; import org.javahelpers.simple.builders.processor.model.type.GenericParameterDto; import org.javahelpers.simple.builders.processor.model.type.NestedTypeDto; @@ -88,7 +89,7 @@ public class BuilderDefinitionDto { private final Set interfaces = new LinkedHashSet<>(); /** Class-level JavaDoc for the generated builder class. */ - private String classJavadoc; + private JavadocDto classJavadoc; /** Configuration for builder generation. */ private BuilderConfiguration configuration; @@ -311,7 +312,7 @@ public void setConfiguration(BuilderConfiguration configuration) { * * @return the class JavaDoc, or null if not set */ - public String getClassJavadoc() { + public JavadocDto getClassJavadoc() { return classJavadoc; } @@ -320,7 +321,7 @@ public String getClassJavadoc() { * * @param classJavadoc the class JavaDoc to set */ - public void setClassJavadoc(String classJavadoc) { + public void setClassJavadoc(JavadocDto classJavadoc) { this.classJavadoc = classJavadoc; } } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/model/core/FieldDto.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/model/core/FieldDto.java index 0a1df9ed..3f565fdb 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/model/core/FieldDto.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/model/core/FieldDto.java @@ -29,6 +29,7 @@ import java.util.Optional; import org.apache.commons.lang3.StringUtils; import org.javahelpers.simple.builders.processor.model.annotation.AnnotationDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; import org.javahelpers.simple.builders.processor.model.type.GenericParameterDto; import org.javahelpers.simple.builders.processor.model.type.TypeName; @@ -50,8 +51,14 @@ public class FieldDto { /** List of all methods in builder, which provide helpers to change the field. */ private final List fieldSetterMethodsList = new ArrayList<>(); - /** Optional Javadoc of the field extracted from setter or constructor. */ - private String javaDoc; + /** + * Original javadoc description extracted from setter or constructor parameter. This is used when + * generating javadoc for builder methods that reference this field. + */ + private String originalJavaDocDescription; + + /** Javadoc for the tracked value field in the builder. */ + private JavadocDto javaDoc; /** Method-level generics declared on the setter, to be reused in builder methods. */ private final List fieldGenerics = new ArrayList<>(); @@ -161,20 +168,50 @@ public void addMethod(MethodDto methodDto) { } /** - * Getting extracted Javadoc. + * Gets the original javadoc description extracted from the DTO. + * + * @return the original javadoc description, or null if none present + */ + public String getOriginalJavaDocDescription() { + return originalJavaDocDescription; + } + + /** + * Sets the original javadoc description extracted from the DTO. + * + * @param originalJavaDocDescription the original javadoc description + */ + public void setOriginalJavaDocDescription(String originalJavaDocDescription) { + this.originalJavaDocDescription = originalJavaDocDescription; + } + + /** + * Gets the original javadoc description if available, otherwise returns the original field name. + * + *

This is useful when generating javadoc for builder methods that reference the field, as it + * provides a meaningful description even when no explicit javadoc was provided. + * + * @return the javadoc description if available, otherwise the original field name + */ + public String getJavaDocDescriptionOrFieldName() { + return originalJavaDocDescription != null ? originalJavaDocDescription : originalFieldName; + } + + /** + * Getting Javadoc for the tracked value field in the builder. * - * @return Javadoc text or null if none present + * @return Javadoc or null if none present */ - public String getJavaDoc() { + public JavadocDto getJavaDoc() { return javaDoc; } /** - * Setting extracted Javadoc. + * Setting Javadoc for the tracked value field in the builder. * - * @param javaDoc Javadoc text + * @param javaDoc Javadoc */ - public void setJavaDoc(String javaDoc) { + public void setJavaDoc(JavadocDto javaDoc) { this.javaDoc = javaDoc; } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/model/javadoc/JavadocDto.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/model/javadoc/JavadocDto.java new file mode 100644 index 00000000..dc21fb92 --- /dev/null +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/model/javadoc/JavadocDto.java @@ -0,0 +1,236 @@ +/* + * MIT License + * + * Copyright (c) 2026 Andreas Igel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.javahelpers.simple.builders.processor.model.javadoc; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import org.apache.commons.lang3.StringUtils; + +/** + * Represents structured Javadoc with description text and tags. + * + *

Used for method and class-level javadoc. Note that @param tags are for documenting method + * parameters, not for individual parameter javadoc. + * + *

Example usage: + * + *

{@code
+ * JavadocDto javadoc = new JavadocDto("Builds a new PersonDto.")
+ *     .addParam("name", "the person's name")
+ *     .addParam("age", "the person's age")
+ *     .addThrows("IllegalArgumentException", "if name is null")
+ *     .addReturn("a new PersonDto instance");
+ * }
+ */ +public class JavadocDto { + + /** The main description text (everything before the first tag). */ + private String description; + + /** List of Javadoc tags in the order they appear. */ + private final List tags = new ArrayList<>(); + + /** Default constructor. */ + public JavadocDto() { + // Default constructor + } + + /** + * Constructor with description text. + * + * @param description the main description text + */ + public JavadocDto(String description) { + this.description = description; + } + + /** + * Constructor with formatted description text. + * + *

Allows using String.format-style formatting directly in the constructor. + * + *

Example: + * + *

{@code
+   * new JavadocDto("Sets the value for %s.", fieldName)
+   * }
+ * + * @param format the format string (using String.format syntax) + * @param args the arguments referenced by the format specifiers + */ + public JavadocDto(String format, Object... args) { + this.description = String.format(format, args); + } + + /** + * Constructor with description and tags. + * + * @param description the main description text + * @param tags the list of tags + */ + public JavadocDto(String description, List tags) { + this.description = description; + if (tags != null) { + this.tags.addAll(tags); + } + } + + /** + * Gets the main description text. + * + * @return the description text + */ + public String getDescription() { + return description; + } + + /** + * Gets the list of Javadoc tags. + * + * @return the list of tags + */ + public List getTags() { + return tags; + } + + /** + * Adds a tag with the given name and value. + * + * @param tagName the tag name without @ prefix + * @param tagValue the tag value + */ + public void addTag(String tagName, String tagValue) { + if (tagName != null) { + tags.add(new JavadocTagDto(tagName, tagValue)); + } + } + + /** + * Adds a tag without a value. + * + * @param tagName the tag name without @ prefix + */ + public void addTag(String tagName) { + if (tagName != null) { + tags.add(JavadocTagDto.withoutValue(tagName)); + } + } + + /** + * Adds a @param tag with optional formatted description. + * + *

Supports String.format-style formatting when args are provided. + * + *

Examples: + * + *

{@code
+   * addParam("value", "the value to set")              // No formatting
+   * addParam("value", "the %s to set", fieldName)      // With formatting
+   * }
+ * + * @param paramName the parameter name + * @param descriptionFormat the format string for the parameter description + * @param args optional arguments referenced by format specifiers in the description + * @return this JavadocDto for fluent chaining + */ + public JavadocDto addParam(String paramName, String descriptionFormat, Object... args) { + String paramDescription = String.format(descriptionFormat, args); + addTag("param", paramName + " " + paramDescription); + return this; + } + + /** + * Adds a @return tag with optional formatted description. + * + *

Supports String.format-style formatting when args are provided. + * + *

Examples: + * + *

{@code
+   * addReturn("current instance of builder")           // No formatting
+   * addReturn("builder for {@code %s}", className)     // With formatting
+   * }
+ * + * @param descriptionFormat the format string for the return description + * @param args optional arguments referenced by format specifiers in the description + * @return this JavadocDto for fluent chaining + */ + public JavadocDto addReturn(String descriptionFormat, Object... args) { + String returnDescription = String.format(descriptionFormat, args); + addTag("return", returnDescription); + return this; + } + + /** + * Adds a @throws tag with optional formatted description. + * + *

Supports String.format-style formatting when args are provided. + * + *

Examples: + * + *

{@code
+   * addThrows("IllegalArgumentException", "if name is null")
+   * addThrows("IllegalStateException", "if %s is invalid", fieldName)
+   * }
+ * + * @param exceptionName the exception name + * @param descriptionFormat the format string for the exception description + * @param args optional arguments referenced by format specifiers in the description + * @return this JavadocDto for fluent chaining + */ + public JavadocDto addThrows(String exceptionName, String descriptionFormat, Object... args) { + String throwsDescription = String.format(descriptionFormat, args); + addTag("throws", exceptionName + " " + throwsDescription); + return this; + } + + /** + * Returns whether this Javadoc has any content (description or tags). + * + * @return true if there is description text or at least one tag + */ + public boolean hasContent() { + return StringUtils.isNotBlank(description) || !tags.isEmpty(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + JavadocDto that = (JavadocDto) o; + return Objects.equals(description, that.description) && Objects.equals(tags, that.tags); + } + + @Override + public int hashCode() { + return Objects.hash(description, tags); + } + + @Override + public String toString() { + return "JavadocDto{" + "description='" + description + '\'' + ", tags=" + tags + '}'; + } +} diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/model/javadoc/JavadocTagDto.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/model/javadoc/JavadocTagDto.java new file mode 100644 index 00000000..f3934650 --- /dev/null +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/model/javadoc/JavadocTagDto.java @@ -0,0 +1,69 @@ +/* + * MIT License + * + * Copyright (c) 2026 Andreas Igel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.javahelpers.simple.builders.processor.model.javadoc; + +/** Represents a single Javadoc tag with its name and value. */ +public record JavadocTagDto(String tagName, String tagValue) { + + /** + * Creates a new Javadoc tag. + * + * @param tagName the tag name without @ prefix (e.g., "param", "return", "throws", "see") + * @param tagValue the tag value/content (may be empty for tags without content like deprecated) + */ + public JavadocTagDto { + if (tagName != null && tagName.startsWith("@")) { + throw new IllegalArgumentException("Tag name should not include @ prefix: " + tagName); + } + } + + /** + * Creates a tag without a value. + * + * @param tagName the tag name without @ prefix + * @return a new JavadocTagDto with empty value + */ + public static JavadocTagDto withoutValue(String tagName) { + return new JavadocTagDto(tagName, ""); + } + + /** + * Returns whether this tag has a non-empty value. + * + * @return true if the tag value is not null and not empty + */ + public boolean hasValue() { + return tagValue != null && !tagValue.trim().isEmpty(); + } + + /** + * Returns the full tag name with @ prefix for display purposes. + * + * @return the tag name with @ prefix (e.g., "@param") + */ + public String getFullTagName() { + return "@" + tagName; + } +} diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/model/method/MethodDto.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/model/method/MethodDto.java index 5a4b54eb..4d8e5662 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/model/method/MethodDto.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/model/method/MethodDto.java @@ -31,6 +31,7 @@ import javax.lang.model.element.Modifier; import org.apache.commons.lang3.StringUtils; import org.javahelpers.simple.builders.processor.model.annotation.AnnotationDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.type.GenericParameterDto; import org.javahelpers.simple.builders.processor.model.type.TypeName; @@ -61,7 +62,7 @@ public class MethodDto { private TypeName returnType; /** Javadoc comment for the method. */ - private String javadoc; + private JavadocDto javadoc; /** List of annotations on this method. */ private final List annotations = new ArrayList<>(); @@ -326,7 +327,7 @@ public String getSignatureKey() { return sb.toString(); } - public String getJavadoc() { + public JavadocDto getJavadoc() { return javadoc; } @@ -335,7 +336,7 @@ public String getJavadoc() { * * @param javadoc the Javadoc comment */ - public void setJavadoc(String javadoc) { + public void setJavadoc(JavadocDto javadoc) { this.javadoc = javadoc; } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/model/type/NestedTypeDto.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/model/type/NestedTypeDto.java index d7455152..3a82163c 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/model/type/NestedTypeDto.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/model/type/NestedTypeDto.java @@ -26,6 +26,7 @@ import java.util.LinkedList; import java.util.List; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; /** @@ -48,7 +49,7 @@ public class NestedTypeDto { private final List methods = new LinkedList<>(); /** Javadoc comment for this nested type. */ - private String javadoc; + private JavadocDto javadoc; public enum NestedTypeKind { INTERFACE, @@ -87,11 +88,11 @@ public void addMethod(MethodDto method) { this.methods.add(method); } - public String getJavadoc() { + public JavadocDto getJavadoc() { return javadoc; } - public void setJavadoc(String javadoc) { + public void setJavadoc(JavadocDto javadoc) { this.javadoc = javadoc; } } diff --git a/processor/src/main/java/org/javahelpers/simple/builders/processor/processing/BuilderDefinitionCreator.java b/processor/src/main/java/org/javahelpers/simple/builders/processor/processing/BuilderDefinitionCreator.java index f5f9620a..fb2e512d 100644 --- a/processor/src/main/java/org/javahelpers/simple/builders/processor/processing/BuilderDefinitionCreator.java +++ b/processor/src/main/java/org/javahelpers/simple/builders/processor/processing/BuilderDefinitionCreator.java @@ -48,6 +48,7 @@ import org.javahelpers.simple.builders.processor.model.annotation.AnnotationDto; import org.javahelpers.simple.builders.processor.model.core.BuilderDefinitionDto; import org.javahelpers.simple.builders.processor.model.core.FieldDto; +import org.javahelpers.simple.builders.processor.model.javadoc.JavadocDto; import org.javahelpers.simple.builders.processor.model.method.MethodDto; import org.javahelpers.simple.builders.processor.model.method.MethodParameterDto; import org.javahelpers.simple.builders.processor.model.type.TypeName; @@ -303,10 +304,7 @@ private static Optional createFieldFromSetter( // Extract only the @param Javadoc for the single setter parameter (if present) String fullJavaDoc = context.getDocComment(mth); - String javaDoc = JavaLangAnalyser.extractParamJavaDoc(fullJavaDoc, fieldParameter); - if (javaDoc == null) { - javaDoc = fieldName; - } + String javaDocDescription = JavaLangAnalyser.extractParamJavaDoc(fullJavaDoc, fieldParameter); // Check for field name conflicts and rename if necessary String finalFieldName = @@ -315,7 +313,13 @@ private static Optional createFieldFromSetter( // Pass both original field name (for methods) and final field name (for builder field) Optional result = createFieldDto( - fieldName, finalFieldName, javaDoc, fieldParameter, dtoType, builderType, context); + fieldName, + finalFieldName, + javaDocDescription, + fieldParameter, + dtoType, + builderType, + context); if (result.isPresent()) { fieldNameRegistry.put(finalFieldName, result.get()); @@ -335,12 +339,9 @@ private static Optional createFieldFromConstructor( ProcessingContext context, Map fieldNameRegistry) { String fieldName = param.getSimpleName().toString(); - // Set javadoc (default to field name if no javadoc found) - String javaDoc = + // Extract javadoc from constructor parameter (if present) + String javaDocDescription = JavaLangAnalyser.extractParamJavaDoc(context.getDocComment(annotatedType), param); - if (javaDoc == null) { - javaDoc = fieldName; - } // Convert TypeElement to TypeName once TypeName dtoType = JavaLangMapper.map2TypeName(annotatedType, context); @@ -350,7 +351,8 @@ private static Optional createFieldFromConstructor( // Pass both original field name (for methods) and final field name (for builder field) Optional result = - createFieldDto(fieldName, finalFieldName, javaDoc, param, dtoType, builderType, context); + createFieldDto( + fieldName, finalFieldName, javaDocDescription, param, dtoType, builderType, context); if (result.isPresent()) { fieldNameRegistry.put(finalFieldName, result.get()); @@ -430,7 +432,7 @@ The reason could be having helperfunctions in the DTO or a mistake in the DTO (e private static Optional createFieldDto( String fieldName, String fieldNameInBuilder, - String javaDoc, + String javaDocDescription, VariableElement param, TypeName dtoType, TypeName builderType, @@ -448,7 +450,17 @@ private static Optional createFieldDto( fieldNameInBuilder); // Use renamed field name for builder field storage field.setOriginalFieldName(fieldName); field.setFieldType(fieldType); - field.setJavaDoc(javaDoc); + + // Store original javadoc description for reuse in builder method javadocs + field.setOriginalJavaDocDescription(StringUtils.trimToNull(javaDocDescription)); + + // Create javadoc for the tracked value field in the builder + String javaDocDescriptionOrFieldname = field.getJavaDocDescriptionOrFieldName(); + JavadocDto trackedValueJavadoc = + new JavadocDto( + "Tracked value for %s: %s.", + fieldNameInBuilder, javaDocDescriptionOrFieldname); + field.setJavaDoc(trackedValueJavadoc); // Note: setterName will be set explicitly by the caller before field renaming diff --git a/sonar-project.properties b/sonar-project.properties index 81a7cb47..192f94fc 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -17,7 +17,7 @@ sonar.coverage.jacoco.xmlReportPaths=processor/target/site/jacoco/jacoco.xml # Exclusions sonar.exclusions=**/generated/**,example/** -sonar.coverage.exclusions=**/*Mapper*.java,**/processor/dtos/**,**/processor/exceptions/**,**/generated/**,example/** +sonar.coverage.exclusions=**/*Mapper*.java,**/processor/model/**,**/processor/exceptions/**,**/generated/**,example/** # Java Version sonar.java.source=17