0

As we all know, we can automagicaly generate code using custom annotations and Java annotation processors as guys at project Lombook do. But can we remove the annotated code from compiled sources ?

I've tried searching the web for it, but only things that appear are "generate your code" topics and tutorials on "how to generate server with one annotation". It came to my mind while I was searching for ways to "compile out" debug messages from prod app. I can understand, that having the debug/test and production code is not a good practice, but sometimes it is needed to keep things simple. I think of few scenarios for this:

  1. make debug only, laggy code used in developer-only version of code that can have different levels of importance for example:
@Debug(0) void cpuLightFunction(){}
@Debug(100) void cpuHeavyFunction(){} 

void doWork(){
   cpuLightFunction();
   cpuHeavyFunction();
}

In annotation processing step we could use some option to define max level of @Debug annotations that would be compiled. Any usage of @Debug with higher level would produce error or warning in the same way as @Deprecated

  1. platform specyfic code versions - create custom @Platform(ANDROID) void doSomething() and @Plaform(IOS) void doSomething functions that run only on given plaform to get rid of polymorphic void doSomething(AndroidPlatform) or void doSomethingAndroid() code

  2. have parts of code that are conditionally compiled:

@Optional("NetworkStub")
class NetworkStub{
   // ...
}

@Optional("PaymentStub")
class PaymentStub{
   // ...
}

and only use compiler/annotation processor options to enable/disable parts of the code, for example -Aoptional="NetworkStub" that would only compile code related to NetworkStub in the code and remove all code touching PaymentStub.

Robin Green
  • 32,079
  • 16
  • 104
  • 187
Tooster
  • 322
  • 3
  • 14
  • Well, instead of removing that code you could add some glue code that selects needs to be "compiled in" like Lombok is doing it. That might be simpler than having mutliple calls that might be removed in the end - i.e. that first example might cause a lot of bugs due to confusion on which method will be kept. – Thomas Aug 19 '19 at 15:48
  • 1. This would be simpler with a `WorkDoer` interface, where you use a debug implementation in one context, and a production one in the other. – BeUndead Aug 19 '19 at 15:50
  • Alternatively or additionally you could or even should use interfaces for parts that need to be selected based on some property, e.g. any platform specific stuff. Just provide a dependency (jar) for each platform and only load the one that's needed. That would apply to "optional" dependencies as well - have a look at CDI for one framework that's meant to do exactly that. – Thomas Aug 19 '19 at 15:50
  • I expect Byte Buddy can do it. Haven't used it much – Michael Aug 19 '19 at 15:52
  • Possible duplicate of [Java (Eclipse) - Conditional compilation](https://stackoverflow.com/questions/5402974/java-eclipse-conditional-compilation) – Robin Green Aug 19 '19 at 16:33

1 Answers1

0

You can do this by writing an annotation processor that traverses and modifies the program's AST (abstract syntax tree) during compilation, before code generation.

That is how Project Lombok works.

This question is a near-duplicate of How to write a Java annotation processor?, but the accepted answer to that question says it's impossible, which is factually wrong.

mernst
  • 7,437
  • 30
  • 45