in nullaway/src/main/java/com/uber/nullaway/handlers/contract/fieldcontract/EnsuresNonNullHandler.java [74:126]
protected boolean validateAnnotationSemantics(
MethodTree tree, MethodAnalysisContext methodAnalysisContext) {
NullAway analysis = methodAnalysisContext.analysis();
VisitorState state = methodAnalysisContext.state();
Symbol.MethodSymbol methodSymbol = methodAnalysisContext.methodSymbol();
String message;
if (tree.getBody() == null) {
return true;
}
Set<String> nonnullFieldsOfReceiverAtExit =
analysis
.getNullnessAnalysis(state)
.getNonnullFieldsOfReceiverAtExit(new TreePath(state.getPath(), tree), state.context)
.stream()
.map(e -> e.getSimpleName().toString())
.collect(Collectors.toSet());
Set<String> nonnullStaticFieldsAtExit =
analysis
.getNullnessAnalysis(state)
.getNonnullStaticFieldsAtExit(new TreePath(state.getPath(), tree), state.context)
.stream()
.map(e -> e.getSimpleName().toString())
.collect(Collectors.toSet());
Set<String> nonnullFieldsAtExit = new HashSet<String>();
nonnullFieldsAtExit.addAll(nonnullFieldsOfReceiverAtExit);
nonnullFieldsAtExit.addAll(nonnullStaticFieldsAtExit);
Set<String> fieldNames = getAnnotationValueArray(methodSymbol, annotName, false);
if (fieldNames == null) {
fieldNames = Collections.emptySet();
}
fieldNames = ContractUtils.trimReceivers(fieldNames);
nonnullFieldsAtExit = ContractUtils.trimReceivers(nonnullFieldsAtExit);
boolean isValidLocalPostCondition = nonnullFieldsAtExit.containsAll(fieldNames);
if (!isValidLocalPostCondition) {
fieldNames.removeAll(nonnullFieldsAtExit);
message =
String.format(
"Method is annotated with @EnsuresNonNull but fails to ensure the following fields are non-null at exit: %s",
fieldNames);
state.reportMatch(
analysis
.getErrorBuilder()
.createErrorDescription(
new ErrorMessage(ErrorMessage.MessageTypes.POSTCONDITION_NOT_SATISFIED, message),
tree,
analysis.buildDescription(tree),
state,
null));
return false;
}
return true;
}