Skip to content

Commit b780604

Browse files
authored
Fix JDT records (#346)
* Fix JDT records Fixes error where records generate incorrectly on JDT * Update TypeReader.java
1 parent c3a1e40 commit b780604

File tree

1 file changed

+43
-11
lines changed

1 file changed

+43
-11
lines changed

jsonb-generator/src/main/java/io/avaje/jsonb/generator/TypeReader.java

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import javax.lang.model.element.*;
44
import javax.lang.model.type.TypeMirror;
55
import javax.lang.model.util.ElementFilter;
6+
import javax.lang.model.util.Elements;
67

78
import static java.util.stream.Collectors.toSet;
89

@@ -263,18 +264,49 @@ private void readMethod(Element element, List<FieldReader> localFields) {
263264
}
264265
}
265266
// for getter/accessor methods only, not setters
266-
PropertyPrism.getOptionalOn(methodElement).ifPresent(propertyPrism -> {
267-
if (!methodElement.getParameters().isEmpty()) {
268-
logError(errorContext + baseType + ", @Json.Property can only be placed on Getter Methods, but on %s", methodElement);
269-
return;
270-
}
267+
PropertyPrism.getOptionalOn(methodElement)
268+
.filter(p -> !hasRecordPropertyAnnotation(methodElement))
269+
.ifPresent(propertyPrism -> {
270+
if (!methodElement.getParameters().isEmpty()) {
271+
logError(errorContext + baseType + ", @Json.Property can only be placed on Getter Methods, but on %s", methodElement);
272+
return;
273+
}
274+
275+
// getter property as simulated read-only field with getter method
276+
final var frequency = frequency(propertyPrism.value());
277+
final var reader = new FieldReader(element, namingConvention, currentSubType, genericTypeParams, frequency);
278+
reader.getterMethod(new MethodReader(methodElement));
279+
localFields.add(reader);
280+
});
281+
}
282+
283+
private boolean hasRecordPropertyAnnotation(ExecutableElement methodElement) {
284+
try {
285+
return APContext.jdkVersion() >= 16
286+
&& Optional.ofNullable(recordComponentFor(methodElement))
287+
.map(Element.class::cast)
288+
.flatMap(TypeReader::matchingField)
289+
.filter(PropertyPrism::isPresent)
290+
.isPresent();
291+
} catch (Exception e) {
292+
return false;
293+
}
294+
}
295+
296+
/**
297+
* e is a RecordComponentElement that doesn't have the annotation
298+
* look up the field by name to see if the annotation is present
299+
*/
300+
private static Optional<VariableElement> matchingField(Element e) {
301+
return ElementFilter.fieldsIn(e.getEnclosingElement().getEnclosedElements()).stream()
302+
.filter(f -> f.getSimpleName().contentEquals(e.getSimpleName()))
303+
.findAny();
304+
}
271305

272-
// getter property as simulated read-only field with getter method
273-
final var frequency = frequency(propertyPrism.value());
274-
final var reader = new FieldReader(element, namingConvention, currentSubType, genericTypeParams, frequency);
275-
reader.getterMethod(new MethodReader(methodElement));
276-
localFields.add(reader);
277-
});
306+
private static Object recordComponentFor(ExecutableElement methodElement) throws Exception {
307+
return Elements.class
308+
.getMethod("recordComponentFor", ExecutableElement.class)
309+
.invoke(APContext.elements(), methodElement);
278310
}
279311

280312
private boolean checkMethod2(ExecutableElement methodElement) {

0 commit comments

Comments
 (0)