Compiling with System.getProperty can throw NPE rather than useful error
niloc132 opened this issue · comments
GWT version: 2.9, 2.10, 2.11
Browser (with version): n/a
Operating System: any
Description
Both binding properties and configuration properties (single value only) can be used to provide strings that can be read at compile time via System.getProperty
, but if no value is set on a configuration property, a NPE will occur in the compiler.
Cases that should be supported:
- Multi-value configuration properties correctly emit an error:
[ERROR] Errors in 'com/google/gwt/dev/jjs/test/SystemGetPropertyTest.java' [ERROR] Line 42: Property 'someConfigProperty' is multivalued. Multivalued properties are not supported by System.getProperty().
- No property defined in .gwt.xml, either binding or configuration results in default value being used (if provided), otherwise error:
[ERROR] Errors in 'com/google/gwt/dev/jjs/test/SystemGetPropertyTest.java' [ERROR] Line 45: Property 'unknownProperty' is not defined.
- Configuration properties defined without a value however result in an NPE:
Compiling 1 permutation [ERROR] An internal compiler exception occurred com.google.gwt.dev.jjs.InternalCompilerException: Unexpected error during visit. at com.google.gwt.dev.jjs.ast.JVisitor.translateException(JVisitor.java:111) at com.google.gwt.dev.jjs.ast.JModVisitor.acceptImmutable(JModVisitor.java:313) at com.google.gwt.dev.jjs.ast.JMethodCall.visitChildren(JMethodCall.java:275) at com.google.gwt.dev.jjs.ast.JMethodCall.traverse(JMethodCall.java:266) at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361) at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273) at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265) at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:118) at com.google.gwt.dev.jjs.ast.JExpressionStatement.traverse(JExpressionStatement.java:42) at com.google.gwt.dev.jjs.ast.JModVisitor$ListContext.traverse(JModVisitor.java:88) at com.google.gwt.dev.jjs.ast.JModVisitor.acceptWithInsertRemove(JModVisitor.java:331) at com.google.gwt.dev.jjs.ast.JBlock.traverse(JBlock.java:94) at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361) at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273) at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:139) at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:135) at com.google.gwt.dev.jjs.ast.JMethodBody.traverse(JMethodBody.java:83) at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361) at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273) at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265) at com.google.gwt.dev.jjs.ast.JMethod.visitChildren(JMethod.java:786) at com.google.gwt.dev.jjs.ast.JMethod.traverse(JMethod.java:778) at com.google.gwt.dev.jjs.ast.JModVisitor$ListContextImmutable.traverse(JModVisitor.java:169) at com.google.gwt.dev.jjs.ast.JModVisitor.acceptWithInsertRemoveImmutable(JModVisitor.java:336) at com.google.gwt.dev.jjs.ast.JClassType.traverse(JClassType.java:147) at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361) at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273) at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265) at com.google.gwt.dev.jjs.ast.JProgram.visitModuleTypes(JProgram.java:1284) at com.google.gwt.dev.jjs.ast.JProgram.traverse(JProgram.java:1249) at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361) at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273) at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265) at com.google.gwt.dev.jjs.impl.ResolvePermutationDependentValues.execImpl(ResolvePermutationDependentValues.java:163) at com.google.gwt.dev.jjs.impl.ResolvePermutationDependentValues.exec(ResolvePermutationDependentValues.java:113) at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.compilePermutation(JavaToJavaScriptCompiler.java:333) at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.compilePermutation(JavaToJavaScriptCompiler.java:272) at com.google.gwt.dev.CompilePerms.compile(CompilePerms.java:198) at com.google.gwt.dev.ThreadedPermutationWorkerFactory$ThreadedPermutationWorker.compile(ThreadedPermutationWorkerFactory.java:50) at com.google.gwt.dev.PermutationWorkerFactory$Manager$WorkerThread.run(PermutationWorkerFactory.java:74) at java.base/java.lang.Thread.run(Thread.java:829) Caused by: java.lang.NullPointerException at com.google.gwt.thirdparty.guava.common.base.Preconditions.checkNotNull(Preconditions.java:212) at com.google.gwt.thirdparty.guava.common.base.Joiner.toString(Joiner.java:447) at com.google.gwt.thirdparty.guava.common.base.Joiner.appendTo(Joiner.java:110) at com.google.gwt.thirdparty.guava.common.base.Joiner.appendTo(Joiner.java:154) at com.google.gwt.thirdparty.guava.common.base.Joiner.join(Joiner.java:197) at com.google.gwt.thirdparty.guava.common.base.Joiner.join(Joiner.java:186) at com.google.gwt.dev.jjs.impl.ResolvePermutationDependentValues$ValueReplacer.propertyValueExpression(ResolvePermutationDependentValues.java:79) at com.google.gwt.dev.jjs.impl.ResolvePermutationDependentValues$ValueReplacer.endVisit(ResolvePermutationDependentValues.java:73) at com.google.gwt.dev.jjs.ast.JPermutationDependentValue.traverse(JPermutationDependentValue.java:112) at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361) at com.google.gwt.dev.jjs.ast.JModVisitor.acceptImmutable(JModVisitor.java:305) ... 39 more [ERROR] at SystemGetPropertyTest.java(44): System.getProperty("someConfigPropertyUnset", "bar") [ERROR] at SystemGetPropertyTest.java(44): Assert.assertEquals("bar", System.getProperty("someConfigPropertyUnset", "bar")) [ERROR] at SystemGetPropertyTest.java(44): Assert.assertEquals("bar", System.getProperty("someConfigPropertyUnset", "bar")) [ERROR] at SystemGetPropertyTest.java(41): { Assert.assertEquals("foo", "foo"); Assert.assertEquals("foo", "foo"); Assert.assertEquals("bar", System.getProperty("someConfigPropertyUnset", "bar")); } [ERROR] at SystemGetPropertyTest.java(41): { Assert.assertEquals("foo", "foo"); Assert.assertEquals("foo", "foo"); Assert.assertEquals("bar", System.getProperty("someConfigPropertyUnset", "bar")); } [ERROR] at SystemGetPropertyTest.java(41): com.google.gwt.dev.jjs.test.SystemGetPropertyTest.testConfigurationProperties()V [ERROR] at SystemGetPropertyTest.java(23): com.google.gwt.dev.jjs.test.SystemGetPropertyTest (extends GWTTestCase) [ERROR] at Unknown(0): <JProgram> [ERROR] Unrecoverable exception, shutting down
Steps to reproduce
Declare a configuration property, but don't assign it (for example, one .gwt.xml for a library might declare it, and a downstream app may choose to set it):
<define-configuration-property name="someConfigPropertyUnset" is-multi-valued="false"/>
Attempt to use that property in GWT/Java sources without a default:
assertEquals("bar", System.getProperty("someConfigPropertyUnset", "bar"));
Expected: default value is used
Actual: NPE is thrown during compilation
Known workarounds
The simplest workaround is to just define a "this is unset" value for the configuration property, but that means that shared code has two places to change the default.
<set-configuration-property name="someConfigPropertyUnset" value="this-is-unset" />