From bcee5a50db361abe7468de74c79194d394c8229e Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 24 Jun 2009 07:01:52 +0200 Subject: javac's HandleData now generates the constructor only if it doesn't already exist, and the staticConstructor is now also completed. Left: toString, hashCode, equals. --- runJavac | 29 ++++++++++--- src/lombok/eclipse/handlers/PKG.java | 4 +- src/lombok/javac/handlers/HandleData.java | 70 ++++++++++++++++++++++++++++--- src/lombok/javac/handlers/PKG.java | 23 +++++++++- 4 files changed, 113 insertions(+), 13 deletions(-) diff --git a/runJavac b/runJavac index 79e3c456..e7b4942b 100755 --- a/runJavac +++ b/runJavac @@ -1,10 +1,29 @@ #!/bin/sh -if [ "$1" == "run" ]; then - javac -cp ~/foo/lombok.jar ~/foo/*.java -else - ant && cp dist/lombok.jar ~/foo && javac -cp ~/foo/lombok.jar ~/foo/*.java +CONTINUE=0 +if [ "$1" != "run" ]; then + echo BUILDING... + ant && cp dist/lombok.jar ~/foo + CONTINUE=$? fi +if [ $CONTINUE -eq 0 ]; then + echo COMPILING... + javac -cp ~/foo/lombok.jar ~/foo/*.java + CONTINUE=$? +fi - +if [ "$2" == "javap" ]; then + if [ $CONTINUE -eq 0 ]; then + echo DECOMPILING... + shift + shift + javap -classpath /Users/rzwitserloot/foo/lombok.jar:/Users/rzwitserloot/foo $@ + fi +elif [ "$2" != "" ]; then + if [ $CONTINUE -eq 0 ]; then + echo RUNNING... + shift + java -cp /Users/rzwitserloot/foo/lombok.jar:/Users/rzwitserloot/foo $@ + fi +fi diff --git a/src/lombok/eclipse/handlers/PKG.java b/src/lombok/eclipse/handlers/PKG.java index 3cfbf9c6..e9d12b62 100644 --- a/src/lombok/eclipse/handlers/PKG.java +++ b/src/lombok/eclipse/handlers/PKG.java @@ -50,7 +50,7 @@ class PKG { node = node.up(); } - if ( node.get() instanceof TypeDeclaration ) { + if ( node != null && node.get() instanceof TypeDeclaration ) { TypeDeclaration typeDecl = (TypeDeclaration)node.get(); if ( typeDecl.methods != null ) for ( AbstractMethodDeclaration def : typeDecl.methods ) { char[] mName = ((AbstractMethodDeclaration)def).selector; @@ -71,7 +71,7 @@ class PKG { node = node.up(); } - if ( node.get() instanceof TypeDeclaration ) { + if ( node != null && node.get() instanceof TypeDeclaration ) { TypeDeclaration typeDecl = (TypeDeclaration)node.get(); if ( typeDecl.methods != null ) for ( AbstractMethodDeclaration def : typeDecl.methods ) { if ( def instanceof ConstructorDeclaration ) { diff --git a/src/lombok/javac/handlers/HandleData.java b/src/lombok/javac/handlers/HandleData.java index 5d1cc913..8ab50812 100644 --- a/src/lombok/javac/handlers/HandleData.java +++ b/src/lombok/javac/handlers/HandleData.java @@ -16,12 +16,17 @@ import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCAssign; +import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; +import com.sun.tools.javac.tree.JCTree.JCIdent; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCModifiers; +import com.sun.tools.javac.tree.JCTree.JCReturn; import com.sun.tools.javac.tree.JCTree.JCStatement; +import com.sun.tools.javac.tree.JCTree.JCTypeApply; +import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; @@ -55,10 +60,18 @@ public class HandleData implements JavacAnnotationHandler { } String staticConstructorName = annotation.getInstance().staticConstructor(); - JCMethodDecl constructor = createConstructor(staticConstructorName.equals(""), typeNode, nodesForConstructorAndToString); - injectMethod(typeNode, constructor); - //TODO generate static constructors, hashCode, equals, toString. + if ( constructorExists(typeNode) == MethodExistsResult.NOT_EXISTS ) { + JCMethodDecl constructor = createConstructor(staticConstructorName.equals(""), typeNode, nodesForConstructorAndToString); + injectMethod(typeNode, constructor); + } + + if ( !staticConstructorName.isEmpty() && methodExists("of", typeNode) == MethodExistsResult.NOT_EXISTS ) { + JCMethodDecl staticConstructor = createStaticConstructor(staticConstructorName, typeNode, nodesForConstructorAndToString); + injectMethod(typeNode, staticConstructor); + } + + //TODO hashCode, equals, toString. return true; } @@ -79,7 +92,54 @@ public class HandleData implements JavacAnnotationHandler { } JCModifiers mods = maker.Modifiers(isPublic ? Modifier.PUBLIC : Modifier.PRIVATE); - return maker.MethodDef(mods, - typeNode.toName(""), null, type.typarams, params, List.nil(), maker.Block(0L, assigns), null); + return maker.MethodDef(mods, typeNode.toName(""), + null, type.typarams, params, List.nil(), maker.Block(0L, assigns), null); + } + + private JCMethodDecl createStaticConstructor(String name, Node typeNode, List fields) { + TreeMaker maker = typeNode.getTreeMaker(); + JCClassDecl type = (JCClassDecl) typeNode.get(); + + JCModifiers mods = maker.Modifiers(Flags.STATIC); + + JCExpression returnType, constructorType; + + List typeParams = List.nil(); + List params = List.nil(); + List typeArgs1 = List.nil(); + List typeArgs2 = List.nil(); + List args = List.nil(); + + if ( !type.typarams.isEmpty() ) { + for ( JCTypeParameter param : type.typarams ) { + typeArgs1 = typeArgs1.append(maker.Ident(param.name)); + typeArgs2 = typeArgs2.append(maker.Ident(param.name)); + typeParams = typeParams.append(maker.TypeParameter(param.name, param.bounds)); + } + returnType = maker.TypeApply(maker.Ident(type.name), typeArgs1); + constructorType = maker.TypeApply(maker.Ident(type.name), typeArgs2); + } else { + returnType = maker.Ident(type.name); + constructorType = maker.Ident(type.name); + } + + for ( Node fieldNode : fields ) { + JCVariableDecl field = (JCVariableDecl) fieldNode.get(); + JCExpression pType; + if ( field.vartype instanceof JCIdent ) pType = maker.Ident(((JCIdent)field.vartype).name); + else if ( field.vartype instanceof JCTypeApply ) { + JCTypeApply typeApply = (JCTypeApply) field.vartype; + List tArgs = List.nil(); + for ( JCExpression arg : typeApply.arguments ) tArgs = tArgs.append(arg); + pType = maker.TypeApply(typeApply.clazz, tArgs); + } else pType = field.vartype; + JCVariableDecl param = maker.VarDef(maker.Modifiers(0), field.name, pType, null); + params = params.append(param); + args = args.append(maker.Ident(field.name)); + } + JCReturn returnStatement = maker.Return(maker.NewClass(null, List.nil(), constructorType, args, null)); + JCBlock body = maker.Block(0, List.of(returnStatement)); + + return maker.MethodDef(mods, typeNode.toName(name), returnType, typeParams, params, List.nil(), body, null); } } diff --git a/src/lombok/javac/handlers/PKG.java b/src/lombok/javac/handlers/PKG.java index 615e4c80..25d1a93e 100644 --- a/src/lombok/javac/handlers/PKG.java +++ b/src/lombok/javac/handlers/PKG.java @@ -40,7 +40,7 @@ class PKG { node = node.up(); } - if ( node.get() instanceof JCClassDecl ) { + if ( node != null && node.get() instanceof JCClassDecl ) { for ( JCTree def : ((JCClassDecl)node.get()).defs ) { if ( def instanceof JCMethodDecl ) { if ( ((JCMethodDecl)def).name.contentEquals(methodName) ) { @@ -55,6 +55,27 @@ class PKG { return MethodExistsResult.NOT_EXISTS; } + static MethodExistsResult constructorExists(JavacAST.Node node) { + while ( node != null && !(node.get() instanceof JCClassDecl) ) { + node = node.up(); + } + + if ( node != null && node.get() instanceof JCClassDecl ) { + for ( JCTree def : ((JCClassDecl)node.get()).defs ) { + if ( def instanceof JCMethodDecl ) { + if ( ((JCMethodDecl)def).name.contentEquals("") ) { + if ( (((JCMethodDecl)def).mods.flags & Flags.GENERATEDCONSTR) != 0 ) continue; + JavacAST.Node existing = node.getNodeFor(def); + if ( existing == null || !existing.isHandled() ) return MethodExistsResult.EXISTS_BY_USER; + return MethodExistsResult.EXISTS_BY_LOMBOK; + } + } + } + } + + return MethodExistsResult.NOT_EXISTS; + } + static int toJavacModifier(AccessLevel accessLevel) { switch ( accessLevel ) { case MODULE: -- cgit