New “Magic Constant” Inspection

Have you ever cursed an API which uses magic integer constants instead of the proper enumeration?

What should I pass as the titleJustification parameter here? 0 or 1?
Can I pass “42” for the titlePosition parameter? Even Javadoc won’t know.
Actually, you must use one of the constants in the TitledBorder class to make the code correct:

I call these constants “magic” because sometimes it is far from easy to figure them out.

Here comes a new “Magic constant” inspection that looks for usages of methods/variables which expect “magic constants” as their arguments:

Then it helps you to replace plain numbers or strings with a proper magic constant:

How does it know if the method expects a “magic constant” argument?

It seems that a number of JDK Swing methods is annotated with a special form of the @beaninfo javadoc tag, which provides the information about allowed values:

Unfortunately, only a handful of the JDK methods are annotated this way. The majority of the rest method parameters are left in the dark.
So we’ve created our own @MagicConstant annotation and annotated some JDK methods and our own code:

As you can see, you just enumerate constant names which can be used in this place.
IntelliJ IDEA then checks arguments of method calls, variable assignments, etc. and warns if expressions involved are not valid, considering the data flow.

@MagicConstant annotation can do the following:

@MagicConstant(intValues = {Const1, Const2,...}) or
@MagicConstant(stringValues = {Const1, Const2,...})

Tells IntelliJ IDEA that only one of the listed constants can be used as an argument.

@MagicConstant(valuesFromClass = ClassName.class)

Tells IntelliJ IDEA that allowed value for the argument is one of the public static final fields declared in the class “ClassName”.

@MagicConstant(flags = {Const1, Const2,...})
Tells IntelliJ IDEA that one or several of the listed integer constants can be combined with the bitwise OR operator.

You can also apply @MagicConstant to another annotation class to create an alias you can use everywhere:

How to make it work in my setup?

1. @MagicConstant annotation sits in the IDEA_HOME/lib/annotations.jar. You have to attach it to your project in Project Structure|Global Libraries dialog.
2. External annotations for the JDK methods sit in the IDEA_HOME/lib/jdkAnnotations.jar. It is attached automatically to your JDK as soon as you enable the “Magic Constant” inspection (see the Project Structure | SDKs | Annotations tab).

Comments below can no longer be edited.

10 Responses to New “Magic Constant” Inspection

  1. Avatar

    Erik van Oosten says:

    February 15, 2012

    Is it possible to annotate code that lives elsewhere?

  2. Avatar

    Toni Menzel says:

    February 15, 2012

    Good one!
    Any reason why the annotation.jar is not on Maven Central ?
    Can i republish it (possibly under different groupId to use existing pipelines) to Central if Jetbrains is not interested in doing so ?

  3. Avatar

    Leszek says:

    February 15, 2012

    Google Annotation Gallery seems to be good place for it 🙂 http://code.google.com/p/gag/

  4. Avatar

    Alexey Kudravtsev says:

    February 16, 2012

    It is possible to annotate any code, including libraries with external annotations. Please see http://www.jetbrains.com/idea/webhelp/using-external-annotations.html

  5. Avatar

    magicprinc says:

    February 16, 2012

    It’s a magic!

  6. Avatar

    Fredrik says:

    February 16, 2012

    Might be useful for usage and clarifications of existing code libraries and APIs, but “now” that enums are available and there is no reason not to use enums instead of magic integers with an excusing annotation (except maybe in some cases for performance reasons in Android).

  7. Avatar

    Alexey Kudravtsev says:

    February 16, 2012

    @Tony Menzel You are welcome to do so (annotations.jar are Apache 2 licensed after all) but under the different groupid please.

  8. Avatar

    Moshe says:

    March 6, 2012

    Great feature.

    A small issue – in the following example, Magic Constant inspection warns about “cal.get(Calendar.MONTH)” that it should be Calendar.JANUARY, Calendar.FEBRUARY, …

    Calendar cal = Calendar.getInstance();
    cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DATE), 0, 0, 0);

    Could you please think of how to improve or add a way to suppress the inspection without disabling it.


  9. Avatar

    Miguel Muñoz says:

    April 6, 2012

    Wonderful enhancement! I love it. (I’ve always hated named constants. enums are so much cleaner.) Thanks.

  10. Avatar

    Simon Mayerhofer says:

    August 19, 2013

    I think there is a bug with methods which are returning a Magic Constant value. I opend a question on stackoverflow:

Discover more