protected boolean validateAnnotationSemantics()

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;
  }