in nullaway/src/main/java/com/uber/nullaway/handlers/AbstractFieldContractHandler.java [109:214]
protected abstract void validateOverridingRules(
Set<String> fieldNames,
NullAway analysis,
VisitorState state,
MethodTree tree,
Symbol.MethodSymbol overriddenMethod);
/**
* Validates that a method implementation matches the semantics of the annotation.
*
* @return Returns true, if the annotation conforms to the semantic rules.
*/
protected abstract boolean validateAnnotationSemantics(
NullAway analysis, VisitorState state, MethodTree tree, Symbol.MethodSymbol methodSymbol);
/**
* Validates whether the parameter inside annotation conforms to the syntax rules. Parameters must
* conform to the following rules:
*
* <p>
*
* <ul>
* <li>Cannot annotate a method with empty param set.
* <li>The receiver of selected fields in annotation can only be the receiver of the method.
* <li>All parameters given in the annotation must be one of the fields of the class or its
* super classes.
* </ul>
*
* <p>
*
* @return Returns true, if the annotation conforms to the syntax rules.
*/
protected boolean validateAnnotationSyntax(
Set<String> content,
NullAway analysis,
MethodTree tree,
VisitorState state,
Symbol.MethodSymbol methodSymbol) {
String message;
if (content.isEmpty()) {
// we should not allow useless annotations.
message =
"empty @"
+ annotName
+ " is the default precondition for every method, please remove it.";
state.reportMatch(
analysis
.getErrorBuilder()
.createErrorDescription(
new ErrorMessage(ErrorMessage.MessageTypes.ANNOTATION_VALUE_INVALID, message),
tree,
analysis.buildDescription(tree),
state,
null));
return false;
} else {
for (String fieldName : content) {
if (fieldName.contains(".")) {
if (!fieldName.startsWith(THIS_NOTATION)) {
message =
"currently @"
+ annotName
+ " supports only class fields of the method receiver: "
+ fieldName
+ " is not supported";
state.reportMatch(
analysis
.getErrorBuilder()
.createErrorDescription(
new ErrorMessage(
ErrorMessage.MessageTypes.ANNOTATION_VALUE_INVALID, message),
tree,
analysis.buildDescription(tree),
state,
null));
return false;
} else {
fieldName = fieldName.substring(fieldName.lastIndexOf(".") + 1);
}
}
Symbol.ClassSymbol classSymbol = castToNonNull(ASTHelpers.enclosingClass(methodSymbol));
VariableElement field = getInstanceFieldOfClass(classSymbol, fieldName);
if (field == null) {
message =
"For @"
+ annotName
+ " annotation, cannot find instance field "
+ fieldName
+ " in class "
+ classSymbol.getSimpleName();
state.reportMatch(
analysis
.getErrorBuilder()
.createErrorDescription(
new ErrorMessage(ErrorMessage.MessageTypes.ANNOTATION_VALUE_INVALID, message),
tree,
analysis.buildDescription(tree),
state,
null));
return false;
}
}
}
return true;
}