in legacy/java/piranha/src/main/java/com/uber/piranha/testannotations/TestAnnotationResolver.java [110:202]
private Optional<ResolvedTestAnnotation> attemptResolveSpec(
TestAnnotationSpecRecord spec, AnnotationTree at, Tree parent, VisitorState state) {
if (!at.getAnnotationType().toString().contains(spec.getAnnotationName())) {
// For sanity, attempting to resolve an annotation with a spec without the same name will
// always return empty.
return Optional.empty();
}
final ImmutableMultimap<String, AnnotationArgument> fields = parseAnnotationArguments(at);
Set<String> relevantFieldParsingErrors = new HashSet<String>();
// Process flag id(s)
ImmutableList.Builder<AnnotationArgument> flagIdsBuilder = ImmutableList.builder();
String flagIdentifierOrField = spec.getFlagIdentifierOrField();
if (TestAnnotationSpecRecord.isFieldReference(flagIdentifierOrField)) {
// Annotation field reference
if (!fields.containsKey(flagIdentifierOrField)) {
// Annotation does not match the spec. That's fine, maybe another spec with the same name
// does, let's wait until we have seen if that isn't the case before reporting an error.
return Optional.empty();
}
for (AnnotationArgument argument : fields.get(flagIdentifierOrField)) {
if (argument.getValue().equals(UNPARSED_FIELD_VALUE)) {
// There is an error parsing the value of this field, let's wait to see if the rest of the
// annotation matches the specification's shape before we report that as an error.
relevantFieldParsingErrors.add(
String.format(
"Field %s is not of a type which can be parsed to a flag or list of flags.",
flagIdentifierOrField));
}
flagIdsBuilder.add(argument);
}
} else {
// constant flag name
flagIdsBuilder.add(new AnnotationArgument(flagIdentifierOrField, null));
}
// Process flag treatment value
boolean treated = false;
String treatedValueOrField = spec.getTreatedValueOrField();
if (TestAnnotationSpecRecord.isFieldReference(treatedValueOrField)) {
if (!fields.containsKey(treatedValueOrField)) {
// Annotation does not match the spec. That's fine, maybe another spec with the same name
// does.
return Optional.empty();
} else if (fields.get(treatedValueOrField).size() != 1) {
relevantFieldParsingErrors.add(
String.format(
"Field %s is not valid for specifying the treatment condition. Expected single "
+ "boolean (or string encoding boolean) value.",
treatedValueOrField));
}
AnnotationArgument argument = fields.get(treatedValueOrField).asList().get(0);
if (TRUE_STR.equalsIgnoreCase(argument.getValue())) {
treated = true;
} else if (FALSE_STR.equalsIgnoreCase(argument.getValue())) {
treated = false;
} else {
relevantFieldParsingErrors.add(
String.format(
"Field %s is not valid for specifying the treatment condition. Expected a "
+ "boolean (or string encoding boolean) value.",
treatedValueOrField));
}
} else {
// Only 'true' or 'false' are possible at this point, due to parsing logic
Preconditions.checkArgument(
TRUE_STR.equalsIgnoreCase(treatedValueOrField)
|| FALSE_STR.equalsIgnoreCase(treatedValueOrField));
treated = TRUE_STR.equalsIgnoreCase(treatedValueOrField);
}
// Process treatment group, if any
ImmutableList.Builder<AnnotationArgument> groupsBuilder = ImmutableList.builder();
Optional<String> groupValueOrField = spec.getGroupValueOrField();
if (groupValueOrField.isPresent()) {
// ToDo: implement
throw new UnsupportedOperationException(
"Treatment group information in test annotations not yet supported");
}
if (!relevantFieldParsingErrors.isEmpty()) {
throw new AnnotationResolutionException(
String.format(
"Found annotation %s at %s, matching the shape of the test annotation "
+ "specification `%s` from Piranha's configuration file. However, one or more errors "
+ "occurred when parsing the annotation's fields:\n\t* %s",
state.getSourceForNode(at),
ASTHelpers.getSymbol(parent).flatName().toString(),
spec,
relevantFieldParsingErrors
.stream()
.map(a -> a.toString())
.collect(Collectors.joining("\n\t* "))));
}
return Optional.of(
new ResolvedTestAnnotation(flagIdsBuilder.build(), treated, groupsBuilder.build(), at));
}