Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
package org.javahelpers.simple.builders.processor;

import static org.javahelpers.simple.builders.processor.processing.BuilderDefinitionCreator.extractFromElement;
import static org.javahelpers.simple.builders.processor.processing.logging.PerformanceTracker.PHASE_BUILDER_DEFINITION_EXTRACTION;
import static org.javahelpers.simple.builders.processor.processing.logging.PerformanceTracker.PHASE_CODE_GENERATION;
import static org.javahelpers.simple.builders.processor.processing.logging.PerformanceTracker.PHASE_CONFIGURATION_RESOLUTION;
import static org.javahelpers.simple.builders.processor.processing.logging.PerformanceTracker.PHASE_DTO_MAPPING;
import static org.javahelpers.simple.builders.processor.processing.logging.PerformanceTracker.PHASE_ELEMENT_COLLECTION;
import static org.javahelpers.simple.builders.processor.processing.ProcessingPhases.PHASE_BUILDER_DEFINITION_EXTRACTION;
import static org.javahelpers.simple.builders.processor.processing.ProcessingPhases.PHASE_CODE_GENERATION;
import static org.javahelpers.simple.builders.processor.processing.ProcessingPhases.PHASE_CONFIGURATION_RESOLUTION;
import static org.javahelpers.simple.builders.processor.processing.ProcessingPhases.PHASE_DTO_MAPPING;
import static org.javahelpers.simple.builders.processor.processing.ProcessingPhases.PHASE_ELEMENT_COLLECTION;

