use of lombok.javac.JavacNode in project lombok by rzwitserloot.
the class HandleBuilder method addObtainVia.
private void addObtainVia(BuilderFieldData bfd, JavacNode node) {
for (JavacNode child : node.down()) {
if (!annotationTypeMatches(ObtainVia.class, child))
continue;
AnnotationValues<ObtainVia> ann = createAnnotation(ObtainVia.class, child);
bfd.obtainVia = ann.getInstance();
bfd.obtainViaNode = child;
deleteAnnotationIfNeccessary(child, ObtainVia.class);
return;
}
}
use of lombok.javac.JavacNode in project lombok by rzwitserloot.
the class HandleCleanup method handle.
@Override
public void handle(AnnotationValues<Cleanup> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.CLEANUP_FLAG_USAGE, "@Cleanup");
if (inNetbeansEditor(annotationNode))
return;
deleteAnnotationIfNeccessary(annotationNode, Cleanup.class);
String cleanupName = annotation.getInstance().value();
if (cleanupName.length() == 0) {
annotationNode.addError("cleanupName cannot be the empty string.");
return;
}
if (annotationNode.up().getKind() != Kind.LOCAL) {
annotationNode.addError("@Cleanup is legal only on local variable declarations.");
return;
}
JCVariableDecl decl = (JCVariableDecl) annotationNode.up().get();
if (decl.init == null) {
annotationNode.addError("@Cleanup variable declarations need to be initialized.");
return;
}
JavacNode ancestor = annotationNode.up().directUp();
JCTree blockNode = ancestor.get();
final List<JCStatement> statements;
if (blockNode instanceof JCBlock) {
statements = ((JCBlock) blockNode).stats;
} else if (blockNode instanceof JCCase) {
statements = ((JCCase) blockNode).stats;
} else if (blockNode instanceof JCMethodDecl) {
statements = ((JCMethodDecl) blockNode).body.stats;
} else {
annotationNode.addError("@Cleanup is legal only on a local variable declaration inside a block.");
return;
}
boolean seenDeclaration = false;
ListBuffer<JCStatement> newStatements = new ListBuffer<JCStatement>();
ListBuffer<JCStatement> tryBlock = new ListBuffer<JCStatement>();
for (JCStatement statement : statements) {
if (!seenDeclaration) {
if (statement == decl)
seenDeclaration = true;
newStatements.append(statement);
} else {
tryBlock.append(statement);
}
}
if (!seenDeclaration) {
annotationNode.addError("LOMBOK BUG: Can't find this local variable declaration inside its parent.");
return;
}
doAssignmentCheck(annotationNode, tryBlock.toList(), decl.name);
JavacTreeMaker maker = annotationNode.getTreeMaker();
JCFieldAccess cleanupMethod = maker.Select(maker.Ident(decl.name), annotationNode.toName(cleanupName));
List<JCStatement> cleanupCall = List.<JCStatement>of(maker.Exec(maker.Apply(List.<JCExpression>nil(), cleanupMethod, List.<JCExpression>nil())));
JCExpression preventNullAnalysis = preventNullAnalysis(maker, annotationNode, maker.Ident(decl.name));
JCBinary isNull = maker.Binary(CTC_NOT_EQUAL, preventNullAnalysis, maker.Literal(CTC_BOT, null));
JCIf ifNotNullCleanup = maker.If(isNull, maker.Block(0, cleanupCall), null);
Context context = annotationNode.getContext();
JCBlock finalizer = recursiveSetGeneratedBy(maker.Block(0, List.<JCStatement>of(ifNotNullCleanup)), ast, context);
newStatements.append(setGeneratedBy(maker.Try(setGeneratedBy(maker.Block(0, tryBlock.toList()), ast, context), List.<JCCatch>nil(), finalizer), ast, context));
if (blockNode instanceof JCBlock) {
((JCBlock) blockNode).stats = newStatements.toList();
} else if (blockNode instanceof JCCase) {
((JCCase) blockNode).stats = newStatements.toList();
} else if (blockNode instanceof JCMethodDecl) {
((JCMethodDecl) blockNode).body.stats = newStatements.toList();
} else
throw new AssertionError("Should not get here");
ancestor.rebuild();
}
use of lombok.javac.JavacNode in project lombok by rzwitserloot.
the class HandleConstructor method createStaticConstructor.
public JCMethodDecl createStaticConstructor(String name, AccessLevel level, JavacNode typeNode, List<JavacNode> fields, JCTree source) {
JavacTreeMaker maker = typeNode.getTreeMaker();
JCClassDecl type = (JCClassDecl) typeNode.get();
JCModifiers mods = maker.Modifiers(Flags.STATIC | toJavacModifier(level));
JCExpression returnType, constructorType;
ListBuffer<JCTypeParameter> typeParams = new ListBuffer<JCTypeParameter>();
ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
ListBuffer<JCExpression> typeArgs1 = new ListBuffer<JCExpression>();
ListBuffer<JCExpression> typeArgs2 = new ListBuffer<JCExpression>();
ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
if (!type.typarams.isEmpty()) {
for (JCTypeParameter param : type.typarams) {
typeArgs1.append(maker.Ident(param.name));
typeArgs2.append(maker.Ident(param.name));
typeParams.append(maker.TypeParameter(param.name, param.bounds));
}
returnType = maker.TypeApply(maker.Ident(type.name), typeArgs1.toList());
constructorType = maker.TypeApply(maker.Ident(type.name), typeArgs2.toList());
} else {
returnType = maker.Ident(type.name);
constructorType = maker.Ident(type.name);
}
for (JavacNode fieldNode : fields) {
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
Name fieldName = removePrefixFromField(fieldNode);
JCExpression pType = cloneType(maker, field.vartype, source, typeNode.getContext());
List<JCAnnotation> nonNulls = findAnnotations(fieldNode, NON_NULL_PATTERN);
List<JCAnnotation> nullables = findAnnotations(fieldNode, NULLABLE_PATTERN);
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, nonNulls.appendList(nullables)), fieldName, pType, null);
params.append(param);
args.append(maker.Ident(fieldName));
}
JCReturn returnStatement = maker.Return(maker.NewClass(null, List.<JCExpression>nil(), constructorType, args.toList(), null));
JCBlock body = maker.Block(0, List.<JCStatement>of(returnStatement));
return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName(name), returnType, typeParams.toList(), params.toList(), List.<JCExpression>nil(), body, null), source, typeNode.getContext());
}
use of lombok.javac.JavacNode in project lombok by rzwitserloot.
the class HandleConstructor method addConstructorProperties.
public static void addConstructorProperties(JCModifiers mods, JavacNode node, List<JavacNode> fields) {
if (fields.isEmpty())
return;
JavacTreeMaker maker = node.getTreeMaker();
JCExpression constructorPropertiesType = chainDots(node, "java", "beans", "ConstructorProperties");
ListBuffer<JCExpression> fieldNames = new ListBuffer<JCExpression>();
for (JavacNode field : fields) {
Name fieldName = removePrefixFromField(field);
fieldNames.append(maker.Literal(fieldName.toString()));
}
JCExpression fieldNamesArray = maker.NewArray(null, List.<JCExpression>nil(), fieldNames.toList());
JCAnnotation annotation = maker.Annotation(constructorPropertiesType, List.of(fieldNamesArray));
mods.annotations = mods.annotations.append(annotation);
}
use of lombok.javac.JavacNode in project lombok by rzwitserloot.
the class HandleHelper method handle.
@Override
public void handle(AnnotationValues<Helper> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.HELPER_FLAG_USAGE, "@Helper");
deleteAnnotationIfNeccessary(annotationNode, Helper.class);
JavacNode annotatedType = annotationNode.up();
JavacNode containingBlock = annotatedType == null ? null : annotatedType.directUp();
List<JCStatement> origStatements = getStatementsFromJcNode(containingBlock == null ? null : containingBlock.get());
if (annotatedType == null || annotatedType.getKind() != Kind.TYPE || origStatements == null) {
annotationNode.addError("@Helper is legal only on method-local classes.");
return;
}
JCClassDecl annotatedType_ = (JCClassDecl) annotatedType.get();
Iterator<JCStatement> it = origStatements.iterator();
while (it.hasNext()) {
if (it.next() == annotatedType_) {
break;
}
}
java.util.List<String> knownMethodNames = new ArrayList<String>();
for (JavacNode ch : annotatedType.down()) {
if (ch.getKind() != Kind.METHOD)
continue;
String n = ch.getName();
if (n == null || n.isEmpty() || n.charAt(0) == '<')
continue;
knownMethodNames.add(n);
}
Collections.sort(knownMethodNames);
final String[] knownMethodNames_ = knownMethodNames.toArray(new String[knownMethodNames.size()]);
final Name helperName = annotationNode.toName("$" + annotatedType_.name);
final boolean[] helperUsed = new boolean[1];
final JavacTreeMaker maker = annotationNode.getTreeMaker();
TreeVisitor<Void, Void> visitor = new TreeScanner<Void, Void>() {
@Override
public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
JCMethodInvocation jcmi = (JCMethodInvocation) node;
apply(jcmi);
return super.visitMethodInvocation(node, p);
}
private void apply(JCMethodInvocation jcmi) {
if (!(jcmi.meth instanceof JCIdent))
return;
JCIdent jci = (JCIdent) jcmi.meth;
if (Arrays.binarySearch(knownMethodNames_, jci.name.toString()) < 0)
return;
jcmi.meth = maker.Select(maker.Ident(helperName), jci.name);
helperUsed[0] = true;
}
};
while (it.hasNext()) {
JCStatement stat = it.next();
stat.accept(visitor, null);
}
if (!helperUsed[0]) {
annotationNode.addWarning("No methods of this helper class are ever used.");
return;
}
ListBuffer<JCStatement> newStatements = new ListBuffer<JCStatement>();
boolean mark = false;
for (JCStatement stat : origStatements) {
newStatements.append(stat);
if (mark || stat != annotatedType_)
continue;
mark = true;
JCExpression init = maker.NewClass(null, List.<JCExpression>nil(), maker.Ident(annotatedType_.name), List.<JCExpression>nil(), null);
JCExpression varType = maker.Ident(annotatedType_.name);
JCVariableDecl decl = maker.VarDef(maker.Modifiers(Flags.FINAL), helperName, varType, init);
newStatements.append(decl);
}
setStatementsOfJcNode(containingBlock.get(), newStatements.toList());
}
Aggregations