private Description checkParamOverriding(
      List<VarSymbol> overridingParamSymbols,
      Symbol.MethodSymbol overriddenMethod,
      @Nullable LambdaExpressionTree lambdaExpressionTree,
      @Nullable MemberReferenceTree memberReferenceTree,
      VisitorState state) {
    com.sun.tools.javac.util.List<VarSymbol> superParamSymbols = overriddenMethod.getParameters();
    boolean unboundMemberRef =
        (memberReferenceTree != null)
            && ((JCTree.JCMemberReference) memberReferenceTree).kind.isUnbound();
    // if we have an unbound method reference, the first parameter of the overridden method must be
    // @NonNull, as this parameter will be used as a method receiver inside the generated lambda
    if (unboundMemberRef) {
      // there must be at least one parameter; otherwise code wouldn't compile
      if (Nullness.hasNullableAnnotation(superParamSymbols.get(0))) {
        String message =
            "unbound instance method reference cannot be used, as first parameter of "
                + "functional interface method "
                + ASTHelpers.enclosingClass(overriddenMethod)
                + "."
                + overriddenMethod.toString()
                + " is @Nullable";
        return errorBuilder.createErrorDescription(
            new ErrorMessage(MessageTypes.WRONG_OVERRIDE_PARAM, message),
            state.getPath(),
            buildDescription(memberReferenceTree));
      }
    }
    // for unbound member references, we need to adjust parameter indices by 1 when matching with
    // overridden method
    int startParam = unboundMemberRef ? 1 : 0;
    // Collect @Nullable params of overriden method
    ImmutableSet<Integer> nullableParamsOfOverriden;
    if (NullabilityUtil.isUnannotated(overriddenMethod, config)) {
      nullableParamsOfOverriden =
          handler.onUnannotatedInvocationGetExplicitlyNullablePositions(
              state.context, overriddenMethod, ImmutableSet.of());
    } else {
      ImmutableSet.Builder<Integer> builder = ImmutableSet.builder();
      for (int i = startParam; i < superParamSymbols.size(); i++) {
        // we need to call paramHasNullableAnnotation here since overriddenMethod may be defined
        // in a class file
        if (Nullness.paramHasNullableAnnotation(overriddenMethod, i)) {
          builder.add(i);
        }
      }
      nullableParamsOfOverriden = builder.build();
    }
    for (int i : nullableParamsOfOverriden) {
      int methodParamInd = i - startParam;
      VarSymbol paramSymbol = overridingParamSymbols.get(methodParamInd);
      // in the case where we have a parameter of a lambda expression, we do
      // *not* force the parameter to be annotated with @Nullable; instead we "inherit"
      // nullability from the corresponding functional interface method.
      // So, we report an error if the @Nullable annotation is missing *and*
      // we don't have a lambda with implicitly typed parameters
      boolean implicitlyTypedLambdaParam =
          lambdaExpressionTree != null
              && NullabilityUtil.lambdaParamIsImplicitlyTyped(
                  lambdaExpressionTree.getParameters().get(methodParamInd));
      if (!Nullness.hasNullableAnnotation(paramSymbol) && !implicitlyTypedLambdaParam) {
        final String message =
            "parameter "
                + paramSymbol.name.toString()
                + (memberReferenceTree != null ? " of referenced method" : "")
                + " is @NonNull, but parameter in "
                + ((lambdaExpressionTree != null || memberReferenceTree != null)
                    ? "functional interface "
                    : "superclass ")
                + "method "
                + ASTHelpers.enclosingClass(overriddenMethod)
                + "."
                + overriddenMethod.toString()
                + " is @Nullable";
        Tree errorTree;
        if (memberReferenceTree != null) {
          errorTree = memberReferenceTree;
        } else {
          errorTree = getTreesInstance(state).getTree(paramSymbol);
        }
        return errorBuilder.createErrorDescription(
            new ErrorMessage(MessageTypes.WRONG_OVERRIDE_PARAM, message),
            state.getPath(),
            buildDescription(errorTree));
      }
    }
    return Description.NO_MATCH;
  }
