How to properly annotate java.util.function.Predicate.not

13 views
Skip to first unread message

Jon Schewe

unread,
Dec 18, 2021, 8:55:10 AM12/18/21
to Checker Framework discussion
I'm filtering null and empty strings out of a stream and having some issues with the annotations on Predicate.not. Is there a way to properly annotate Predicate.not to handle this situation with checker?

When I compile the following code I get
```
/home/jpschewe/projects/checker-bugs/src/main/java/net/mtu/eggplant/checker/PredicateNot.java:17: error: [argument] incompatible argument for parameter arg0 of filter.
        .filter(Predicate.not(PredicateNot::isBlank)) //
                             ^
  found   : @Initialized @NonNull Predicate<@Initialized @NonNull String>
  required: @Initialized @NonNull Predicate<? extends @Initialized @Nullable Object super @Initialized @Nullable String>
```

```java
package net.mtu.eggplant.checker;

import java.util.*;
import java.util.function.*;
import java.util.stream.*;

import org.checkerframework.checker.nullness.qual.*;

public class PredicateNot {

  public static void function(final @Nullable String @Nullable [] headerRow) {
    final Collection<String> headerNames;
    if (null == headerRow) {
      headerNames = Collections.emptyList();
    } else {
      headerNames = Arrays.asList(headerRow).stream() //
        .filter(Predicate.not(PredicateNot::isBlank)) //
        .collect(Collectors.toList());
    }
  }

  // from apache commons lang3 StringUtils
  @EnsuresNonNullIf(expression="#1", result=false)
  public static boolean isBlank(final @Nullable CharSequence cs) {
    if(null == cs) {
      return true;
    }
    
    final int strLen = length(cs);
    if (strLen == 0) {
      return true;
    }
    for (int i = 0; i < strLen; i++) {
      if (!Character.isWhitespace(cs.charAt(i))) {
        return false;
      }
    }
    return true;
  }

  // from apache commons lang3 StringUtils
  public static int length(final @Nullable CharSequence cs) {
    return cs == null ? 0 : cs.length();
  }
  
}
```

Suzanne Millstein

unread,
Jan 5, 2022, 6:42:21 PM1/5/22
to Jon Schewe, Checker Framework discussion
Hi Jon,

This code requires Java 8 type argument inference, so the Checker Framework incorrectly issues an error here.  We are working on fixing this as tracked by https://github.com/typetools/checker-framework/issues/979, but it's a huge undertaking.  In the meantime, you can add an explicit type argument to get this code to pass:

```
.filter(Predicate.<@Nullable CharSequence>not(PredicateNot::isBlank)) //
```

-Suzanne

--

---
You received this message because you are subscribed to the Google Groups "Checker Framework discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to checker-framework-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/checker-framework-discuss/9f8fba66781402d1420a48eec5acb81cf775e915.camel%40mtu.net.
Reply all
Reply to author
Forward
0 new messages