import com.google.auto.service.AutoService;
import java.util.ArrayList;
Expand All @@ -50,6 +50,8 @@
import org.javahelpers.simple.builders.core.annotations.Ignore4BuilderGeneration;
import org.javahelpers.simple.builders.core.annotations.SimpleBuilder.Template;
import org.javahelpers.simple.builders.processor.analysis.JavaLangAnalyser;
import org.javahelpers.simple.builders.processor.classgen.ClassCodeGenerator;
import org.javahelpers.simple.builders.processor.classgen.GenerationEnvironment;
import org.javahelpers.simple.builders.processor.classgen.roaster.RoasterCodeGenerator;
import org.javahelpers.simple.builders.processor.exceptions.BuilderException;
import org.javahelpers.simple.builders.processor.generators.integration.JacksonModuleGenerator;
Expand Down Expand Up @@ -77,23 +79,27 @@
public class BuilderProcessor extends AbstractProcessor {
private ProcessingContext context;
private ProcessingLogger logger;
private RoasterCodeGenerator codeGenerator;
private ClassCodeGenerator codeGenerator;
private JacksonModuleGenerator jacksonModuleGenerator;
private boolean supportedJdk = true;

@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
this.logger = new ProcessingLogger(processingEnv);
logger.debug("Starting BuilderProcessor...");

// Read global configuration from compiler arguments
CompilerArgumentsReader reader = new CompilerArgumentsReader(processingEnv);
BuilderConfiguration globalConfig = reader.readBuilderConfiguration(logger);
this.logger =
new ProcessingLogger(processingEnv, reader.readBooleanValue(CompilerArgumentsEnum.VERBOSE));
logger.debug("Starting BuilderProcessor...");
BuilderConfiguration globalConfig =
BuilderConfigurationReader.readBuilderConfiguration(reader, logger);
logger.debug("Loaded global configuration from compiler arguments: %s", globalConfig);

this.context = new ProcessingContext(logger, globalConfig, processingEnv);
this.codeGenerator = new RoasterCodeGenerator(context, processingEnv);
this.codeGenerator =
new RoasterCodeGenerator(
new GenerationEnvironment(processingEnv, logger, context.getPerformanceTracker()),
context::createSourceFormatter);
this.jacksonModuleGenerator = new JacksonModuleGenerator(processingEnv, logger, globalConfig);

// Initialize GeneratorRegistry once during processor initialization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
import org.javahelpers.simple.builders.processor.model.annotation.AnnotationDto;
import org.javahelpers.simple.builders.processor.model.type.TypeName;
import org.javahelpers.simple.builders.processor.model.type.TypeNamePrimitive;
import org.javahelpers.simple.builders.processor.processing.ProcessingContext;
import org.javahelpers.simple.builders.processor.processing.AnnotationProcessingContext;

/** Extractor for field annotations, converting them from Java model elements to DTOs. */
public final class FieldAnnotationExtractor {
Expand Down Expand Up @@ -82,17 +82,17 @@ private FieldAnnotationExtractor() {
* Extracts the {@code @Deprecated} annotation from the given element, preserving its members
* (e.g. {@code since} and {@code forRemoval}).
*
* <p>Unlike {@link #extractAnnotations(VariableElement, ProcessingContext)}, this method targets
* a single annotation and works on any {@link Element} (method, field, parameter, record
* component, type), not just {@link VariableElement}s.
* <p>Unlike {@link #extractAnnotations(VariableElement, AnnotationProcessingContext)}, this
* method targets a single annotation and works on any {@link Element} (method, field, parameter,
* record component, type), not just {@link VariableElement}s.
*
* @param element the element to inspect, or {@code null}
* @param context processing context
* @return an {@link Optional} containing the {@code @Deprecated} annotation DTO, or empty if the
* element is not deprecated
*/
public static Optional<AnnotationDto> extractDeprecatedAnnotation(
Element element, ProcessingContext context) {
Element element, AnnotationProcessingContext context) {
if (element == null) {
return Optional.empty();
}
Expand Down Expand Up @@ -120,7 +120,7 @@ public static Optional<AnnotationDto> extractDeprecatedAnnotation(
* @return list of annotations to be copied to the builder field
*/
public static List<AnnotationDto> extractAnnotations(
VariableElement param, ProcessingContext context) {
VariableElement param, AnnotationProcessingContext context) {
List<AnnotationDto> annotations = new ArrayList<>();
List<? extends AnnotationMirror> annotationMirrors = param.getAnnotationMirrors();

Expand All @@ -140,7 +140,7 @@ public static List<AnnotationDto> extractAnnotations(
* @return list of annotations to be copied to the builder field
*/
public static List<AnnotationDto> extractAnnotations(
javax.lang.model.type.TypeMirror typeMirror, ProcessingContext context) {
javax.lang.model.type.TypeMirror typeMirror, AnnotationProcessingContext context) {
List<AnnotationDto> annotations = new ArrayList<>();
List<? extends AnnotationMirror> annotationMirrors = typeMirror.getAnnotationMirrors();

Expand All @@ -160,7 +160,7 @@ public static List<AnnotationDto> extractAnnotations(
* @return Optional containing the extracted annotation, or empty if it should be skipped
*/
private static Optional<AnnotationDto> extractAnnotation(
AnnotationMirror mirror, ProcessingContext context) {
AnnotationMirror mirror, AnnotationProcessingContext context) {
// Get the annotation type element
Element annotationElement = mirror.getAnnotationType().asElement();
if (!(annotationElement instanceof TypeElement annotationType)) {
Expand Down Expand Up @@ -188,7 +188,7 @@ private static Optional<AnnotationDto> extractAnnotation(
* @return Optional containing the extracted annotation
*/
private static Optional<AnnotationDto> extractAnnotationWithoutFiltering(
AnnotationMirror mirror, ProcessingContext context) {
AnnotationMirror mirror, AnnotationProcessingContext context) {
Element annotationElement = mirror.getAnnotationType().asElement();
if (!(annotationElement instanceof TypeElement annotationType)) {
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Strings;
import org.javahelpers.simple.builders.core.annotations.SimpleBuilderConstructor;
import org.javahelpers.simple.builders.processor.processing.ProcessingContext;
import org.javahelpers.simple.builders.processor.processing.AnnotationProcessingContext;

/** Helperclass for extrating specific information from existing classes. */
public final class JavaLangAnalyser {
Expand Down Expand Up @@ -74,7 +73,7 @@ public static boolean isNoMethodOfObjectClass(ExecutableElement mth) {
* @return filtered list excluding Object class methods
*/
public static List<ExecutableElement> findAllPossibleSettersOfClass(
TypeElement typeElement, ProcessingContext context) {
TypeElement typeElement, AnnotationProcessingContext context) {
return ElementFilter.methodsIn(context.getAllMembers(typeElement)).stream()
.filter(JavaLangAnalyser::isNoMethodOfObjectClass)
.filter(JavaLangAnalyser::isSetterForField)
Expand Down Expand Up @@ -187,7 +186,8 @@ public static boolean isSetterForField(ExecutableElement mth) {
* @param context processing context
* @return {@code true}, if the element has an empty constructor
*/
public static boolean hasEmptyConstructor(TypeElement typeElement, ProcessingContext context) {
public static boolean hasEmptyConstructor(
TypeElement typeElement, AnnotationProcessingContext context) {
List<ExecutableElement> constructors =
ElementFilter.constructorsIn(context.getAllMembers(typeElement));
return constructors.stream().anyMatch(c -> c.getParameters().isEmpty());
Expand Down Expand Up @@ -232,7 +232,7 @@ public static Optional<AnnotationMirror> findAnnotation(
* @return {@code true} if the type declares or inherits a matching {@code build()} method
*/
public static boolean hasBuildMethodReturning(
TypeElement builderType, String expectedReturnType, ProcessingContext context) {
TypeElement builderType, String expectedReturnType, AnnotationProcessingContext context) {
if (builderType == null) {
return false;
}
Expand All @@ -255,7 +255,7 @@ public static boolean hasBuildMethodReturning(
* @return {@code true} if the type declares or inherits a matching constructor
*/
public static boolean hasConstructorAccepting(
TypeElement builderType, String expectedType, ProcessingContext context) {
TypeElement builderType, String expectedType, AnnotationProcessingContext context) {
if (builderType == null) {
return false;
}
Expand Down Expand Up @@ -474,7 +474,7 @@ public static Optional<ExecutableElement> findGetterForField(
TypeElement dtoType,
String fieldName,
TypeMirror fieldTypeMirror,
ProcessingContext context) {
AnnotationProcessingContext context) {
if (dtoType == null || fieldName == null || fieldTypeMirror == null) {
return Optional.empty();
}
Expand Down Expand Up @@ -541,7 +541,7 @@ public static Optional<javax.lang.model.element.RecordComponentElement> findReco
* @return Optional containing the setter ExecutableElement if found
*/
public static Optional<ExecutableElement> findSetterForField(
TypeElement dtoType, String fieldName, ProcessingContext context) {
TypeElement dtoType, String fieldName, AnnotationProcessingContext context) {
if (dtoType == null || fieldName == null) {
return Optional.empty();
}
Expand All @@ -559,22 +559,26 @@ public static Optional<ExecutableElement> findSetterForField(

/**
* Determines which constructor to use for builder initialization. Prioritizes constructors
* annotated with {@link SimpleBuilderConstructor}. If none is annotated, selects the constructor
* annotated with {@code constructorAnnotation}. If none is annotated, selects the constructor
* with the highest number of parameters. Returns empty if no constructor has parameters (i.e.,
* only default constructor or none found).
*
* @param annotatedType the type element to search for constructors
* @param constructorAnnotation the annotation type marking a preferred constructor, may be {@code
* null} to skip the annotation check
* @param context the processing context providing access to elements and types utilities
* @return Optional containing the selected constructor, or empty if none suitable
*/
public static Optional<ExecutableElement> findConstructorForBuilder(
TypeElement annotatedType, ProcessingContext context) {
TypeElement annotatedType,
Class<? extends Annotation> constructorAnnotation,
AnnotationProcessingContext context) {
List<ExecutableElement> ctors =
ElementFilter.constructorsIn(context.getAllMembers(annotatedType));

// First, check if any constructor is annotated with @SimpleBuilderConstructor
// First, check if any constructor is annotated with the constructor annotation
for (ExecutableElement ctor : ctors) {
if (ctor.getAnnotation(SimpleBuilderConstructor.class) != null) {
if (constructorAnnotation != null && ctor.getAnnotation(constructorAnnotation) != null) {
return Optional.of(ctor);
}
}
Expand Down
Loading
Loading