docs: 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);
    }