mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-15 00:17:45 +00:00
Added the SetterHandler for javac. Also added a way to get the SymbolTable on a JavacAST.Node, because you need it to e.g. access constant types like 'void'.
This commit is contained in:
1 parent
7c65e0fdff
commit
1929a28c9d
6 files changed
+114
-10
No files matched your search
@@ -0,0 +1,12 @@
|
||||
package lombok;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Setter {
|
||||
AccessLevel value() default lombok.AccessLevel.PUBLIC;
|
||||
}
|
||||
@@ -5,14 +5,22 @@ public class TransformationsUtil {
|
||||
|
||||
public static String toGetterName(CharSequence fieldName, boolean isBoolean) {
|
||||
final String prefix = isBoolean ? "is" : "get";
|
||||
final String suffix;
|
||||
|
||||
if ( fieldName.length() == 0 ) return prefix;
|
||||
|
||||
char first = fieldName.charAt(0);
|
||||
return buildName(prefix, fieldName.toString());
|
||||
}
|
||||
|
||||
private static String buildName(String prefix, String suffix) {
|
||||
if ( suffix.length() == 0 ) return prefix;
|
||||
|
||||
char first = suffix.charAt(0);
|
||||
if ( Character.isLowerCase(first) )
|
||||
suffix = String.format("%s%s", Character.toTitleCase(first), fieldName.subSequence(1, fieldName.length()));
|
||||
else suffix = fieldName.toString();
|
||||
suffix = String.format("%s%s", Character.toTitleCase(first), suffix.subSequence(1, suffix.length()));
|
||||
return String.format("%s%s", prefix, suffix);
|
||||
}
|
||||
|
||||
public static String toSetterName(CharSequence fieldName) {
|
||||
return buildName("set", fieldName.toString());
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import javax.tools.JavaFileObject;
|
||||
import lombok.core.AST;
|
||||
|
||||
import com.sun.source.util.Trees;
|
||||
import com.sun.tools.javac.code.Symtab;
|
||||
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.TreeMaker;
|
||||
@@ -33,6 +34,7 @@ public class JavacAST extends AST<JCTree> {
|
||||
private final Messager messager;
|
||||
private final Name.Table nameTable;
|
||||
private final TreeMaker treeMaker;
|
||||
private final Symtab symtab;
|
||||
private final Log log;
|
||||
|
||||
public JavacAST(Trees trees, JavacProcessingEnvironment env, JCCompilationUnit top) {
|
||||
@@ -42,6 +44,7 @@ public class JavacAST extends AST<JCTree> {
|
||||
this.log = Log.instance(env.getContext());
|
||||
this.nameTable = Name.Table.instance(env.getContext());
|
||||
this.treeMaker = TreeMaker.instance(env.getContext());
|
||||
this.symtab = Symtab.instance(env.getContext());
|
||||
}
|
||||
|
||||
@Override public String getPackageDeclaration() {
|
||||
@@ -87,6 +90,10 @@ public class JavacAST extends AST<JCTree> {
|
||||
return treeMaker;
|
||||
}
|
||||
|
||||
public Symtab getSymbolTable() {
|
||||
return symtab;
|
||||
}
|
||||
|
||||
private Node buildCompilationUnit(JCCompilationUnit top) {
|
||||
List<Node> childNodes = new ArrayList<Node>();
|
||||
for ( JCTree s : top.defs ) {
|
||||
@@ -294,6 +301,10 @@ public class JavacAST extends AST<JCTree> {
|
||||
return treeMaker;
|
||||
}
|
||||
|
||||
public Symtab getSymbolTable() {
|
||||
return symtab;
|
||||
}
|
||||
|
||||
public Name toName(String name) {
|
||||
return JavacAST.this.toName(name);
|
||||
}
|
||||
|
||||
@@ -10,13 +10,12 @@ import lombok.javac.JavacAST;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.TreeMaker;
|
||||
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
|
||||
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.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCStatement;
|
||||
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
@@ -26,6 +25,7 @@ import com.sun.tools.javac.util.Name;
|
||||
@ProviderFor(JavacAnnotationHandler.class)
|
||||
public class HandleGetter implements JavacAnnotationHandler<Getter> {
|
||||
@Override public void handle(AnnotationValues<Getter> annotation, JCAnnotation ast, JavacAST.Node annotationNode) {
|
||||
//TODO Check for existence of the getter and skip it (+ warn) if it's already there.
|
||||
if ( annotationNode.up().getKind() != Kind.FIELD ) {
|
||||
annotationNode.addError("@Getter is only supported on a field.");
|
||||
return;
|
||||
@@ -37,16 +37,16 @@ public class HandleGetter implements JavacAnnotationHandler<Getter> {
|
||||
|
||||
int access = toJavacModifier(getter.value());
|
||||
|
||||
MethodTree getterMethod = createGetter(access, annotationNode.up(), annotationNode.getTreeMaker());
|
||||
javacClassTree.defs = javacClassTree.defs.append((JCTree)getterMethod);
|
||||
JCMethodDecl getterMethod = createGetter(access, annotationNode.up(), annotationNode.getTreeMaker());
|
||||
javacClassTree.defs = javacClassTree.defs.append(getterMethod);
|
||||
}
|
||||
|
||||
private MethodTree createGetter(int access, JavacAST.Node field, TreeMaker treeMaker) {
|
||||
private JCMethodDecl createGetter(int access, JavacAST.Node field, TreeMaker treeMaker) {
|
||||
JCVariableDecl fieldNode = (JCVariableDecl) field.get();
|
||||
JCStatement returnStatement = treeMaker.Return(treeMaker.Ident(fieldNode.getName()));
|
||||
|
||||
JCBlock methodBody = treeMaker.Block(0, List.of(returnStatement));
|
||||
Name methodName = field.toName(toGetterName((JCVariableDecl)field.get()));
|
||||
Name methodName = field.toName(toGetterName(fieldNode));
|
||||
JCExpression methodType = fieldNode.type != null ? treeMaker.Type(fieldNode.type) : fieldNode.vartype;
|
||||
|
||||
List<JCTypeParameter> methodGenericParams = List.nil();
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package lombok.javac.handlers;
|
||||
|
||||
import static lombok.javac.handlers.PKG.toJavacModifier;
|
||||
import static lombok.javac.handlers.PKG.toSetterName;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
import lombok.Setter;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.javac.JavacAST;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacAST.Node;
|
||||
|
||||
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.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCStatement;
|
||||
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.util.Name;
|
||||
|
||||
@ProviderFor(JavacAnnotationHandler.class)
|
||||
public class HandleSetter implements JavacAnnotationHandler<Setter> {
|
||||
@Override public void handle(AnnotationValues<Setter> annotation, JCAnnotation ast, Node annotationNode) {
|
||||
//TODO Check for existence of the setter and skip it (+ warn) if it's already there.
|
||||
if ( annotationNode.up().getKind() != Kind.FIELD ) {
|
||||
annotationNode.addError("@Setter is only supported on a field.");
|
||||
return;
|
||||
}
|
||||
|
||||
Setter setter = annotation.getInstance();
|
||||
|
||||
JCClassDecl javacClassTree = (JCClassDecl) annotationNode.up().up().get();
|
||||
|
||||
int access = toJavacModifier(setter.value());
|
||||
|
||||
JCMethodDecl setterMethod = createSetter(access, annotationNode.up(), annotationNode.getTreeMaker());
|
||||
javacClassTree.defs = javacClassTree.defs.append(setterMethod);
|
||||
}
|
||||
|
||||
private JCMethodDecl createSetter(int access, JavacAST.Node field, TreeMaker treeMaker) {
|
||||
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
|
||||
|
||||
JCFieldAccess thisX = treeMaker.Select(treeMaker.Ident(field.toName("this")), fieldDecl.name);
|
||||
JCAssign assign = treeMaker.Assign(thisX, treeMaker.Ident(fieldDecl.name));
|
||||
|
||||
JCBlock methodBody = treeMaker.Block(0, List.<JCStatement>of(treeMaker.Exec(assign)));
|
||||
Name methodName = field.toName(toSetterName(fieldDecl));
|
||||
JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(0, List.<JCAnnotation>nil()), fieldDecl.name, fieldDecl.vartype, null);
|
||||
JCExpression methodType = treeMaker.Type(field.getSymbolTable().voidType);
|
||||
|
||||
List<JCTypeParameter> methodGenericParams = List.nil();
|
||||
List<JCVariableDecl> parameters = List.of(param);
|
||||
List<JCExpression> throwsClauses = List.nil();
|
||||
JCExpression annotationMethodDefaultValue = null;
|
||||
|
||||
return treeMaker.MethodDef(treeMaker.Modifiers(access, List.<JCAnnotation>nil()), methodName, methodType,
|
||||
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,12 @@ class PKG {
|
||||
return TransformationsUtil.toGetterName(fieldName, isBoolean);
|
||||
}
|
||||
|
||||
static String toSetterName(JCVariableDecl field) {
|
||||
CharSequence fieldName = field.name;
|
||||
|
||||
return TransformationsUtil.toSetterName(fieldName);
|
||||
}
|
||||
|
||||
static int toJavacModifier(AccessLevel accessLevel) {
|
||||
switch ( accessLevel ) {
|
||||
case MODULE:
|
||||
|
||||
Reference in new issue
Block a user