protected abstract void validateOverridingRules()

in nullaway/src/main/java/com/uber/nullaway/handlers/AbstractFieldContractHandler.java [110:240]


  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.
   * @param methodAnalysisContext The MethodAnalysisContext object
   */
  protected abstract boolean validateAnnotationSemantics(
      MethodTree tree, MethodAnalysisContext methodAnalysisContext);

  /**
   * 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.
   * @param methodAnalysisContext The MethodAnalysisContext object
   */
  protected boolean validateAnnotationSyntax(
      Set<String> content, MethodTree tree, MethodAnalysisContext methodAnalysisContext) {
    String message;
    VisitorState state = methodAnalysisContext.state();
    NullAway analysis = methodAnalysisContext.analysis();
    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 {
      Symbol.ClassSymbol classSymbol =
          castToNonNull(ASTHelpers.enclosingClass(methodAnalysisContext.methodSymbol()));
      for (String fieldName : content) {
        if (isThisDotStaticField(classSymbol, fieldName)) {

          message =
              "Cannot refer to static field "
                  + fieldName.substring(THIS_NOTATION.length())
                  + " using this.";
          state.reportMatch(
              analysis
                  .getErrorBuilder()
                  .createErrorDescription(
                      new ErrorMessage(ErrorMessage.MessageTypes.ANNOTATION_VALUE_INVALID, message),
                      tree,
                      analysis.buildDescription(tree),
                      state,
                      null));
          return false;
        }
        VariableElement field = getFieldOfClass(classSymbol, fieldName);
        if (field != null) {
          if (field.getModifiers().contains(Modifier.STATIC)) {
            continue;
          }
        }
        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);
          }
        }
        field = getFieldOfClass(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;
  }