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