> Makes sense. We have had good experiences with spotless and spotbugs so I think it can work as a separate CI job.
Sounds good. I can set that up next week then. > You might also benefit from having a cache (not just up-to-date checking). Actually the project as a whole would benefit from a shared distributed cache I'm guessing. Is there a JIRA or something for that? I feel like this has been discussed before, but I don't remember the details. On Fri, Mar 12, 2021 at 3:57 PM Kenneth Knowles <k...@apache.org> wrote: > > > On Fri, Mar 12, 2021 at 3:05 PM Kyle Weaver <kcwea...@google.com> wrote: > >> > On the other hand, modifying core is a less common developer use case >> so passing a couple flags to skip it seems manageable for those people who >> are touching the core. >> >> Every time I check out a new git branch that has a modified core compared >> to the previous branch (i.e. almost always) it needs to be rebuilt, and >> runs the null checker again. I usually use Intellij to run tests, and I >> haven't figured out how to make it pass skipCheckerFramework by default, so >> I've resorted to just setting "skipCheckerFramework=true" in my >> gradle.properties. >> > > Makes sense. We have had good experiences with spotless and spotbugs so I > think it can work as a separate CI job. > > You might also benefit from having a cache (not just up-to-date checking). > Actually the project as a whole would benefit from a shared distributed > cache I'm guessing. > > Kenn > > >> >> On Fri, Mar 12, 2021 at 2:53 PM Kenneth Knowles <k...@apache.org> wrote: >> >>> I'm OK with this as long as they are treated as strictly merge blocking. >>> >>> On the other hand, modifying core is a less common developer use case so >>> passing a couple flags to skip it seems manageable for those people who are >>> touching the core. >>> >>> Kenn >>> >>> On Fri, Mar 12, 2021 at 1:19 PM Pablo Estrada <pabl...@google.com> >>> wrote: >>> >>>> Does it make sense to add a Jenkins precommit suite that runs null >>>> checking exclusively? >>>> >>>> On Fri, Mar 12, 2021 at 11:57 AM Kyle Weaver <kcwea...@google.com> >>>> wrote: >>>> >>>>> I don't mind fixing my code or suppressing nullness errors, but the >>>>> cost of the null check itself is hurting my productivity. In the best >>>>> case, >>>>> null checks add about ten minutes to the build time for large modules >>>>> like :sdks:java:core. In the worst case, they cause my build to fail >>>>> altogether, because the framework logs a warning that "Memory constraints >>>>> are impeding performance," which is interpreted by -Wall as an error. It >>>>> might not be a problem on big machines with a lot of memory, but on my >>>>> Macbook, and on the Github Actions executors it is a real problem. >>>>> https://issues.apache.org/jira/browse/BEAM-11837 >>>>> >>>>> Since nullness checks seem to work fine for now on Jenkins, I propose >>>>> making them opt-in rather than opt-out, and only run them on Jenkins by >>>>> default. >>>>> >>>>> On Tue, Mar 2, 2021 at 12:13 PM Kyle Weaver <kcwea...@google.com> >>>>> wrote: >>>>> >>>>>> Can you try adding the generated classes to generatedClassPatterns in >>>>>> the JavaNatureConfiguration? >>>>>> >>>>>> >>>>>> https://github.com/apache/beam/blob/03b883b415d27244ddabb17a0fb5bab147b86f89/buildSrc/src/main/groovy/org/apache/beam/gradle/BeamModulePlugin.groovy#L92 >>>>>> >>>>>> >>>>>> On Tue, Mar 2, 2021 at 12:05 AM Reuven Lax <re...@google.com> wrote: >>>>>> >>>>>>> I'm running into a problem with this check. I added a >>>>>>> protocol-buffer file to a module (google-cloud-platform) that previously >>>>>>> did have any protobuf files in it. The generated files contain lines >>>>>>> that >>>>>>> violate this null checker, so they won't compile. I can't annotate the >>>>>>> files, because they are codegen files. I tried adding the package to >>>>>>> spotbugs-filter.xml, but that didn't help. >>>>>>> >>>>>>> Any suggestions? >>>>>>> >>>>>>> Reuven >>>>>>> >>>>>>> On Fri, Jan 22, 2021 at 10:38 AM Brian Hulette <bhule...@google.com> >>>>>>> wrote: >>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> On Fri, Jan 22, 2021 at 1:18 AM Jan Lukavský <je...@seznam.cz> >>>>>>>> wrote: >>>>>>>> >>>>>>>>> Hi, >>>>>>>>> >>>>>>>>> I'll give my two cents here. >>>>>>>>> >>>>>>>>> I'm not 100% sure that the 1-5% of bugs are as severe as other >>>>>>>>> types of bugs. Yes, throwing NPEs at user is not very polite. On the >>>>>>>>> other >>>>>>>>> hand, many of these actually boil down to user errors. Then we might >>>>>>>>> ask >>>>>>>>> what a correct solution would be. If we manage to figure out what the >>>>>>>>> actual problem is and tell user what specifically is missing or going >>>>>>>>> wrong, that would be just awesome. On the other hand, if a tool used >>>>>>>>> for >>>>>>>>> avoiding "unexpected" NPEs forces us to code >>>>>>>>> >>>>>>>>> Object value = Objects.requireNonNull(myNullableObject); // or >>>>>>>>> similar using Preconditions >>>>>>>>> value.doStuff(); >>>>>>>>> >>>>>>>>> instead of just >>>>>>>>> >>>>>>>>> myNullableObject.doStuff() >>>>>>>>> >>>>>>>>> what we actually did, is a) made a framework happy, and b) changed >>>>>>>>> a line at which NPE is thrown by 1 (and yes, internally prevented JVM >>>>>>>>> from >>>>>>>>> thrown SIGSEGV at itself, but that is deeply technical thing). Nothing >>>>>>>>> changed semantically, from user perspective. >>>>>>>>> >>>>>>>> I'd argue there's value in asking Beam developers to make that >>>>>>>> change. It makes us acknowledge that there's a possibility >>>>>>>> myNullableObject >>>>>>>> is null. If myNullableObject being null is something relevant to the >>>>>>>> user >>>>>>>> we would likely want to wrap it in some other exception or provide a >>>>>>>> more >>>>>>>> useful message than just NPE(!!). >>>>>>>> >>>>>>>>> >>>>>>>>> Now, given that the framework significantly rises compile time >>>>>>>>> (due to all the checks), causes many "bugs" being reported by static >>>>>>>>> code >>>>>>>>> analysis tools (because the framework adds @Nonnull default >>>>>>>>> annotations >>>>>>>>> everywhere, even when Beam's code actually counts with nullability of >>>>>>>>> a >>>>>>>>> field), and given how much we currently suppress these checks ($ git >>>>>>>>> grep >>>>>>>>> BEAM-10402 | wc -l -> 1981), I'd say this deserves a deeper >>>>>>>>> discussion. >>>>>>>>> >>>>>>>> The reason there are so many suppressions is that fixing all the >>>>>>>> errors is a monumental task. Rather than addressing them all, Kenn >>>>>>>> programmatically added suppressions for classes that failed the checks >>>>>>>> ( >>>>>>>> https://github.com/apache/beam/pull/13261). This allowed us to >>>>>>>> start running the checker on the code that passes it while the errors >>>>>>>> are >>>>>>>> fixed. >>>>>>>> >>>>>>>>> Jan >>>>>>>>> >>>>>>>>> >>>>>>>>> On 1/20/21 10:48 PM, Kenneth Knowles wrote: >>>>>>>>> >>>>>>>>> Yes, completely sound nullability checking has been added to the >>>>>>>>> project via checkerframework, based on a large number of NPE bugs >>>>>>>>> (1-5% >>>>>>>>> depending on how you search, but many other bugs likely attributable >>>>>>>>> to >>>>>>>>> nullness-based design errors) which are extra embarrassing because >>>>>>>>> NPEs >>>>>>>>> have were essentially solved, even in practice for Java, well before >>>>>>>>> Beam >>>>>>>>> existed. >>>>>>>>> >>>>>>>>> Checker framework is a pluggable type system analysis with some >>>>>>>>> amount of control flow sensitivity. Every value has a type that is >>>>>>>>> either >>>>>>>>> nullable or not, and certain control structures (like checking for >>>>>>>>> null) >>>>>>>>> can alter the type inside a scope. The best way to think about it is >>>>>>>>> to >>>>>>>>> consider every value in the program as either nullable or not, much >>>>>>>>> like >>>>>>>>> you think of every value as either a string or not, and to view method >>>>>>>>> calls as inherently stateful/nondetermistic. This can be challenging >>>>>>>>> in esoteric cases, but usually makes the overall code health better >>>>>>>>> anyhow. >>>>>>>>> >>>>>>>>> Your example illustrates how problematic the design of the Java >>>>>>>>> language is: the analysis cannot assume that `getDescription` is a >>>>>>>>> pure >>>>>>>>> function, and neither should you. Even if it is aware of >>>>>>>>> boolean-short-circuit it would not be sound to accept this code. >>>>>>>>> There is >>>>>>>>> an annotation for this in the cases where it is true (like >>>>>>>>> proto-generate >>>>>>>>> getters): >>>>>>>>> https://checkerframework.org/api/org/checkerframework/dataflow/qual/Pure.html >>>>>>>>> >>>>>>>>> The refactor for cases like this is trivial so there isn't a lot >>>>>>>>> of value to thinking too hard about it. >>>>>>>>> >>>>>>>>> if (statusCode.equals(Code.INVALID_ARGUMENT) >>>>>>>>> @Nullable String desc = statusCode.toStatus().getDescription(); >>>>>>>>> if (desc != null && desc.contains("finalized")) { >>>>>>>>> return false; >>>>>>>>> } >>>>>>>>> } >>>>>>>>> >>>>>>>>> To a casual eye, this may look like a noop change. To the analysis >>>>>>>>> it makes all the difference. And IMO this difference is real. Humans >>>>>>>>> may >>>>>>>>> assume it is a noop and humans would be wrong. So many times when you >>>>>>>>> think/expect/hope that `getXYZ()` is a trivial getter method you later >>>>>>>>> learn that it was tweaked for some odd reason. I believe this code >>>>>>>>> change >>>>>>>>> makes the code better. Suppressing these errors should be >>>>>>>>> exceptionally >>>>>>>>> rare, and never in normal code. It is far better to improve your code >>>>>>>>> than >>>>>>>>> to suppress the issue. >>>>>>>>> >>>>>>>>> It would be very cool for the proto compiler to annotate enough >>>>>>>>> that new-and-improved type checkers could make things more convenient. >>>>>>>>> >>>>>>>>> Kenn >>>>>>>>> >>>>>>>>> On Mon, Jan 11, 2021 at 8:53 PM Reuven Lax <re...@google.com> >>>>>>>>> wrote: >>>>>>>>> >>>>>>>>>> I can use that trick. However I'm surprised that the check >>>>>>>>>> appears to be so simplistic. >>>>>>>>>> >>>>>>>>>> For example, the following code triggers the check on >>>>>>>>>> getDescription().contains(), since getDescription returns a Nullable >>>>>>>>>> string. However even a simplistic analysis should realize that >>>>>>>>>> getDescription() was checked for null first! I have a dozen or so >>>>>>>>>> cases >>>>>>>>>> like this, and I question how useful such a simplistic check it will >>>>>>>>>> be. >>>>>>>>>> >>>>>>>>>> if (statusCode.equals(Code.INVALID_ARGUMENT) && >>>>>>>>>> statusCode.toStatus().getDescription() != null && >>>>>>>>>> statusCode.toStatus().getDescription().contains("finalized")) { >>>>>>>>>> return false; >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On Mon, Jan 11, 2021 at 8:32 PM Boyuan Zhang <boyu...@google.com> >>>>>>>>>> wrote: >>>>>>>>>> >>>>>>>>>>> Yeah it seems like the checker is enabled: >>>>>>>>>>> https://issues.apache.org/jira/browse/BEAM-10402. I used >>>>>>>>>>> @SuppressWarnings({"nullness" )}) to suppress the error when I >>>>>>>>>>> think it's >>>>>>>>>>> not really a concern. >>>>>>>>>>> >>>>>>>>>>> On Mon, Jan 11, 2021 at 8:28 PM Reuven Lax <re...@google.com> >>>>>>>>>>> wrote: >>>>>>>>>>> >>>>>>>>>>>> Has extra Nullable checking been enabled in the Beam project? I >>>>>>>>>>>> have a PR that was on hold for several months, and I'm struggling >>>>>>>>>>>> now with >>>>>>>>>>>> compile failing to complaints about assigning something that is >>>>>>>>>>>> nullable to >>>>>>>>>>>> something that is not nullable. Even when the immediate control >>>>>>>>>>>> flow makes >>>>>>>>>>>> it absolutely impossible for the variable to be null. >>>>>>>>>>>> >>>>>>>>>>>> Has something changed here? >>>>>>>>>>>> >>>>>>>>>>>> Reuven >>>>>>>>>>>> >>>>>>>>>>>