How to Intentionally Cause a Custom Java Compiler Warning Message

How to intentionally cause a custom java compiler warning message?

One technique that I've seen used is to tie this into unit testing (you do unit test, right?). Basically you create a unit test that fails once the external resource fix is achieved. Then you comment that unit test to tell others how to undo your gnarly hack once the issue is resolved.

What's really slick about this approach is that the trigger for undoing your hack is a fix of the core issue itself.

Java: How might one go about generating custom compiler warnings for method usages?

Thanks to everyone for their feedback. Looking into the compiler API, it's definitely doable (but not so simple). This article provided a good start for the compiler API. I think in the future I will look into writing an extensible rule checker. Attempting to hijack the @Deprecated annotation, by the way, will not work, as inside of the compiler it is removed along with the other "platform annotations".

For now, I'm going with the rather coarse solution of bludgeoning the programmer with a verbose checked exception. While it does clutter the code, it also avoids the complexity of actually analyzing their intent. Something like:

try {
doWork(workUnit, 15, Style.STRICT);
} catch (MakeSureYouOverrodeEverythingYouWantedToFirst warning) {
; // will never actually reach here, but you have been warned!
}

If the programmer fails to do as instructed, the output of their program can be pseudorandomly buggy, and hence rather tedious to debug. And while this solution is certainly a frowned upon hack of exception handling (including by me), it rather simply fullfils my needs.

Besides, the extra effort just might encourage the programmer to actually do what they're supposed to!

I'm still interested in hearing other ideas, if you have one.

How to give warning message in own API?

It's possible using a compiler API. You have to extend an AbstractProcessor and then make sure compiler knows about it.

Lets say we don't like programmers to swear in the source code. So, when someone defines a field with name "shit", we want to show a warning. Here is a simple implementation:

import java.util.List;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;

@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedAnnotationTypes("*")
public class Test extends AbstractProcessor {
public int shit;
public int foo;

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Set<? extends Element> rootElements = roundEnv.getRootElements();

for (Element element : rootElements) {
if (element.getKind() == ElementKind.CLASS) {
List<? extends Element> classElements = element.getEnclosedElements();

for (Element classElement : classElements) {
if (classElement.getKind() == ElementKind.FIELD) {
if (classElement.getSimpleName().contentEquals("shit")) {
processingEnv.getMessager().printMessage(
Kind.WARNING,
"How dare you to swear in the source code?!",
classElement
);
}
}
}
}
}

return false;
}

public static void main(String[] args) {
//
}
}

Now, we want to apply such a processor just for this very class, because there is an ugly bad-called field too.

Using a command line:

javac Test.java
javac -processor Test Test.java

We need to firstly build a processor and then apply it while compiling (in this case to the same file).

And this is the output we get:

Test.java:17: warning: How dare you to swear in the source code?!
public int shit;
^
1 warning

To have the same warning in Eclipse or any other IDE, it's necessary to change compiler settings so it uses this custom processor.

Update: In the comments, kapep sent a link on how to set a custom processor in Eclipse: http://kerebus.com/2011/02/using-java-6-processors-in-eclipse/


Just for the record: Exactly the same warning may be achieved by implementing interface Closeable:

import java.io.Closeable;
import java.io.IOException;

public class Test implements Closeable {
@Override
public void close() throws IOException {
// TODO Auto-generated method stub
}

public static void main(String[] args) {
new Test();
}
}

And you see the same warning:

Sample Image

Does the Java compiler has bug with assignment has no effect warning/error

But the warning and the lack of warning is correct:

  • The j = part of j = ++j has no effect; j already has the updated value in it. So a warning makes sense.
  • But the i = part of i = i++ does have an effect: After i is incremented to 1, it's assigned the value 0 — the result of the right-hand expression. So a "has no effect" warning isn't only not called for, it would be wrong.

You might have an argument for a different warning for the i case, but in general, the compiler doesn't do a huge amount of linting (checking for things that are likely logical errors but which aren't language errors).

I should note that the OpenJDK compiler doesn't issue any warnings at all for the given code. Eclipse has its own compiler, and that compiler does do more warnings, so...you might want to raise a request with them to add a warning for the i = i++ case, something like "Side effects in right-hand expression are negated by assignment" or some such.

Java compiler warning for changing a method argument variable in method body

You shouldn't reassign method parameters. Assignment to a parameter could be confused with an attempt to use it as an output parameter. Further discussion: http://sourcemaking.com/refactoring/remove-assignments-to-parameters.



Related Topics



Leave a reply



Submit