Skip to content
Closed
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 @@ -15,6 +15,7 @@
*/
package io.soabase.recordbuilder.processor;

import com.palantir.javapoet.AnnotationSpec;
import com.palantir.javapoet.ClassName;
import com.palantir.javapoet.ParameterizedTypeName;
import com.palantir.javapoet.TypeName;
Expand Down Expand Up @@ -95,6 +96,28 @@ public static boolean hasAnnotationTarget(ProcessingEnvironment processingEnv, A
return targetTypes.contains(elementType.name());
}

public static TypeName getAnnotatedTypeName(RecordClassType component, ElementType target,
ProcessingEnvironment processingEnv) {
return getAnnotatedTypeName(component, component.typeName(), target, processingEnv);
}

public static TypeName getAnnotatedTypeName(RecordClassType component, TypeName type, ElementType target,
ProcessingEnvironment processingEnv) {
var typeUseAnnotations = component.getAccessorAnnotations().stream()
.filter(annotationMirror -> isTypeUseOnly(processingEnv, annotationMirror, target))
.map(AnnotationSpec::get).toList();
if (typeUseAnnotations.isEmpty()) {
return type;
}
return type.annotated(typeUseAnnotations);
}

private static boolean isTypeUseOnly(ProcessingEnvironment processingEnv, AnnotationMirror annotationMirror,
ElementType target) {
var targetTypes = getAnnotationTargetTypes(processingEnv, annotationMirror);
return !targetTypes.contains(target.name()) && targetTypes.contains(ElementType.TYPE_USE.name());
}

