private Description handleInvocation ( Tree tree , VisitorState state , Symbol . MethodSymbol methodSymbol , List < ? extends ExpressionTree > actualParams ) { ImmutableSet < Integer > nonNullPositions = null ; if ( NullabilityUtil . isUnannotated ( methodSymbol , config ) ) { nonNullPositions = handler . onUnannotatedInvocationGetNonNullPositions ( this , state , methodSymbol , actualParams , ImmutableSet . of ( ) ) ; } List < VarSymbol > formalParams = methodSymbol . getParameters ( ) ; if ( nonNullPositions == null ) { ImmutableSet . Builder < Integer > builder = ImmutableSet . builder ( ) ; // compute which arguments are @NonNull for ( int i = 0 ; i < formalParams . size ( ) ; i ++ ) { VarSymbol param = formalParams . get ( i ) ; if ( param . type . isPrimitive ( ) ) { Description unboxingCheck = doUnboxingCheck ( state , actualParams . get ( i ) ) ; if ( unboxingCheck != Description . NO_MATCH ) { return unboxingCheck ; } else { continue ; } } // we need to call paramHasNullableAnnotation here since the invoked method may be defined // in a class file if ( ! Nullness . paramHasNullableAnnotation ( methodSymbol , i ) ) { builder . add ( i ) ; } } nonNullPositions = builder . build ( ) ; } // now actually check the arguments // NOTE: the case of an invocation on a possibly-null reference // is handled by matchMemberSelect() for ( int argPos : nonNullPositions ) { ExpressionTree actual = null ; boolean mayActualBeNull = false ; if ( argPos == formalParams . size ( ) - 1 && methodSymbol . isVarArgs ( ) ) { // Check all vararg actual arguments for nullability if ( actualParams . size ( ) <= argPos ) { continue ; } for ( ExpressionTree arg : actualParams . subList ( argPos , actualParams . size ( ) ) ) { actual = arg ; mayActualBeNull = mayBeNullExpr ( state , actual ) ; if ( mayActualBeNull ) { break ; } } } else { actual = actualParams . get ( argPos ) ; mayActualBeNull = mayBeNullExpr ( state , actual ) ; } // This statement should be unreachable without assigning actual beforehand: Preconditions . checkNotNull ( actual ) ; // make sure we are passing a non-null value if ( mayActualBeNull ) { String message = "passing @Nullable parameter '" + state . getSourceForNode ( actual ) + "' where @NonNull is required" ; return errorBuilder . createErrorDescriptionForNullAssignment ( new ErrorMessage ( MessageTypes . PASS_NULLABLE , message ) , actual , state . getPath ( ) , buildDescription ( actual ) ) ; } } // Check for @NonNull being passed to castToNonNull (if configured) return checkCastToNonNullTakesNullable ( tree , state , methodSymbol , actualParams ) ; }
handle either a method invocation or a new invocation