private static ImmutableList<Executable> kotlinConstructorsFromReflection(
      AnnotationMirror metadata, TypeElement ofClass) throws ReflectiveOperationException {
    ImmutableMap<String, AnnotationValue> annotationValues =
        AnnotationMirrors.getAnnotationValuesWithDefaults(metadata).entrySet().stream()
            .collect(toImmutableMap(e -> e.getKey().getSimpleName().toString(), e -> e.getValue()));
    // We match the KmConstructor instances with the ExecutableElement instances based on the
    // parameter names. We could possibly just assume that the constructors are in the same order.
    Map<ImmutableSet<String>, ExecutableElement> map =
        constructorsIn(ofClass.getEnclosedElements()).stream()
            .collect(toMap(c -> parameterNames(c), c -> c, (a, b) -> a, LinkedHashMap::new));
    ImmutableMap<ImmutableSet<String>, ExecutableElement> paramNamesToConstructor =
        ImmutableMap.copyOf(map);
    KotlinClassHeader header =
        new KotlinClassHeader(
            (Integer) annotationValues.get("k").getValue(),
            intArrayValue(annotationValues.get("mv")),
            stringArrayValue(annotationValues.get("d1")),
            stringArrayValue(annotationValues.get("d2")),
            (String) annotationValues.get("xs").getValue(),
            (String) annotationValues.get("pn").getValue(),
            (Integer) annotationValues.get("xi").getValue());
    KotlinClassMetadata.Class classMetadata = KotlinClassMetadata.readLenient(header);
    KmClass kmClass = classMetadata.getKmClass();
    ImmutableList.Builder<Executable> kotlinConstructorsBuilder = ImmutableList.builder();
    for (KmConstructor constructor : kmClass.getConstructors()) {
      ImmutableSet.Builder<String> allBuilder = ImmutableSet.builder();
      ImmutableSet.Builder<String> optionalBuilder = ImmutableSet.builder();
      for (KmValueParameter param : constructor.getValueParameters()) {
        String name = param.getName();
        allBuilder.add(name);
        if (Attributes.getDeclaresDefaultValue(param)) {
          optionalBuilder.add(name);
        }
      }
      ImmutableSet<String> optional = optionalBuilder.build();
      ImmutableSet<String> all = allBuilder.build();
      ExecutableElement javaConstructor = paramNamesToConstructor.get(all);
      if (javaConstructor != null) {
        kotlinConstructorsBuilder.add(Executable.of(javaConstructor, optional));
      }
    }
    return kotlinConstructorsBuilder.build();
  }
Use Kotlin reflection to build {@link Executable} instances for the constructors in {@code
ofClass} that include information about which parameters have default values.

@param metadata the {@code @kotlin.Metadata} annotation on {@code ofClass}
@param ofClass the class whose constructors should be returned
value/src/main/java/com/google/auto/value/processor/KotlinMetadata.java