Code review comment: Actually, we require Jandex 2.1+ and re-index dependencies if necessary (https://github.com/quarkusio/quarkus/blob/master/core/deployment/src/main/java/io/quarkus/deployment/index/ApplicationArchiveBuildStep.java#L200-L202). So `hasNoArgsConstructor()` should be enough. I'll update the PR.

Code before review:
public void addMissingConstructors() throws Exception {
Set<ClassInfo> targetClasses = new HashSet<>();
Set<DotName> normalScopes = initNormalScopes();
for (DotName normalScope : normalScopes) {
collectTargetClasses(targetClasses, normalScope);
}
for (Iterator<ClassInfo> iterator = targetClasses.iterator(); iterator.hasNext();) {
ClassInfo targetClass = iterator.next();
if (targetClass.hasNoArgsConstructor()
|| targetClass.methods().stream().anyMatch(m -> m.name().equals("<init>") && m.parameters().isEmpty())) {
iterator.remove();
}
}
if (targetClasses.isEmpty()) {
return;
}
Set<DotName> transformedClasses = new HashSet<>();
for (ClassInfo targetClass : targetClasses) {
String superClassName;
if (targetClass.superName() == null) {
superClassName = "java/lang/Object";
} else {
ClassInfo superClass = combinedIndex.getIndex().getClassByName(targetClass.superName());
if (superClass != null) {
if (superClass.hasNoArgsConstructor() || targetClass.methods().stream()
.anyMatch(m -> m.name().equals("<init>") && m.parameters().isEmpty())) {
superClassName = superClass.name().toString().replace('.', '/');
} else {
superClassName = null;
}
} else {
superClassName = null;
}
}
if (superClassName != null) {
transformedClasses.add(targetClass.name());
LOGGER.debugf("Adding no-args constructor to %s", targetClass);
transformers.produce(new BytecodeTransformerBuildItem(targetClass.name().toString(),
new BiFunction<String, ClassVisitor, ClassVisitor>() {
@Override
public ClassVisitor apply(String className, ClassVisitor classVisitor) {
ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, classVisitor) {
@Override
public void visit(int version, int access, String name, String signature, String superName,
String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
MethodVisitor mv = visitMethod(Modifier.PUBLIC, "<init>", "()V", null,
null);
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, superClassName, "<init>", "()V", false);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
};
return cv;
}
}));
}
}
if (!transformedClasses.isEmpty()) {
validators.produce(new BeanDeploymentValidatorBuildItem(new BeanDeploymentValidator() {
@Override
public boolean skipValidation(InjectionTargetInfo target, ValidationRule rule) {
return ValidationRule.NO_ARGS_CONSTRUCTOR.equals(rule) && target.kind() == TargetKind.BEAN
&& transformedClasses.contains(target.asBean().getBeanClass());
}
}));
}
}

Line under review: || targetClass.methods().stream().anyMatch(m -> m.name().equals("<init>") && m.parameters().isEmpty())) {

Code after addressing the review:
public void addMissingConstructors() throws Exception {
Set<ClassInfo> targetClasses = new HashSet<>();
Set<DotName> normalScopes = initNormalScopes();
for (DotName normalScope : normalScopes) {
collectTargetClasses(targetClasses, normalScope);
}
for (Iterator<ClassInfo> iterator = targetClasses.iterator(); iterator.hasNext();) {
ClassInfo targetClass = iterator.next();
if (targetClass.hasNoArgsConstructor()) {
iterator.remove();
}
}
if (targetClasses.isEmpty()) {
return;
}
Set<DotName> transformedClasses = new HashSet<>();
for (ClassInfo targetClass : targetClasses) {
String superClassName;
if (targetClass.superName() == null) {
superClassName = "java/lang/Object";
} else {
ClassInfo superClass = combinedIndex.getIndex().getClassByName(targetClass.superName());
if (superClass != null && superClass.hasNoArgsConstructor()) {
superClassName = superClass.name().toString().replace('.', '/');
} else {
superClassName = null;
}
}
if (superClassName != null) {
transformedClasses.add(targetClass.name());
LOGGER.debugf("Adding no-args constructor to %s", targetClass);
transformers.produce(new BytecodeTransformerBuildItem(targetClass.name().toString(),
new BiFunction<String, ClassVisitor, ClassVisitor>() {
@Override
public ClassVisitor apply(String className, ClassVisitor classVisitor) {
ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, classVisitor) {
@Override
public void visit(int version, int access, String name, String signature, String superName,
String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
MethodVisitor mv = visitMethod(Modifier.PUBLIC, "<init>", "()V", null,
null);
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, superClassName, "<init>", "()V", false);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
};
return cv;
}
}));
}
}
if (!transformedClasses.isEmpty()) {
validators.produce(new BeanDeploymentValidatorBuildItem(new BeanDeploymentValidator() {
@Override
public boolean skipValidation(InjectionTargetInfo target, ValidationRule rule) {
return ValidationRule.NO_ARGS_CONSTRUCTOR.equals(rule) && target.kind() == TargetKind.BEAN
&& transformedClasses.contains(target.asBean().getBeanClass());
}
}));
}
}