public static boolean getBooleanAttribute(AnnotationValue attribute) {
Object value = (attribute != null) ? attribute.getValue() : null;
if (value != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

import static io.soabase.recordbuilder.processor.ElementUtils.generateName;
import static io.soabase.recordbuilder.processor.ElementUtils.hasAnnotationTarget;
import static io.soabase.recordbuilder.processor.ParameterSpecUtil.createParameterSpec;
import static io.soabase.recordbuilder.processor.RecordBuilderProcessor.generatedRecordBuilderAnnotation;
import static io.soabase.recordbuilder.processor.RecordBuilderProcessor.recordBuilderGeneratedAnnotation;

Expand Down Expand Up @@ -275,10 +276,11 @@ private ValidatedParameter validateParameter(String name, TypeMirror typeMirror)
private void addRecordComponents() {
MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder();
recordComponents.forEach(component -> {
ParameterSpec.Builder componentBuilder = ParameterSpec.builder(component.typeName(), component.name());
ParameterSpec.Builder componentBuilder = createParameterSpec(component, deconstructor.inheritAnnotations(),
processingEnv);
if (deconstructor.inheritAnnotations()) {
componentBuilder.addAnnotations(component
.getAccessorAnnotations().stream().filter(annotationMirror -> hasAnnotationTarget(processingEnv, annotationMirror, ElementType.METHOD))
componentBuilder.addAnnotations(component.getAccessorAnnotations().stream().filter(
annotationMirror -> hasAnnotationTarget(processingEnv, annotationMirror, ElementType.METHOD))
.map(AnnotationSpec::get).toList());
}
constructorBuilder.addParameter(componentBuilder.build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import static io.soabase.recordbuilder.processor.CollectionBuilderUtils.SingleItemsMetaDataMode.EXCLUDE_WILDCARD_TYPES;
import static io.soabase.recordbuilder.processor.CollectionBuilderUtils.SingleItemsMetaDataMode.STANDARD_FOR_SETTER;
import static io.soabase.recordbuilder.processor.ElementUtils.*;
import static io.soabase.recordbuilder.processor.ParameterSpecUtil.createParameterSpec;
import static io.soabase.recordbuilder.processor.RecordBuilderProcessor.generatedRecordBuilderAnnotation;
import static io.soabase.recordbuilder.processor.RecordBuilderProcessor.recordBuilderGeneratedAnnotation;
import static javax.tools.Diagnostic.Kind.ERROR;
Expand Down Expand Up @@ -273,8 +274,8 @@ private void addStagedBuilderClasses() {
var codeBlock = CodeBlock.builder().add("return $L().$L($L);", metaData.builderMethodName(),
optionalComponent.name(), optionalComponent.name()).build();

var parameterSpecBuilder = ParameterSpec.builder(optionalComponent.typeName(),
optionalComponent.name());
var parameterSpecBuilder = createParameterSpec(optionalComponent,
metaData.inheritComponentAnnotations(), processingEnv);
addConstructorAnnotations(optionalComponent, parameterSpecBuilder);
var methodSpec = MethodSpec.methodBuilder(optionalComponent.name())
.addAnnotation(generatedRecordBuilderAnnotation)
Expand Down Expand Up @@ -320,7 +321,8 @@ private void add1StagedBuilderClass(RecordClassType component, Optional<RecordCl
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT);

methodSpec.addJavadoc("Set a new value for the {@code $L} record component in the builder\n", component.name());
var parameterSpecBuilder = ParameterSpec.builder(component.typeName(), component.name());
var parameterSpecBuilder = createParameterSpec(component, metaData.inheritComponentAnnotations(),
processingEnv);
addConstructorAnnotations(component, parameterSpecBuilder);
methodSpec.addParameter(parameterSpecBuilder.build());

Expand Down Expand Up @@ -475,7 +477,8 @@ private void add1WithMethod(TypeSpec.Builder classBuilder, RecordClassType compo
codeBlockBuilder.add(";$]");

var methodName = getWithMethodName(component, metaData.withClassMethodPrefix());
var parameterSpecBuilder = ParameterSpec.builder(component.typeName(), component.name());
var parameterSpecBuilder = createParameterSpec(component, metaData.inheritComponentAnnotations(),
processingEnv);
addConstructorAnnotations(component, parameterSpecBuilder);
var methodSpec = MethodSpec.methodBuilder(methodName).addAnnotation(generatedRecordBuilderAnnotation)
.addJavadoc("Return a new instance of {@code $L} with a new value for {@code $L}\n",
Expand Down Expand Up @@ -539,7 +542,8 @@ private void addStaticBuilder() {
.addTypeVariables(typeVariables).addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addAnnotation(generatedRecordBuilderAnnotation).returns(recordClassType.typeName()).addCode(codeBlock);
recordComponents.forEach(component -> {
var parameterSpecBuilder = ParameterSpec.builder(component.typeName(), component.name());
var parameterSpecBuilder = createParameterSpec(component, metaData.inheritComponentAnnotations(),
processingEnv);
addConstructorAnnotations(component, parameterSpecBuilder);
builder.addParameter(parameterSpecBuilder.build());
});
Expand Down Expand Up @@ -587,7 +591,8 @@ private void addAllArgsConstructor() {
var constructorBuilder = MethodSpec.constructorBuilder().addModifiers(constructorVisibilityModifier)
.addAnnotation(generatedRecordBuilderAnnotation);
recordComponents.forEach(component -> {
var parameterSpecBuilder = ParameterSpec.builder(component.typeName(), component.name());
var parameterSpecBuilder = createParameterSpec(component, metaData.inheritComponentAnnotations(),
processingEnv);
addConstructorAnnotations(component, parameterSpecBuilder);
constructorBuilder.addParameter(parameterSpecBuilder.build());
constructorBuilder.addStatement("this.$L = $L", component.name(), component.name());
Expand Down Expand Up @@ -910,11 +915,13 @@ private void addNestedGetterMethod(TypeSpec.Builder classBuilder, RecordClassTyp
*
* T p();
*/
var returnType = metaData.inheritComponentAnnotations()
? getAnnotatedTypeName(component, ElementType.METHOD, processingEnv) : component.typeName();
var methodSpecBuilder = MethodSpec.methodBuilder(methodName)
.addJavadoc("Return the current value for the {@code $L} record component in the builder\n",
component.name())
.addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC).addAnnotation(generatedRecordBuilderAnnotation)
.returns(component.typeName());
.returns(returnType);
addAccessorAnnotations(component, methodSpecBuilder, this::filterOutValid);
classBuilder.addMethod(methodSpecBuilder.build());
}
Expand Down Expand Up @@ -1059,11 +1066,13 @@ private void add1GetterMethod(RecordClassType component) {
*
* public T p() { return p; }
*/
var returnType = metaData.inheritComponentAnnotations()
? getAnnotatedTypeName(component, ElementType.METHOD, processingEnv) : component.typeName();
var methodSpecBuilder = MethodSpec.methodBuilder(prefixedName(component, true))
.addJavadoc("Return the current value for the {@code $L} record component in the builder\n",
component.name())
.addModifiers(Modifier.PUBLIC).addAnnotation(generatedRecordBuilderAnnotation)
.returns(component.typeName()).addCode(checkReturnShim(component));
.addModifiers(Modifier.PUBLIC).addAnnotation(generatedRecordBuilderAnnotation).returns(returnType)
.addCode(checkReturnShim(component));
addAccessorAnnotations(component, methodSpecBuilder, __ -> true);
builder.addMethod(methodSpecBuilder.build());
}
Expand Down Expand Up @@ -1107,11 +1116,12 @@ private void add1SetterMethod(RecordClassType component, int componentIndex) {
methodSpec.addJavadoc(
"Re-create the internally allocated {@code $T} for {@code $L} by copying the argument\n",
component.typeName(), component.name()).addCode(codeSpec.build());
// skip adding TYPE_USE annotations for wildcards, does not seem simple
return ParameterSpec.builder(meta.wildType(), component.name());
}).orElseGet(() -> {
methodSpec.addJavadoc("Set a new value for the {@code $L} record component in the builder\n",
component.name()).addStatement("this.$L = $L", component.name(), component.name());
return ParameterSpec.builder(component.typeName(), component.name());
return createParameterSpec(component, metaData.inheritComponentAnnotations(), processingEnv);
});

addConstructorAnnotations(component, parameterSpecBuilder);
Expand All @@ -1134,7 +1144,8 @@ private void add1ConcreteOptionalSetterMethod(RecordClassType component) {
var methodSpec = MethodSpec.methodBuilder(prefixedName(component, false)).addModifiers(Modifier.PUBLIC)
.addAnnotation(generatedRecordBuilderAnnotation).returns(builderClassType.typeName());

var parameterSpecBuilder = ParameterSpec.builder(type.valueType(), component.name());
var parameterSpecBuilder = createParameterSpec(component, type.valueType(),
metaData.inheritComponentAnnotations(), processingEnv);
methodSpec.addJavadoc("Set a new value for the {@code $L} record component in the builder\n", component.name())
.addStatement(getOptionalStatement(type), component.name(), type.typeName(), component.name());
addConstructorAnnotations(component, parameterSpecBuilder);
Expand Down Expand Up @@ -1195,7 +1206,8 @@ private TypeSpec buildFunctionalInterface(String className, boolean isMap) {
var localTypeVariables = isMap ? typeVariablesWithReturn() : typeVariables;
var methodBuilder = MethodSpec.methodBuilder("apply").addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT);
recordComponents.forEach(component -> {
var parameterSpecBuilder = ParameterSpec.builder(component.typeName(), component.name());
var parameterSpecBuilder = createParameterSpec(component, metaData.inheritComponentAnnotations(),
processingEnv);
addConstructorAnnotations(component, parameterSpecBuilder);
methodBuilder.addParameter(parameterSpecBuilder.build());
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2019 The original author or authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.soabase.recordbuilder.processor;

import com.palantir.javapoet.ParameterSpec;
import com.palantir.javapoet.TypeName;
import java.lang.annotation.ElementType;
import javax.annotation.processing.ProcessingEnvironment;

final class ParameterSpecUtil {

public static ParameterSpec.Builder createParameterSpec(RecordClassType component, boolean inheritAnnotations,
ProcessingEnvironment processingEnv) {
return createParameterSpec(component, component.typeName(), inheritAnnotations, processingEnv);
}

public static ParameterSpec.Builder createParameterSpec(RecordClassType component, TypeName type,
boolean inheritAnnotations, ProcessingEnvironment processingEnv) {
if (inheritAnnotations) {
type = ElementUtils.getAnnotatedTypeName(component, type, ElementType.PARAMETER, processingEnv);
}
return ParameterSpec.builder(type, component.name());
}

private ParameterSpecUtil() {
}
}