Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA
-
This is a cross-post from StackOverflow, I thought I'd ask here as well in case anyone knew the answer.
I'm using a Java framework (Minecraft Forge) that injects specific objects into
public static final
fields withnull
values (through the@CapabilityInject
and@ObjectHolder
annotations). Unfortunately whenever I reference one of these fields in a context that doesn't allownull
values, the "Constant conditions & exceptions" inspection in IntelliJ IDEA warns me that the field may benull
(because it doesn't know about the injection).I know that these fields won't be
null
when they're accessed, so I'd like to disable the warning for them.Is there a way to disable the warning for a specific field or all fields in a class? Adding
@SuppressWarnings("ConstantConditions")
or//noinspection ConstantConditions
to the field doesn't remove the warning on the field access and adding the annotation to the field's class only removes the warning in that class.I'd like to avoid adding
//noinspection ConstantConditions
ornull
-checks to every location I access the fields from.
-
diesieben07 answered this in my thread on the Minecraft Forge Forums.
The solution/workaround is to create a method that always returns
null
, annotate it with@Nonnull
and@SuppressWarnings("ConstantConditions")
and then use that to initialise the field that will be injected into.For example:
public class Injection { @CapabilityInject public static final Capability<IItemHandler> CAPABILITY = getNull(); @Nonnull @SuppressWarnings({"ConstantConditions", "SameReturnValue"}) private static <T> T getNull() { return null; } public void doStuff() { // No warning Capability<IItemHandler> capability = CAPABILITY; } }
Edit: Added a missing word.
-
How many fields do you have? I can't seem to work out how to do it globally, but on a per-field basis, it seems to not flag it for me if either the field isn't final, or I use a static initialiser block, e.g.
public class Holder { public static final Object FLAGGED = null; public static final Object NOT_FLAGGED; public static Object NOT_FLAGGED_NOT_FINAL = null; static { NOT_FLAGGED = null; } } //---- import java.util.Objects; public class Main { public static void c1() { //IntelliJ: "The call to 'requireNonNull' always fails, according to its method contracts" Objects.requireNonNull(Holder.FLAGGED); } public static void c2() { //No warning Objects.requireNonNull(Holder.NOT_FLAGGED); } public static void c3() { //No warning Objects.requireNonNull(Holder.NOT_FLAGGED_NOT_FINAL); } }
-
I have quite a few fields, e.g. 55 in one class and 33 in another.
Minecraft Forge requires
final
fields for one annotation (@ObjectHolder
, the one that injects into the most fields) but not for the other (@CapabilityInject
).A static initialiser block does seem less hackish than a method that always returns
null
, but it would add a lot of clutter to some of the larger classes.
-
@choonster Hello fellow Minecraft modder! And personally I think that's worthy of a bug report to Jetbrains.
Question. What would happen if you just annotated the field
@Nonnull
and suppressed that warning?
-
There are a bunch of inspections in IDEA that you can disable, but I forget how to do it every time. I know it's in the settings somewhere, so maybe try searching for the warning?
(Also, woo, another Minecrafter! I've never touched Forge, just Bukkit.)
-
@erufael said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
I know it's in the settings somewhere, so maybe try searching for the warning?
Alt-Enter should show it
-
@pie_flavor said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
@choonster Hello fellow Minecraft modder! And personally I think that's worthy of a bug report to Jetbrains.
Question. What would happen if you just annotated the field
@Nonnull
and suppressed that warning?Hello.
Annotating the field with
@Nonnull
doesn't get rid of the warning on the field access, it only adds another warning to the field initialisation ("null
is assigned to a variable that is annotated with@NotNull
").
-
@erufael said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
There are a bunch of inspections in IDEA that you can disable, but I forget how to do it every time. I know it's in the settings somewhere, so maybe try searching for the warning?
(Also, woo, another Minecrafter! I've never touched Forge, just Bukkit.)
The inspection can be disabled globally, but there's no way to configure it for individual fields or classes.
-
@choonster said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
injects specific objects into public static final fields with null values
So the compiler doesn't fuck up "here's a compile-time-constant null pointer" by inlining it? I'd be worried about that.
-
In java, only primitives and Strings are truly compile-time constant; everything else is evaluated at runtime, at the first point you try and do anything with the class.
Injecting things into static final fields is dodgy as hell, but technically works.
You need to perform reflection on java's reflection classes to actually do it though, so it's pretty damn obvious that not only are there dragons, you're basically insulting their mothers.
-
@ben_lubar said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
@choonster said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
injects specific objects into public static final fields with null values
So the compiler doesn't fuck up "here's a compile-time-constant null pointer" by inlining it? I'd be worried about that.
It doesn't appear to, Bytecode Viewer shows
getstatic
operations on the lines where these fields are accessed.
-
@salamander said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
In java, only primitives and Strings are truly compile-time constant; everything else is evaluated at runtime, at the first point you try and do anything with the class.
Injecting things into static final fields is dodgy as hell, but technically works.
You need to perform reflection on java's reflection classes to actually do it though, so it's pretty damn obvious that not only are there dragons, you're basically insulting their mothers.I personally think it's cool that Java's reflection classes so accurately represent the underlying state that you can reflect against them as well and it Just Works . And Forge already modifies bytecode during classloading to inject custom code into classes, so they're already far over the deep end.
-
@choonster Field injection is
@choonster said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
The solution/workaround is to create a method that always returns null, annotate it with @Nonnull and @SuppressWarnings("ConstantConditions") and then use that to initialise the field that be injected into.
:puke:
I'd actually consider wrapping it with some other DI and injecting it that way. Alternatively, make a injection only class like you specified, but provide @NonNull getters for the dependency and inject that into the child class via setter or constructor injection.
-
@salamander said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
You need to perform reflection on java's reflection classes to actually do it though, so it's pretty damn obvious that not only are there dragons, you're basically insulting their mothers.
Yo dawg, I hear you like reflection, so I--
*mauled to death by angry dragons*
-
@jazzyjosh said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
@choonster Field injection is .
There's a lot of oddness to Forge, but it does make development a lot easier.
-
@jazzyjosh said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
Field injection is
Field injection is fine. Field injection into
static final
fields is
-
@dkf said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
@jazzyjosh said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
Field injection is
Field injection is fine. Field injection into
static final
fields isWhy? This isn't some corporation whose new fad is hating constructors, this is an environment that's loading plugins and doesn't want your class to have to extend their class. Again, once you're over the deep end of transforming class bytecode during loading, there's not much you can do to worsen the state.
-
@pie_flavor said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
Why?
Because static final field are candidates for compile-time inlining.
-
@dkf said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
@pie_flavor said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
Why?
Because static final field are candidates for compile-time inlining.
Well, only if they're literals. Forge injections are of custom types, not of Strings and ints.
-
@dkf said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
@pie_flavor said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
Why?
Because static final field are candidates for compile-time inlining.
But if the field gets inlined, wouldn't that mean the injection no longer works because the place the value is injected to is not the inlined place that gets used?
-
Every time I see a discussion of Minecraft modding, I am utterly horrified.
-
@weng I get both horrified and amazed. The first time I encountered this craziness was when I found out the Bukkit team re-wrote bytecode during compile time to allow overloading on return types, effectively creating "public double getHealth();" and "public int getHealth();" in the same class.
Because apparently the JVM supports that but Java as a language does not, and they were high on shrooms or something.
-
@salamander said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
@weng I get both horrified and amazed. The first time I encountered this craziness was when I found out the Bukkit team re-wrote bytecode during compile time to allow overloading on return types, effectively creating "public double getHealth();" and "public int getHealth();" in the same class.
Because apparently the JVM supports that but Java as a language does not, and they were high on shrooms or something.Bukkit had the Java mentality, i.e. 'never break anything ever for any reason', allowing plugins written for Bukkit 1.0 to remain compatible all the way to the latest release. Except of course in the 1.7 update when they changed
Server#getOnlinePlayers()
fromPlayer[]
toCollection<? extends Player>
, breaking about 80% of plugins. And they didn't do the same return-value hackery, because raisins.
In even deeper depths of hell is Spigot, which manages to stay legal because the server binaries are built on the user's computer; if they distributed the binaries themselves, it'd violate copyright since Spigot/Bukkit is a modified version of the actual jar.Meanwhile, Sponge does its runtime transformation in an extremely cool way.
-
@pie_flavor said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
@dkf said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
@jazzyjosh said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
Field injection is
Field injection is fine. Field injection into
static final
fields isWhy? This isn't some corporation whose new fad is hating constructors, this is an environment that's loading plugins and doesn't want your class to have to extend their class. Again, once you're over the deep end of transforming class bytecode during loading, there's not much you can do to worsen the state.
But you could just use constructor injection and have none of these problems :/
I mean, I guess you could use setter injection, but then it's a little non-obvious why the methods are there if there are no explicit calls.
-
@jazzyjosh said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
@pie_flavor said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
@dkf said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
@jazzyjosh said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
Field injection is
Field injection is fine. Field injection into
static final
fields isWhy? This isn't some corporation whose new fad is hating constructors, this is an environment that's loading plugins and doesn't want your class to have to extend their class. Again, once you're over the deep end of transforming class bytecode during loading, there's not much you can do to worsen the state.
But you could just use constructor injection and have none of these problems :/
I mean, I guess you could use setter injection, but then it's a little non-obvious why the methods are there if there are no explicit calls.
I use constructor injection when I'm using a language that makes it simple, like Kotlin. I use field injection in Java, because I'm lazy and it doesn't hurt anyone.
-
@pie_flavor It hurts me.
Physically.
-
@jazzyjosh said in Disable “Constant conditions & exceptions” inspection for field in IntelliJ IDEA:
@pie_flavor It hurts me.
Physically.
Why? What's wrong with it?