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).

This entry was posted in New Features and tagged . Bookmark the permalink.

10 Responses to New “Magic Constant” Inspection

  1. Erik van Oosten says:

    Is it possible to annotate code that lives elsewhere?

  2. Toni Menzel says:

    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. Leszek says:

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

  4. Alexey Kudravtsev says:

    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. magicprinc says:

    It’s a magic!

  6. Fredrik says:

    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. Alexey Kudravtsev says:

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

  8. Moshe says:

    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.

    Thanks!

  9. Miguel Muñoz says:

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

  10. Simon Mayerhofer says:

    I think there is a bug with methods which are returning a Magic Constant value. I opend a question on stackoverflow:
    http://stackoverflow.com/questions/18313829/is-there-a-way-to-declare-supresswarnings-to-the-declaration-of-the-method?noredirect=1#comment26875103_18313829

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>