Skip to content

Commit

Permalink
The processor for data objects does not converse the natural order of…
Browse files Browse the repository at this point in the history
… the declarations provided by the annotation processor element. In order to allows users reason about protobuf generation where the order matters, we need this order to be preserved.

Update the DataObjectModel implementation to conserve the declaration order as provided by the annotation processor. This changes the existing behavior that was sorting the elements using their name as sorting element.
  • Loading branch information
vietj committed Sep 15, 2023
1 parent 68508cc commit 332cd66
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -308,10 +308,10 @@ private void traverse() {
processMethods(methodsElt);

// Sort the properties so we do have a consistent order
ArrayList<PropertyInfo> props = new ArrayList<>(propertyMap.values());
Collections.sort(props, (p1, p2) -> p1.name.compareTo(p2.name));
propertyMap.clear();
props.forEach(prop -> propertyMap.put(prop.name, prop));
// ArrayList<PropertyInfo> props = new ArrayList<>(propertyMap.values());
// Collections.sort(props, (p1, p2) -> p1.name.compareTo(p2.name));
// propertyMap.clear();
// props.forEach(prop -> propertyMap.put(prop.name, prop));
}

private void processTypeAnnotations() {
Expand Down Expand Up @@ -377,6 +377,8 @@ private void processMethods(List<ExecutableElement> methodsElt) {
return a;
};

Set<String> names = new LinkedHashSet<>();

while (methodsElt.size() > 0) {
ExecutableElement methodElt = methodsElt.remove(0);
if (((TypeElement) methodElt.getEnclosingElement()).getQualifiedName().toString().equals("java.lang.Object") ||
Expand All @@ -385,17 +387,18 @@ private void processMethods(List<ExecutableElement> methodsElt) {
continue;
}
String methodName = methodElt.getSimpleName().toString();
String name;
if (methodName.startsWith("get") && methodName.length() > 3 && Character.isUpperCase(methodName.charAt(3)) && methodElt.getParameters().isEmpty() && methodElt.getReturnType().getKind() != TypeKind.VOID) {
String name = Helper.normalizePropertyName(methodName.substring(3));
name = Helper.normalizePropertyName(methodName.substring(3));
getters.put(name, methodElt);
annotations.merge(name, (List<AnnotationMirror>) elementUtils.getAllAnnotationMirrors(methodElt), merger);
} else if (methodName.startsWith("is") && methodName.length() > 2 && Character.isUpperCase(methodName.charAt(2)) && methodElt.getParameters().isEmpty() && methodElt.getReturnType().getKind() != TypeKind.VOID) {
String name = Helper.normalizePropertyName(methodName.substring(2));
name = Helper.normalizePropertyName(methodName.substring(2));
getters.put(name, methodElt);
annotations.merge(name, (List<AnnotationMirror>) elementUtils.getAllAnnotationMirrors(methodElt), merger);
} else if ((methodName.startsWith("set") || methodName.startsWith("add")) && methodName.length() > 3 && Character.isUpperCase(methodName.charAt(3))) {
String prefix = methodName.substring(0, 3);
String name = Helper.normalizePropertyName(methodName.substring(3));
name = Helper.normalizePropertyName(methodName.substring(3));
int numParams = methodElt.getParameters().size();
if ("add".equals(prefix)) {
if (name.endsWith("s")) {
Expand All @@ -408,21 +411,25 @@ private void processMethods(List<ExecutableElement> methodsElt) {
((TypeElement) ((DeclaredType) t).asElement()).getQualifiedName().toString().equals("java.lang.String"))) {
adders.put(name, methodElt);
annotations.merge(name, (List<AnnotationMirror>) elementUtils.getAllAnnotationMirrors(methodElt), merger);
} else {
continue;
}
} else {
if (numParams == 1) {
setters.put(name, methodElt);
annotations.merge(name, (List<AnnotationMirror>) elementUtils.getAllAnnotationMirrors(methodElt), merger);
} else {
continue;
}
}
} else {
continue;
}
if (!names.contains(name)) {
names.add(name);
}
}

Set<String> names = new HashSet<>();
names.addAll(getters.keySet());
names.addAll(setters.keySet());
names.addAll(adders.keySet());

for (String name : names) {
//Check annotations on field
List<? extends AnnotationMirror> list = getElement().getEnclosedElements().stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import java.time.Instant;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import static org.junit.Assert.*;
Expand Down Expand Up @@ -103,6 +104,26 @@ public void testPropertySetters() throws Exception {
.generateDataObject(PropertySetters.class, ApiObjectWithMapper.class);
assertNotNull(model);
assertEquals(15, model.getPropertyMap().size());

// Check order
Iterator<String> i = model.getPropertyMap().keySet().iterator();
assertEquals("string", i.next());
assertEquals("boxedInteger", i.next());
assertEquals("primitiveInteger", i.next());
assertEquals("boxedBoolean", i.next());
assertEquals("primitiveBoolean", i.next());
assertEquals("boxedLong", i.next());
assertEquals("primitiveLong", i.next());
assertEquals("instant", i.next());
assertEquals("apiObject", i.next());
assertEquals("apiObjectWithMapper", i.next());
assertEquals("dataObject", i.next());
assertEquals("toJsonDataObject", i.next());
assertEquals("jsonObject", i.next());
assertEquals("jsonArray", i.next());
assertEquals("enumerated", i.next());
assertFalse(i.hasNext());

assertProperty(model.getPropertyMap().get("string"), "string", "setString", null, null, TypeReflectionFactory.create(String.class), true, PropertyKind.VALUE, true);
assertProperty(model.getPropertyMap().get("boxedInteger"), "boxedInteger", "setBoxedInteger", null, null, TypeReflectionFactory.create(Integer.class), true, PropertyKind.VALUE, true);
assertProperty(model.getPropertyMap().get("primitiveInteger"), "primitiveInteger", "setPrimitiveInteger", null, null, TypeReflectionFactory.create(int.class), true, PropertyKind.VALUE, true);
Expand Down

0 comments on commit 332cd66

Please sign in to comment.