Hi there, if the NPE management is being worked on, I'd like to again advocate for a way to switch on a “default-safe” mode, be it a compiler switch, an annotation, whatever.
With this mode on, the compiler would use the “safe“ (more precisely, null-propagation) mode by default all the time without forcing the programmer to use all those pesky question marks explicitly (or, as I do, to add ASTTs to make exp.safe=true everywhere, along with a couple of other tricks to turn NPEs which I hate very much to the consistent ubiquitous null-propagation which I very strongly prefer). (As for the problem with external libraries, I am currently considering wrapping all the external library calls into a try/catch harness which would catch NPE and return a null in this case. I would, actually; but the one problem I haven't solved yet is to recognise an external library call; at the moment a foo.bar() is being compiled, nobody knows whether the bar method is my own compiled code or an external library, for nobody knows what foo contains :/ Perhaps this might be solved at runtime though, checking at the moment a method is being dispatched?) Thanks and all the best, OC > On 19 Sep 2021, at 17:46, MG <mg...@arscreat.com> wrote: > > Hi guys, > > I don't encounter a lot of NPE in my code and have been using a lot of > @CompileStatic so am not sure - but did Groovy have a pretty printed NPE > output at some point, that showed exactly where the null-pointer was located > in a call chain ?-) > In any case, could we supply that (at least in @TypeChecked/@CompileDynamic) ? > > I believe that the many measures languages have been and are taking to avoid > NPEs from occuring, often times are heading in the wrong direction and would > not be necessary if the exact location of a NPE in a call chain was known > when the NPE gets printed :-) > > > The JVM has been improved in this regard since OpenJDK 14: > https://openjdk.java.net/jeps/358 <https://openjdk.java.net/jeps/358> > https://www.baeldung.com/java-14-nullpointerexception > <https://www.baeldung.com/java-14-nullpointerexception> > https://bugs.openjdk.java.net/browse/JDK-8233014 > <https://bugs.openjdk.java.net/browse/JDK-8233014> > > The messages produced alas look pretty ugly for @CompileStatic Groovy (see > below), due to its predominant use of properties instead of fields, and the > original goal of JEP 358 to print the complete call chain (access path) seems > to have been dropped... > > > In Groovy 3.0.9 under OpenJDK 16: > @Newify(pattern=/[A-Z][A-Za-z0-9_]*/) > //@CompileStatic > class HelpfulNullPointerExceptionTest { > > static class X { > X x; String s > X(X x, String s = null) { this.x = x; this.s = s } > @Override String toString() { "X($s,$x)" } > } > > @Test > void nullPointerInCallChain() { > final x = X(X(X(X(null,"X-Men")))) > println "x.x.x.x=$x.x.x.x" > x.x.x = null > /* > * OpenJDK 16 (Eclipse jdk-16.0.2.7-hotspot) (Note: > -XX:+ShowCodeDetailsInExceptionMessages is now always on by default) > ** @CompileDynamic: java.lang.NullPointerException: Cannot get > property 'x' on null object > ** @CompileStatic: java.lang.NullPointerException: Cannot invoke > "simple.groovy.HelpfulNullPointerExceptionTest$X.getX()" because the return > value of "simple.groovy.HelpfulNullPointerExceptionTest$X.getX()" is null > ** Would hope for something like (or its pretty-printed > equivalent): java.lang.NullPointerException: Cannot get property 'x.x.x.x' on > null object > */ > println "x.x.x.x=$x.x.x.x" > } > > @Canonical static class A { String a } > @Canonical static class B { A a } > @Canonical static class C { B b } > @Canonical static class D { C c } > > @Test > void nullPointerInCallChain2() { > final x = D(C(B(A("aha!")))) > println "x.c.b.a=$x.c.b.a" > /* > * OpenJDK 16 (Eclipse jdk-16.0.2.7-hotspot) > ** @CompileDynamic: java.lang.NullPointerException: Cannot get > property 'b' on null object > ** @CompileStatic: java.lang.NullPointerException: Cannot invoke > "simple.groovy.HelpfulNullPointerExceptionTest$C.getB()" because the return > value of "simple.groovy.HelpfulNullPointerExceptionTest$D.getC()" is null > ** Would hope for something like (or its pretty-printed > equivalent): java.lang.NullPointerException: Cannot get property 'x.c.b.a' on > null object > */ > x.c = null > println "x.c.b.a=$x.c.b.a" > } > } > > Cheers, > mg > >