private Description checkParamOverriding ( List < VarSymbol > overridingParamSymbols , Symbol . MethodSymbol overriddenMethod , @ Nullable LambdaExpressionTree lambdaExpressionTree , @ Nullable MemberReferenceTree memberReferenceTree , VisitorState state ) { com . sun . tools . javac . util . List < VarSymbol > superParamSymbols = overriddenMethod . getParameters ( ) ; boolean unboundMemberRef = ( memberReferenceTree != null ) && ( ( JCTree . JCMemberReference ) memberReferenceTree ) . kind . isUnbound ( ) ; if ( unboundMemberRef ) { if ( Nullness . hasNullableAnnotation ( superParamSymbols . get ( 0 ) ) ) { String message = "unbound instance method reference cannot be used, as first parameter of " + "functional interface method " + ASTHelpers . enclosingClass ( overriddenMethod ) + "." + overriddenMethod . toString ( ) + " is @Nullable" ; return errorBuilder . createErrorDescription ( new ErrorMessage ( MessageTypes . WRONG_OVERRIDE_PARAM , message ) , state . getPath ( ) , buildDescription ( memberReferenceTree ) ) ; } } int startParam = unboundMemberRef ? 1 : 0 ; ImmutableSet < Integer > nullableParamsOfOverriden ; if ( NullabilityUtil . isUnannotated ( overriddenMethod , config ) ) { nullableParamsOfOverriden = handler . onUnannotatedInvocationGetExplicitlyNullablePositions ( state . context , overriddenMethod , ImmutableSet . of ( ) ) ; } else { ImmutableSet . Builder < Integer > builder = ImmutableSet . builder ( ) ; for ( int i = startParam ; i < superParamSymbols . size ( ) ; i ++ ) { if ( Nullness . paramHasNullableAnnotation ( overriddenMethod , i ) ) { builder . add ( i ) ; } } nullableParamsOfOverriden = builder . build ( ) ; } for ( int i : nullableParamsOfOverriden ) { int methodParamInd = i - startParam ; VarSymbol paramSymbol = overridingParamSymbols . get ( methodParamInd ) ; boolean implicitlyTypedLambdaParam = lambdaExpressionTree != null && NullabilityUtil . lambdaParamIsImplicitlyTyped ( lambdaExpressionTree . getParameters ( ) . get ( methodParamInd ) ) ; if ( ! Nullness . hasNullableAnnotation ( paramSymbol ) && ! implicitlyTypedLambdaParam ) { final String message = "parameter " + paramSymbol . name . toString ( ) + ( memberReferenceTree != null ? " of referenced method" : "" ) + " is @NonNull, but parameter in " + ( ( lambdaExpressionTree != null || memberReferenceTree != null ) ? "functional interface " : "superclass " ) + "method " + ASTHelpers . enclosingClass ( overriddenMethod ) + "." + overriddenMethod . toString ( ) + " is @Nullable" ; Tree errorTree ; if ( memberReferenceTree != null ) { errorTree = memberReferenceTree ; } else { errorTree = getTreesInstance ( state ) . getTree ( paramSymbol ) ; } return errorBuilder . createErrorDescription ( new ErrorMessage ( MessageTypes . WRONG_OVERRIDE_PARAM , message ) , state . getPath ( ) , buildDescription ( errorTree ) ) ; } } return Description . NO_MATCH ; }
checks that an overriding method does not override a {@code @Nullable} parameter with a
{@code @NonNull} parameter

@param overridingParamSymbols parameters of the overriding method
@param overriddenMethod method being overridden
@param lambdaExpressionTree if the overriding method is a lambda, the {@link
LambdaExpressionTree}; otherwise {@code null}
@param memberReferenceTree if the overriding method is a member reference (which "overrides" a
functional interface method), the {@link MemberReferenceTree}; otherwise {@code null}
@return