Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error when constructor parameters names cannot be resolved #41626

Merged
merged 1 commit into from
Sep 17, 2024
Merged
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 @@ -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
Loading