aboutsummaryrefslogtreecommitdiff
path: root/src/lombok/eclipse
diff options
context:
space:
mode:
authorReinier Zwitserloot <reinier@tipit.to>2009-06-09 18:27:10 +0200
committerReinier Zwitserloot <reinier@tipit.to>2009-06-09 18:27:10 +0200
commit41fb7cba62b543243c784757d1af4e05824ddc4e (patch)
treeb910a78f31576d08f7a95440edb8f630cf4164eb /src/lombok/eclipse
parent525211b872b982b880aa2bed5e263ec582593f0d (diff)
downloadlombok-41fb7cba62b543243c784757d1af4e05824ddc4e.tar.gz
lombok-41fb7cba62b543243c784757d1af4e05824ddc4e.tar.bz2
lombok-41fb7cba62b543243c784757d1af4e05824ddc4e.zip
Many changes:
- Split off the actual agent work into a separate src package in preparation for creating separate jars. Involved a lot of renaming - Renamed TransformCompilationUnitDeclaration to TransformEclipseAST, as this class will also be transforming e.g. MethodDeclaration objects. - Expanded the patching to also patch in transform calls when the parser fills in the Statement array for existing constructors, methods, and initializers. - Redesigned the ClassLoaderWorkaround class quite a bit. - Positioning should not work correctly ('jump to method' should jump to the getter annotation). (Apparently, Clinit objects are always fully parsed in the original run, so no need to patch anything there).
Diffstat (limited to 'src/lombok/eclipse')
-rw-r--r--src/lombok/eclipse/HandleGetter_ecj.java62
-rw-r--r--src/lombok/eclipse/TransformEclipseAST.java60
2 files changed, 122 insertions, 0 deletions
diff --git a/src/lombok/eclipse/HandleGetter_ecj.java b/src/lombok/eclipse/HandleGetter_ecj.java
new file mode 100644
index 00000000..f71376a3
--- /dev/null
+++ b/src/lombok/eclipse/HandleGetter_ecj.java
@@ -0,0 +1,62 @@
+package lombok.eclipse;
+
+import java.lang.reflect.Modifier;
+
+import lombok.transformations.TransformationsUtil;
+
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
+import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+
+public class HandleGetter_ecj {
+ public void apply(Annotation annotation, TypeDeclaration type, FieldDeclaration field) {
+ TypeReference fieldType = field.type;
+ String getterName = TransformationsUtil.toGetterName(new String(field.name), nameEquals(fieldType.getTypeName(), "boolean"));
+
+ for ( AbstractMethodDeclaration method : type.methods ) {
+ if ( method.selector != null && new String(method.selector).equals(getterName) ) return;
+ }
+
+ MethodDeclaration method = new MethodDeclaration(type.compilationResult);
+ method.modifiers = Modifier.PUBLIC;
+ method.returnType = field.type;
+ method.annotations = null;
+ method.arguments = null;
+ method.selector = getterName.toCharArray();
+ method.binding = null;
+ method.thrownExceptions = null;
+ method.typeParameters = null;
+ method.scope = new MethodScope(type.scope, method, false);
+ method.bits |= ASTNode.Bit24;
+ Expression fieldExpression = new SingleNameReference(field.name, (field.declarationSourceStart << 32) | field.declarationSourceEnd);
+ Statement returnStatement = new ReturnStatement(fieldExpression, field.sourceStart, field.sourceEnd);
+ method.bodyStart = method.declarationSourceStart = method.sourceStart = annotation.sourceStart;
+ method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = annotation.sourceEnd;
+ method.statements = new Statement[] { returnStatement };
+ AbstractMethodDeclaration[] newArray = new AbstractMethodDeclaration[type.methods.length + 1];
+ System.arraycopy(type.methods, 0, newArray, 0, type.methods.length);
+ newArray[type.methods.length] = method;
+ type.methods = newArray;
+ }
+
+ private boolean nameEquals(char[][] typeName, String string) {
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for ( char[] elem : typeName ) {
+ if ( first ) first = false;
+ else sb.append('.');
+ sb.append(elem);
+ }
+
+ return string.contentEquals(sb);
+ }
+}
diff --git a/src/lombok/eclipse/TransformEclipseAST.java b/src/lombok/eclipse/TransformEclipseAST.java
new file mode 100644
index 00000000..9212a0d4
--- /dev/null
+++ b/src/lombok/eclipse/TransformEclipseAST.java
@@ -0,0 +1,60 @@
+package lombok.eclipse;
+
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Initializer;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+
+/**
+ * Entry point for the Eclipse Parser patch that lets lombok modify the Abstract Syntax Tree as generated by
+ * eclipse's parser implementations. This class is injected into the appropriate OSGi ClassLoader and can thus
+ * use any classes that belong to org.eclipse.jdt.(apt.)core.
+ *
+ * Note that, for any Method body, if Bit24 is set, the eclipse parser has been patched to never attempt to
+ * (re)parse it. You should set Bit24 on any MethodDeclaration object you inject into the AST:
+ *
+ * <code>methodDeclaration.bits |= 0x80000;</code>
+ *
+ * @author rzwitserloot
+ * @author rspilker
+ */
+public class TransformEclipseAST {
+ /**
+ * This method is called immediately after eclipse finishes building a CompilationUnitDeclaration, which is
+ * the top-level AST node when eclipse parses a source file. The signature is 'magic' - you should not
+ * change it!
+ *
+ * Eclipse's parsers often operate in diet mode, which means many parts of the AST have been left blank.
+ * Be ready to deal with just about anything being null, such as the Statement[] arrays of the Method AST nodes.
+ *
+ * @param parser The eclipse parser object that generated the AST.
+ * @param ast The AST node belonging to the compilation unit (java speak for a single source file).
+ */
+ public static void transform(Parser parser, CompilationUnitDeclaration ast) {
+ if ( ast.types != null ) for ( TypeDeclaration type : ast.types ) {
+ if ( type.fields != null ) for ( FieldDeclaration field : type.fields ) {
+ if ( field.annotations != null ) for ( Annotation annotation : field.annotations ) {
+ if ( annotation.type.toString().equals("Getter") ) {
+ new HandleGetter_ecj().apply(annotation, type, field);
+ }
+ }
+ }
+ }
+ }
+
+ public static void transform(Parser parser, MethodDeclaration ast) {
+
+ }
+
+ public static void transform(Parser parser, ConstructorDeclaration ast) {
+
+ }
+
+ public static void transform(Parser parser, Initializer ast) {
+
+ }
+}