use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project lombok by rzwitserloot.
the class HandleNonNull method handle.
@Override
public void handle(AnnotationValues<NonNull> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.NON_NULL_FLAG_USAGE, "@NonNull");
if (annotationNode.up().getKind() == Kind.FIELD) {
try {
if (isPrimitive(((JCVariableDecl) annotationNode.up().get()).vartype)) {
annotationNode.addWarning("@NonNull is meaningless on a primitive.");
}
} catch (Exception ignore) {
}
return;
}
if (annotationNode.up().getKind() != Kind.ARGUMENT)
return;
JCMethodDecl declaration;
try {
declaration = (JCMethodDecl) annotationNode.up().up().get();
} catch (Exception e) {
return;
}
if (declaration.body == null) {
// This used to be a warning, but as @NonNull also has a documentary purpose, better to not warn about this. Since 1.16.7
return;
}
// Possibly, if 'declaration instanceof ConstructorDeclaration', fetch declaration.constructorCall, search it for any references to our parameter,
// and if they exist, create a new method in the class: 'private static <T> T lombok$nullCheck(T expr, String msg) {if (expr == null) throw NPE; return expr;}' and
// wrap all references to it in the super/this to a call to this method.
JCStatement nullCheck = recursiveSetGeneratedBy(generateNullCheck(annotationNode.getTreeMaker(), annotationNode.up(), annotationNode), ast, annotationNode.getContext());
if (nullCheck == null) {
// @NonNull applied to a primitive. Kinda pointless. Let's generate a warning.
annotationNode.addWarning("@NonNull is meaningless on a primitive.");
return;
}
List<JCStatement> statements = declaration.body.stats;
String expectedName = annotationNode.up().getName();
/* Abort if the null check is already there, delving into try and synchronized statements */
{
List<JCStatement> stats = statements;
int idx = 0;
while (stats.size() > idx) {
JCStatement stat = stats.get(idx++);
if (JavacHandlerUtil.isConstructorCall(stat))
continue;
if (stat instanceof JCTry) {
stats = ((JCTry) stat).body.stats;
idx = 0;
continue;
}
if (stat instanceof JCSynchronized) {
stats = ((JCSynchronized) stat).body.stats;
idx = 0;
continue;
}
String varNameOfNullCheck = returnVarNameIfNullCheck(stat);
if (varNameOfNullCheck == null)
break;
if (varNameOfNullCheck.equals(expectedName))
return;
}
}
List<JCStatement> tail = statements;
List<JCStatement> head = List.nil();
for (JCStatement stat : statements) {
if (JavacHandlerUtil.isConstructorCall(stat) || (JavacHandlerUtil.isGenerated(stat) && isNullCheck(stat))) {
tail = tail.tail;
head = head.prepend(stat);
continue;
}
break;
}
List<JCStatement> newList = tail.prepend(nullCheck);
for (JCStatement stat : head) newList = newList.prepend(stat);
declaration.body.stats = newList;
annotationNode.getAst().setChanged();
}
use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project lombok by rzwitserloot.
the class HandleSetter method createSetter.
public static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, String setterName, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
if (setterName == null)
return null;
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
JCExpression fieldRef = createFieldAccessor(treeMaker, field, FieldAccess.ALWAYS_FIELD);
JCAssign assign = treeMaker.Assign(fieldRef, treeMaker.Ident(fieldDecl.name));
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
List<JCAnnotation> nonNulls = findAnnotations(field, NON_NULL_PATTERN);
List<JCAnnotation> nullables = findAnnotations(field, NULLABLE_PATTERN);
Name methodName = field.toName(setterName);
List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(nonNulls).appendList(nullables);
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, field.getContext());
JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(flags, annsOnParam), fieldDecl.name, fieldDecl.vartype, null);
if (nonNulls.isEmpty()) {
statements.append(treeMaker.Exec(assign));
} else {
JCStatement nullCheck = generateNullCheck(treeMaker, field, source);
if (nullCheck != null)
statements.append(nullCheck);
statements.append(treeMaker.Exec(assign));
}
JCExpression methodType = null;
if (shouldReturnThis) {
methodType = cloneSelfType(field);
}
if (methodType == null) {
//WARNING: Do not use field.getSymbolTable().voidType - that field has gone through non-backwards compatible API changes within javac1.6.
methodType = treeMaker.Type(Javac.createVoidType(field.getSymbolTable(), CTC_VOID));
shouldReturnThis = false;
}
if (shouldReturnThis) {
JCReturn returnStatement = treeMaker.Return(treeMaker.Ident(field.toName("this")));
statements.append(returnStatement);
}
JCBlock methodBody = treeMaker.Block(0, statements.toList());
List<JCTypeParameter> methodGenericParams = List.nil();
List<JCVariableDecl> parameters = List.of(param);
List<JCExpression> throwsClauses = List.nil();
JCExpression annotationMethodDefaultValue = null;
List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod);
if (isFieldDeprecated(field)) {
annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
}
JCMethodDecl decl = recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType, methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source.get(), field.getContext());
copyJavadoc(field, decl, CopyJavadoc.SETTER);
return decl;
}
use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project lombok by rzwitserloot.
the class HandleSynchronized method handle.
@Override
public void handle(AnnotationValues<Synchronized> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.SYNCHRONIZED_FLAG_USAGE, "@Synchronized");
if (inNetbeansEditor(annotationNode))
return;
deleteAnnotationIfNeccessary(annotationNode, Synchronized.class);
JavacNode methodNode = annotationNode.up();
if (methodNode == null || methodNode.getKind() != Kind.METHOD || !(methodNode.get() instanceof JCMethodDecl)) {
annotationNode.addError("@Synchronized is legal only on methods.");
return;
}
JCMethodDecl method = (JCMethodDecl) methodNode.get();
if ((method.mods.flags & Flags.ABSTRACT) != 0) {
annotationNode.addError("@Synchronized is legal only on concrete methods.");
return;
}
boolean isStatic = (method.mods.flags & Flags.STATIC) != 0;
String lockName = annotation.getInstance().value();
boolean autoMake = false;
if (lockName.length() == 0) {
autoMake = true;
lockName = isStatic ? STATIC_LOCK_NAME : INSTANCE_LOCK_NAME;
}
JavacTreeMaker maker = methodNode.getTreeMaker().at(ast.pos);
Context context = methodNode.getContext();
if (fieldExists(lockName, methodNode) == MemberExistsResult.NOT_EXISTS) {
if (!autoMake) {
annotationNode.addError("The field " + lockName + " does not exist.");
return;
}
JCExpression objectType = genJavaLangTypeRef(methodNode, ast.pos, "Object");
//We use 'new Object[0];' because unlike 'new Object();', empty arrays *ARE* serializable!
JCNewArray newObjectArray = maker.NewArray(genJavaLangTypeRef(methodNode, ast.pos, "Object"), List.<JCExpression>of(maker.Literal(CTC_INT, 0)), null);
JCVariableDecl fieldDecl = recursiveSetGeneratedBy(maker.VarDef(maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (isStatic ? Flags.STATIC : 0)), methodNode.toName(lockName), objectType, newObjectArray), ast, context);
injectFieldAndMarkGenerated(methodNode.up(), fieldDecl);
}
if (method.body == null)
return;
JCExpression lockNode;
if (isStatic) {
lockNode = chainDots(methodNode, ast.pos, methodNode.up().getName(), lockName);
} else {
lockNode = maker.Select(maker.Ident(methodNode.toName("this")), methodNode.toName(lockName));
}
recursiveSetGeneratedBy(lockNode, ast, context);
method.body = setGeneratedBy(maker.Block(0, List.<JCStatement>of(setGeneratedBy(maker.Synchronized(lockNode, method.body), ast, context))), ast, context);
methodNode.rebuild();
}
use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project lombok by rzwitserloot.
the class HandleToString method generateToString.
public void generateToString(JavacNode typeNode, JavacNode source, List<String> excludes, List<String> includes, boolean includeFieldNames, Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess) {
boolean notAClass = true;
if (typeNode.get() instanceof JCClassDecl) {
long flags = ((JCClassDecl) typeNode.get()).mods.flags;
notAClass = (flags & (Flags.INTERFACE | Flags.ANNOTATION)) != 0;
}
if (callSuper == null) {
try {
callSuper = ((Boolean) ToString.class.getMethod("callSuper").getDefaultValue()).booleanValue();
} catch (Exception ignore) {
}
}
if (notAClass) {
source.addError("@ToString is only supported on a class or enum.");
return;
}
ListBuffer<JavacNode> nodesForToString = new ListBuffer<JavacNode>();
if (includes != null) {
for (JavacNode child : typeNode.down()) {
if (child.getKind() != Kind.FIELD)
continue;
JCVariableDecl fieldDecl = (JCVariableDecl) child.get();
if (includes.contains(fieldDecl.name.toString()))
nodesForToString.append(child);
}
} else {
for (JavacNode child : typeNode.down()) {
if (child.getKind() != Kind.FIELD)
continue;
JCVariableDecl fieldDecl = (JCVariableDecl) child.get();
//Skip static fields.
if ((fieldDecl.mods.flags & Flags.STATIC) != 0)
continue;
//Skip excluded fields.
if (excludes != null && excludes.contains(fieldDecl.name.toString()))
continue;
//Skip fields that start with $.
if (fieldDecl.name.toString().startsWith("$"))
continue;
nodesForToString.append(child);
}
}
switch(methodExists("toString", typeNode, 0)) {
case NOT_EXISTS:
JCMethodDecl method = createToString(typeNode, nodesForToString.toList(), includeFieldNames, callSuper, fieldAccess, source.get());
injectMethod(typeNode, method);
break;
case EXISTS_BY_LOMBOK:
break;
default:
case EXISTS_BY_USER:
if (whineIfExists) {
source.addWarning("Not generating toString(): A method with that name already exists");
}
break;
}
}
use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project lombok by rzwitserloot.
the class HandleUtilityClass method createPrivateDefaultConstructor.
private void createPrivateDefaultConstructor(JavacNode typeNode) {
JavacTreeMaker maker = typeNode.getTreeMaker();
JCModifiers mods = maker.Modifiers(Flags.PRIVATE, List.<JCAnnotation>nil());
Name name = typeNode.toName("<init>");
JCBlock block = maker.Block(0L, createThrowStatement(typeNode, maker));
JCMethodDecl methodDef = maker.MethodDef(mods, name, null, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), block, null);
JCMethodDecl constructor = recursiveSetGeneratedBy(methodDef, typeNode.get(), typeNode.getContext());
JavacHandlerUtil.injectMethod(typeNode, constructor, List.<Type>nil(), Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID));
}
Aggregations