I'm about to commit an ugly temporary hack in order to work around a blocking issue while we wait for an external resource to be fixed. Aside from marking it with a big scary comment and a bunch of FIXMEs, I'd love to have the compiler throw an obvious warning message as a reminder so we don't forget to take this out. For example, something like:
[javac] com.foo.Hacky.java:192: warning: FIXME temporary hack to work around library bug, remove me when library is fixed!
Is there a way I can cause an intentional compiler warning with a message of my choosing? Failing that, what's the easiest thing to add to the code to throw an existing warning, with perhaps a message in a string on the offending line so it gets printed in the warning message?
EDIT: Deprecated tags don't seem to be doing anything for me:
/** * @deprecated "Temporary hack to work around remote server quirks" */ @Deprecated private void doSomeHackyStuff() { ... }
No compiler or runtime errors in eclipse or from sun javac 1.6 (running from ant script), and it's definitely executing the function.
warning(String msg): This method is used to log a WARNING message. If the logger is enabled for logging WARNING level message then the given message is forwarded to all the registered output Handler objects. Parameters: This method accepts a single parameter String which is the string message.
Usually a warning is letting you know about something that is legal, but unusual. which will always be false, and assigns i the value of 0. This generates a warning, because it's probably not what you wanted to do. But it will compile it as you wrote it, and assuming no other errors, it will build.
The @SuppressWarnings annotation type allows Java programmers to disable compilation warnings for a certain part of a program (type, field, method, parameter, constructor, and local variable). Normally warnings are good. However in some cases they would be inappropriate and annoying.
In eclipse if you right click on your Project in the Package Explorer, then go to properties -> Java Compiler -> Errors/Warnings. You can then manually change which compiler findings appear as warnings/errors/ignored etc...
I think that a custom annotation, which will be processed by the compiler, is the solution. I frequently write custom annotations to do things at runtime, but I never tried to use them at compilation time. So, I can only give you pointers on the tools you may need :
I don't know if this solution is really practicable. I'll try to implement it myself when I find some time.
Edit
I successfully implemented my solution. And as a bonus, I used java's service provider facility to simplify its use. Actually, my solution is a jar that contains 2 classes : the custom annotation and the annotation processor. To use it, just add this jar in the classpath of your project, and annotate whatever you want ! This is working fine right inside my IDE (NetBeans).
Code of the annotation :
package fr.barjak.hack; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.SOURCE) @Target({ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PACKAGE, ElementType.PARAMETER, ElementType.TYPE}) public @interface Hack { }
Code of the processor :
package fr.barjak.hack_processor; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic.Kind; @SupportedAnnotationTypes("fr.barjak.hack.Hack") public class Processor extends AbstractProcessor { private ProcessingEnvironment env; @Override public synchronized void init(ProcessingEnvironment pe) { this.env = pe; } @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { if (!roundEnv.processingOver()) { for (TypeElement te : annotations) { final Set< ? extends Element> elts = roundEnv.getElementsAnnotatedWith(te); for (Element elt : elts) { env.getMessager().printMessage(Kind.WARNING, String.format("%s : thou shalt not hack %s", roundEnv.getRootElements(), elt), elt); } } } return true; } }
To enable the resulting jar as a service provider, add the file META-INF/services/javax.annotation.processing.Processor
in the jar. This file is an acsii file that must contain the following text :
fr.barjak.hack_processor.Processor
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With