Skip to content

Commit

Permalink
Improve error when constructor parameters names cannot be resolved
Browse files Browse the repository at this point in the history
  • Loading branch information
metacosm authored and gsmet committed Aug 27, 2024
1 parent fae59c9 commit d09dc71
Showing 1 changed file with 39 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1135,40 +1135,25 @@ public void prepare(MethodContext context) {
nonDefaultConstructorHandles[i] = loadObjectInstance(obj, existing,
parameterTypes[count++], relaxedValidation);
}
if (nonDefaultConstructorHolder.constructor.getParameterCount() > 0) {
Parameter[] parameters = nonDefaultConstructorHolder.constructor.getParameters();
for (int i = 0; i < parameters.length; ++i) {
if (parameters[i].isNamePresent()) {
String name = parameters[i].getName();
constructorParamNameMap.put(name, i);
}
}
}
extractConstructorParameterNames(nonDefaultConstructorHolder.constructor, constructorParamNameMap);
} else if (classesToUseRecordableConstructor.contains(param.getClass())) {
Constructor<?> current = null;
int count = 0;
for (var c : param.getClass().getConstructors()) {
if (current == null || current.getParameterCount() < c.getParameterCount()) {
current = c;
count = 0;
} else if (current != null && current.getParameterCount() == c.getParameterCount()) {
} else if (current.getParameterCount() == c.getParameterCount()) {
count++;
}
}
if (current == null || count > 0) {
throw new RuntimeException("Unable to determine the recordable constructor to use for " + param.getClass());
}

nonDefaultConstructorHolder = new NonDefaultConstructorHolder(current, null);
nonDefaultConstructorHandles = new DeferredParameter[current.getParameterCount()];
if (current.getParameterCount() > 0) {
Parameter[] parameters = current.getParameters();
for (int i = 0; i < parameters.length; ++i) {
if (parameters[i].isNamePresent()) {
String name = parameters[i].getName();
constructorParamNameMap.put(name, i);
}
}
}
extractConstructorParameterNames(current, constructorParamNameMap);
} else {
Constructor<?>[] ctors = param.getClass().getConstructors();
Constructor<?> selectedCtor = null;
Expand All @@ -1184,16 +1169,13 @@ public void prepare(MethodContext context) {
}
if (selectedCtor != null) {
nonDefaultConstructorHolder = new NonDefaultConstructorHolder(selectedCtor, null);
nonDefaultConstructorHandles = new DeferredParameter[selectedCtor.getParameterCount()];

if (selectedCtor.getParameterCount() > 0) {
Parameter[] ctorParameters = selectedCtor.getParameters();
for (int i = 0; i < ctorParameters.length; ++i) {
if (ctorParameters[i].isNamePresent()) {
String name = ctorParameters[i].getName();
constructorParamNameMap.put(name, i);
}
}
final var parameterCount = selectedCtor.getParameterCount();
nonDefaultConstructorHandles = new DeferredParameter[parameterCount];
extractConstructorParameterNames(selectedCtor, constructorParamNameMap);

if (constructorParamNameMap.size() != parameterCount) {
throw new IllegalArgumentException("Couldn't extract all parameters information for constructor "
+ selectedCtor + " for type " + expectedType);
}
}
}
Expand Down Expand Up @@ -1358,8 +1340,15 @@ public void prepare(MethodContext context) {
}
}
}
DeferredParameter val = loadObjectInstance(propertyValue, existing,
i.getPropertyType(), relaxedValidation);
DeferredParameter val;
try {
val = loadObjectInstance(propertyValue, existing,
i.getPropertyType(), relaxedValidation);
} catch (Exception e) {
throw new RuntimeException(
"Couldn't load object of type " + i.propertyType.getName() + " for property '" + i.getName()
+ "' on object '" + param + "'.");
}
if (ctorParamIndex != null) {
nonDefaultConstructorHandles[ctorParamIndex] = val;
ctorSetupSteps.add(new SerializationStep() {
Expand Down Expand Up @@ -1458,7 +1447,7 @@ public void prepare(MethodContext context) {
NonDefaultConstructorHolder finalNonDefaultConstructorHolder = nonDefaultConstructorHolder;
DeferredParameter[] finalCtorHandles = nonDefaultConstructorHandles;

//create a deferred value to represet the object itself. This allows the creation to be split
//create a deferred value to represent the object itself. This allows the creation to be split
//over multiple methods, which is important if this is a large object
DeferredArrayStoreParameter objectValue = new DeferredArrayStoreParameter(param, expectedType) {
@Override
Expand Down Expand Up @@ -1540,6 +1529,24 @@ ResultHandle createValue(MethodContext context, MethodCreator method, ResultHand
};
}

private static List<Parameter> extractConstructorParameterNames(Constructor<?> selectedCtor,
Map<String, Integer> constructorParamNameMap) {
List<Parameter> unnamed = Collections.emptyList();
if (selectedCtor.getParameterCount() > 0) {
Parameter[] ctorParameters = selectedCtor.getParameters();
unnamed = new ArrayList<>(ctorParameters.length);
for (int i = 0; i < ctorParameters.length; ++i) {
if (ctorParameters[i].isNamePresent()) {
String name = ctorParameters[i].getName();
constructorParamNameMap.put(name, i);
} else {
unnamed.add(ctorParameters[i]);
}
}
}
return unnamed;
}

/**
* Returns {@code true} iff the field is annotated {@link IgnoreProperty} or the field is marked as {@code transient}
*/
Expand Down

0 comments on commit d09dc71

Please sign in to comment.