Overview
Every Programm talks about something. A Webshop will talk about Products, Customers, Orders and Payment. Programms can also talk about other Programms in the same way (Metaprogramming). The Livecycle from writing code to it being executed is long and there are many different opportunities for metaprogramming. Each having different tradeoffs depending on the context.
The code written with this Library runs in the java compiler. It takes in source files and outputs class files. Derivandi can do two things:
Annotations
Writing CustomerEntitiy or @Entity Customer represents the same information.
The structured way of expressing metadata as Annotations is just easier to process by tools.
Annotations don’t do anything on their own.
The most relevant properties of Annotations for compile time meta programming are:
-
@Retentionconfigures how long an Annotations should be kept in the livecycle.-
SOURCEAnnotations are discarded at the end of the compilation -
CLASSAnnotations are written in the class files, but not read by the java runtime -
RUNTIMEAnnotations are always present
-
-
@Targetconfigures where an Annotation can be used -
@Inheritedconfigures inheritance for an Annotation
Derivandi
Derivandi core features are
Code Model
It is possible to query the code model from modules down to method parameters.
D.Class string = context.getClassOrThrow("java.lang.String");
for (D.Property property : string.getProperties()) {
D.Method getter = property.getGetter();
for (D.Parameter parameter : getter.getParameters()) {
System.out.println(parameter.isFinal());
}
}
JavaDsl
The JavaDsl makes it easy to generate source files. The Code Model can be used with the JavaDsl. Modules down to method parameters are typesafe. Everything has a flexible String overload.
JavaDsl.class_().package_("org.example")
.public_().name("MyClass")
.field(JavaDsl.field().private_().type("String").name("foo"))
.method(JavaDsl.method().public_().resultType("void").name("bar"))
.renderDeclaration(RenderingContext.createRenderingContext());
File Generation
There are tree kind of files that can be generated. Class files, resource files and source files. Generated source files will be complied like any other. Generating them should be preferred over class files. The JavaDsl can be used.
context.writeClassFile();
context.writeResource();
context.writeAndCompileSourceFile(JavaDsl.class_().package_("org.example")
.public_().name("MyClass")
.constructor(JavaDsl.constructor().surroundingType()));
Logging
Logging can be done on three levels. Error, Warning or Info. Errors will interrupt the compilation. It is possible to log with a reference to a specific place in the code.
context.logAndRaiseError("broken");
D.Class string = context.getClassOrThrow("java.lang.String");
context.logWarningAt(string, "let me warn you about Strings!");
context.logInfo("i was here");
Compiler
Overview
Derivandi runs in the complier. Compilation happens in five steps.
-
Parse
The source files are parsed -
Enter
The Parser Result is entered in the internal datastructures -
Annotation Processing
All Annotation processors, like Derivandi, are executed. This may parts in new source files. If new source files are generated the steps 1-3 will be run for again for just these. -
Analyse
Analyses and Validates the code.This means that "normal" code can reference code that will only be generated at compile time. -
Generate
Class files are generated