protected int diffAnnotation(JCAnnotation oldT, JCAnnotation newT, int[] bounds) { int localPointer = bounds[0]; int[] annotationBounds = getBounds(oldT.annotationType); copyTo(localPointer, annotationBounds[0]); localPointer = diffTree(oldT.annotationType, newT.annotationType, annotationBounds); JavaTokenId[] parens = null; if (oldT.args.nonEmpty()) { copyTo(localPointer, localPointer = getOldPos(oldT.args.head)); } else { // check, if there are already written parenthesis int endPos = endPos(oldT); tokenSequence.move(endPos); tokenSequence.movePrevious(); if (JavaTokenId.RPAREN != tokenSequence.token().id()) { parens = new JavaTokenId[] { JavaTokenId.LPAREN, JavaTokenId.RPAREN }; } else { endPos -= 1; } copyTo(localPointer, localPointer = endPos); } localPointer = diffParameterList(oldT.args, newT.args, oldT, parens, localPointer, Measure.ARGUMENT); copyTo(localPointer, bounds[1]); return bounds[1]; }
private int diffAnnotationsLists(com.sun.tools.javac.util.List<JCAnnotation> oldAnnotations, com.sun.tools.javac.util.List<JCAnnotation> newAnnotations, int startPos, int localPointer) { int annotationsEnd = oldAnnotations.nonEmpty() ? endPos(oldAnnotations) : localPointer; if (listsMatch(oldAnnotations, newAnnotations)) { copyTo(localPointer, localPointer = (annotationsEnd != localPointer ? annotationsEnd : startPos)); } else { tokenSequence.move(startPos); if (tokenSequence.movePrevious() && JavaTokenId.WHITESPACE == tokenSequence.token().id()) { String text = tokenSequence.token().text().toString(); int index = text.lastIndexOf('\n'); startPos = tokenSequence.offset(); if (index > -1) { startPos += index + 1; } if (startPos < localPointer) startPos = localPointer; } copyTo(localPointer, startPos); PositionEstimator est = EstimatorFactory.annotations(oldAnnotations,newAnnotations, diffContext, parameterPrint); localPointer = diffList(oldAnnotations, newAnnotations, startPos, est, Measure.ARGUMENT, printer); } return localPointer; }
/** * Resolve an identifier. * * @param name The identifier to resolve */ public Symbol resolveIdent(String name) { if (name.equals("")) return syms.errSymbol; JavaFileObject prev = log.useSource(null); try { JCExpression tree = null; for (String s : name.split("\\.", -1)) { if (!SourceVersion.isIdentifier(s)) // TODO: check for keywords return syms.errSymbol; tree = (tree == null) ? make.Ident(names.fromString(s)) : make.Select(tree, names.fromString(s)); } JCCompilationUnit toplevel = make.TopLevel(List.<JCAnnotation>nil(), null, List.<JCTree>nil()); toplevel.packge = syms.unnamedPackage; return attr.attribIdent(tree, toplevel); } finally { log.useSource(prev); } }
@Override public void visitAnnotation(JCAnnotation tree) { print("@"); print(tree.annotationType); if (tree.args.isEmpty()) return; print("("); boolean done = false; if (tree.args.length() == 1 && tree.args.get(0) instanceof JCAssign) { JCAssign arg1 = (JCAssign) tree.args.get(0); JCIdent arg1Name = arg1.lhs instanceof JCIdent ? ((JCIdent) arg1.lhs) : null; if (arg1Name != null && arg1Name.name == name_value(arg1Name.name)) { print(arg1.rhs); done = true; } } if (!done) print(tree.args, ", "); print(")"); }
/** * Handles the provided annotation node by first finding a qualifying instance of * {@link JavacAnnotationHandler} and if one exists, calling it with a freshly cooked up * instance of {@link lombok.core.AnnotationValues}. * * Note that depending on the printASTOnly flag, the {@link lombok.core.PrintAST} annotation * will either be silently skipped, or everything that isn't {@code PrintAST} will be skipped. * * The HandlerLibrary will attempt to guess if the given annotation node represents a lombok annotation. * For example, if {@code lombok.*} is in the import list, then this method will guess that * {@code Getter} refers to {@code lombok.Getter}, presuming that {@link lombok.javac.handlers.HandleGetter} * has been loaded. * * @param unit The Compilation Unit that contains the Annotation AST Node. * @param node The Lombok AST Node representing the Annotation AST Node. * @param annotation 'node.get()' - convenience parameter. */ public void handleAnnotation(JCCompilationUnit unit, JavacNode node, JCAnnotation annotation, long priority) { TypeResolver resolver = new TypeResolver(node.getImportList()); String rawType = annotation.annotationType.toString(); String fqn = resolver.typeRefToFullyQualifiedName(node, typeLibrary, rawType); if (fqn == null) return; AnnotationHandlerContainer<?> container = annotationHandlers.get(fqn); if (container == null) return; try { if (container.getPriority() == priority) { if (checkAndSetHandled(annotation)) container.handle(node); } } catch (AnnotationValueDecodeFail fail) { fail.owner.setError(fail.getMessage(), fail.idx); } catch (Throwable t) { String sourceName = "(unknown).java"; if (unit != null && unit.sourcefile != null) sourceName = unit.sourcefile.getName(); javacError(String.format("Lombok annotation handler %s failed on " + sourceName, container.handler.getClass()), t); } }
/** {@inheritDoc} */ @Override protected JavacNode buildTree(JCTree node, Kind kind) { switch (kind) { case COMPILATION_UNIT: return buildCompilationUnit((JCCompilationUnit) node); case TYPE: return buildType((JCClassDecl) node); case FIELD: return buildField((JCVariableDecl) node); case INITIALIZER: return buildInitializer((JCBlock) node); case METHOD: return buildMethod((JCMethodDecl) node); case ARGUMENT: return buildLocalVar((JCVariableDecl) node, kind); case LOCAL: return buildLocalVar((JCVariableDecl) node, kind); case STATEMENT: return buildStatementOrExpression(node); case ANNOTATION: return buildAnnotation((JCAnnotation) node, false); default: throw new AssertionError("Did not expect: " + kind); } }
private JavacNode buildType(JCClassDecl type) { if (setAndGetAsHandled(type)) return null; List<JavacNode> childNodes = new ArrayList<JavacNode>(); for (JCAnnotation annotation : type.mods.annotations) addIfNotNull(childNodes, buildAnnotation(annotation, false)); for (JCTree def : type.defs) { /* A def can be: * JCClassDecl for inner types * JCMethodDecl for constructors and methods * JCVariableDecl for fields * JCBlock for (static) initializers */ if (def instanceof JCMethodDecl) addIfNotNull(childNodes, buildMethod((JCMethodDecl)def)); else if (def instanceof JCClassDecl) addIfNotNull(childNodes, buildType((JCClassDecl)def)); else if (def instanceof JCVariableDecl) addIfNotNull(childNodes, buildField((JCVariableDecl)def)); else if (def instanceof JCBlock) addIfNotNull(childNodes, buildInitializer((JCBlock)def)); } return putInMap(new JavacNode(this, type, childNodes, Kind.TYPE)); }
@Override public void handle(AnnotationValues<NoArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.NO_ARGS_CONSTRUCTOR_FLAG_USAGE, "@NoArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor"); deleteAnnotationIfNeccessary(annotationNode, NoArgsConstructor.class); deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode typeNode = annotationNode.up(); if (!checkLegality(typeNode, annotationNode, NoArgsConstructor.class.getSimpleName())) return; List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@NoArgsConstructor(onConstructor=", annotationNode); NoArgsConstructor ann = annotation.getInstance(); AccessLevel level = ann.access(); if (level == AccessLevel.NONE) return; String staticName = ann.staticName(); boolean force = ann.force(); List<JavacNode> fields = force ? findFinalFields(typeNode) : List.<JavacNode>nil(); new HandleConstructor().generateConstructor(typeNode, level, onConstructor, fields, force, staticName, SkipIfConstructorExists.NO, null, annotationNode); }
@Override public void handle(AnnotationValues<RequiredArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.REQUIRED_ARGS_CONSTRUCTOR_FLAG_USAGE, "@RequiredArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor"); deleteAnnotationIfNeccessary(annotationNode, RequiredArgsConstructor.class); deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode typeNode = annotationNode.up(); if (!checkLegality(typeNode, annotationNode, RequiredArgsConstructor.class.getSimpleName())) return; List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@RequiredArgsConstructor(onConstructor=", annotationNode); RequiredArgsConstructor ann = annotation.getInstance(); AccessLevel level = ann.access(); if (level == AccessLevel.NONE) return; String staticName = ann.staticName(); Boolean suppressConstructorProperties = null; if (annotation.isExplicit("suppressConstructorProperties")) { @SuppressWarnings("deprecation") boolean suppress = ann.suppressConstructorProperties(); suppressConstructorProperties = suppress; } new HandleConstructor().generateConstructor(typeNode, level, onConstructor, findRequiredFields(typeNode), false, staticName, SkipIfConstructorExists.NO, suppressConstructorProperties, annotationNode); }
@Override public void handle(AnnotationValues<AllArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.ALL_ARGS_CONSTRUCTOR_FLAG_USAGE, "@AllArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor"); deleteAnnotationIfNeccessary(annotationNode, AllArgsConstructor.class); deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode typeNode = annotationNode.up(); if (!checkLegality(typeNode, annotationNode, AllArgsConstructor.class.getSimpleName())) return; List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@AllArgsConstructor(onConstructor=", annotationNode); AllArgsConstructor ann = annotation.getInstance(); AccessLevel level = ann.access(); if (level == AccessLevel.NONE) return; String staticName = ann.staticName(); Boolean suppressConstructorProperties = null; if (annotation.isExplicit("suppressConstructorProperties")) { @SuppressWarnings("deprecation") boolean suppress = ann.suppressConstructorProperties(); suppressConstructorProperties = suppress; } new HandleConstructor().generateConstructor(typeNode, level, onConstructor, findAllFields(typeNode), false, staticName, SkipIfConstructorExists.NO, suppressConstructorProperties, annotationNode); }
@Override public void handle(AnnotationValues<Setter> annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.SETTER_FLAG_USAGE, "@Setter"); Collection<JavacNode> fields = annotationNode.upFromAnnotationToFields(); deleteAnnotationIfNeccessary(annotationNode, Setter.class); deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode node = annotationNode.up(); AccessLevel level = annotation.getInstance().value(); if (level == AccessLevel.NONE || node == null) return; List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod=", annotationNode); List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam=", annotationNode); switch (node.getKind()) { case FIELD: createSetterForFields(level, fields, annotationNode, true, onMethod, onParam); break; case TYPE: if (!onMethod.isEmpty()) annotationNode.addError("'onMethod' is not supported for @Setter on a type."); if (!onParam.isEmpty()) annotationNode.addError("'onParam' is not supported for @Setter on a type."); generateSetterForType(node, annotationNode, level, false); break; } }
/** * Checks if there is a (non-default) constructor. In case of multiple constructors (overloading), only * the first constructor decides if EXISTS_BY_USER or EXISTS_BY_LOMBOK is returned. * * @param node Any node that represents the Type (JCClassDecl) to look in, or any child node thereof. */ public static MemberExistsResult constructorExists(JavacNode node) { node = upToTypeNode(node); if (node != null && node.get() instanceof JCClassDecl) { top: for (JCTree def : ((JCClassDecl)node.get()).defs) { if (def instanceof JCMethodDecl) { JCMethodDecl md = (JCMethodDecl) def; if (md.name.contentEquals("<init>")) { if ((md.mods.flags & Flags.GENERATEDCONSTR) != 0) continue; List<JCAnnotation> annotations = md.getModifiers().getAnnotations(); if (annotations != null) for (JCAnnotation anno : annotations) { if (typeMatches(Tolerate.class, node, anno.getAnnotationType())) continue top; } return getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK; } } } } return MemberExistsResult.NOT_EXISTS; }
/** * Searches the given field node for annotations and returns each one that matches the provided regular expression pattern. * * Only the simple name is checked - the package and any containing class are ignored. */ public static List<JCAnnotation> findAnnotations(JavacNode fieldNode, Pattern namePattern) { ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>(); for (JavacNode child : fieldNode.down()) { if (child.getKind() == Kind.ANNOTATION) { JCAnnotation annotation = (JCAnnotation) child.get(); String name = annotation.annotationType.toString(); int idx = name.lastIndexOf("."); String suspect = idx == -1 ? name : name.substring(idx + 1); if (namePattern.matcher(suspect).matches()) { result.append(annotation); } } } return result.toList(); }
@Override public void handle(AnnotationValues<SneakyThrows> annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.SNEAKY_THROWS_FLAG_USAGE, "@SneakyThrows"); deleteAnnotationIfNeccessary(annotationNode, SneakyThrows.class); Collection<String> exceptionNames = annotation.getRawExpressions("value"); if (exceptionNames.isEmpty()) { exceptionNames = Collections.singleton("java.lang.Throwable"); } java.util.List<String> exceptions = new ArrayList<String>(); for (String exception : exceptionNames) { if (exception.endsWith(".class")) exception = exception.substring(0, exception.length() - 6); exceptions.add(exception); } JavacNode owner = annotationNode.up(); switch (owner.getKind()) { case METHOD: handleMethod(annotationNode, (JCMethodDecl)owner.get(), exceptions); break; default: annotationNode.addError("@SneakyThrows is legal only on methods and constructors."); break; } }
@Override public void handle(AnnotationValues<Wither> annotation, JCAnnotation ast, JavacNode annotationNode) { handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.WITHER_FLAG_USAGE, "@Wither"); Collection<JavacNode> fields = annotationNode.upFromAnnotationToFields(); deleteAnnotationIfNeccessary(annotationNode, Wither.class); deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode node = annotationNode.up(); AccessLevel level = annotation.getInstance().value(); if (level == AccessLevel.NONE || node == null) return; List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Wither(onMethod=", annotationNode); List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Wither(onParam=", annotationNode); switch (node.getKind()) { case FIELD: createWitherForFields(level, fields, annotationNode, true, onMethod, onParam); break; case TYPE: if (!onMethod.isEmpty()) annotationNode.addError("'onMethod' is not supported for @Wither on a type."); if (!onParam.isEmpty()) annotationNode.addError("'onParam' is not supported for @Wither on a type."); generateWitherForType(node, annotationNode, level, false); break; } }
public JCMethodDecl createCanEqual(JavacNode typeNode, JCTree source, List<JCAnnotation> onParam) { /* protected boolean canEqual(final java.lang.Object other) { * return other instanceof Outer.Inner.MyType; * } */ JavacTreeMaker maker = typeNode.getTreeMaker(); JCModifiers mods = maker.Modifiers(Flags.PROTECTED, List.<JCAnnotation>nil()); JCExpression returnType = maker.TypeIdent(CTC_BOOLEAN); Name canEqualName = typeNode.toName("canEqual"); JCExpression objectType = genJavaLangTypeRef(typeNode, "Object"); Name otherName = typeNode.toName("other"); long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext()); List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(flags, onParam), otherName, objectType, null)); JCBlock body = maker.Block(0, List.<JCStatement>of( maker.Return(maker.TypeTest(maker.Ident(otherName), createTypeReference(typeNode))))); return recursiveSetGeneratedBy(maker.MethodDef(mods, canEqualName, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source, typeNode.getContext()); }
@Override public void handle(AnnotationValues<Data> annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.DATA_FLAG_USAGE, "@Data"); deleteAnnotationIfNeccessary(annotationNode, Data.class); JavacNode typeNode = annotationNode.up(); boolean notAClass = !isClass(typeNode); if (notAClass) { annotationNode.addError("@Data is only supported on a class."); return; } String staticConstructorName = annotation.getInstance().staticConstructor(); // TODO move this to the end OR move it to the top in eclipse. new HandleConstructor().generateRequiredArgsConstructor(typeNode, AccessLevel.PUBLIC, staticConstructorName, SkipIfConstructorExists.YES, annotationNode); new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true); new HandleSetter().generateSetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true); new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode); new HandleToString().generateToStringForType(typeNode, annotationNode); }
public void visitAnnotation(JCAnnotation tree) { try { print("@"); printExpr(tree.annotationType); if (tree.args.nonEmpty()) { print("("); if (tree.args.length() == 1 && tree.args.get(0) instanceof JCAssign) { JCExpression lhs = ((JCAssign)tree.args.get(0)).lhs; if (lhs instanceof JCIdent && ((JCIdent)lhs).name.toString().equals("value")) tree.args = List.of(((JCAssign)tree.args.get(0)).rhs); } printExprs(tree.args); print(")"); } } catch (IOException e) { throw new UncheckedIOException(e); } }
@Override public void handle(AnnotationValues<RequiredArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.REQUIRED_ARGS_CONSTRUCTOR_FLAG_USAGE, "@RequiredArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor"); deleteAnnotationIfNeccessary(annotationNode, RequiredArgsConstructor.class); deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode typeNode = annotationNode.up(); if (!checkLegality(typeNode, annotationNode, RequiredArgsConstructor.class.getSimpleName())) return; List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@RequiredArgsConstructor(onConstructor=", annotationNode); RequiredArgsConstructor ann = annotation.getInstance(); AccessLevel level = ann.access(); if (level == AccessLevel.NONE) return; String staticName = ann.staticName(); Boolean suppressConstructorProperties = null; if (annotation.isExplicit("suppressConstructorProperties")) { @SuppressWarnings("deprecation") boolean suppress = ann.suppressConstructorProperties(); suppressConstructorProperties = suppress; } new HandleConstructor().generateConstructor(typeNode, level, onConstructor, findRequiredFields(typeNode), staticName, SkipIfConstructorExists.NO, suppressConstructorProperties, annotationNode); }
@Override public void handle(AnnotationValues<AllArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.ALL_ARGS_CONSTRUCTOR_FLAG_USAGE, "@AllArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor"); deleteAnnotationIfNeccessary(annotationNode, AllArgsConstructor.class); deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode typeNode = annotationNode.up(); if (!checkLegality(typeNode, annotationNode, AllArgsConstructor.class.getSimpleName())) return; List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@AllArgsConstructor(onConstructor=", annotationNode); AllArgsConstructor ann = annotation.getInstance(); AccessLevel level = ann.access(); if (level == AccessLevel.NONE) return; String staticName = ann.staticName(); Boolean suppressConstructorProperties = null; if (annotation.isExplicit("suppressConstructorProperties")) { @SuppressWarnings("deprecation") boolean suppress = ann.suppressConstructorProperties(); suppressConstructorProperties = suppress; } new HandleConstructor().generateConstructor(typeNode, level, onConstructor, findAllFields(typeNode), staticName, SkipIfConstructorExists.NO, suppressConstructorProperties, annotationNode); }
public JCMethodDecl createCanEqual(JavacNode typeNode, JCTree source, List<JCAnnotation> onParam) { /* public boolean canEqual(final java.lang.Object other) { * return other instanceof Outer.Inner.MyType; * } */ JavacTreeMaker maker = typeNode.getTreeMaker(); JCModifiers mods = maker.Modifiers(Flags.PROTECTED, List.<JCAnnotation>nil()); JCExpression returnType = maker.TypeIdent(CTC_BOOLEAN); Name canEqualName = typeNode.toName("canEqual"); JCExpression objectType = genJavaLangTypeRef(typeNode, "Object"); Name otherName = typeNode.toName("other"); long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext()); List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(flags, onParam), otherName, objectType, null)); JCBlock body = maker.Block(0, List.<JCStatement>of( maker.Return(maker.TypeTest(maker.Ident(otherName), createTypeReference(typeNode))))); return recursiveSetGeneratedBy(maker.MethodDef(mods, canEqualName, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source, typeNode.getContext()); }
private void printAnnotations(List<JCAnnotation> annotations, boolean newlines) { for (JCAnnotation ann : annotations) { print(ann); if (newlines) { println(); align(); } else print(" "); } }
@Override protected boolean fieldContainsAnnotation(JCTree field, JCTree annotation) { if (!(field instanceof JCVariableDecl)) return false; JCVariableDecl f = (JCVariableDecl) field; if (f.mods.annotations == null) return false; for (JCAnnotation childAnnotation : f.mods.annotations) { if (childAnnotation == annotation) return true; } return false; }
private JavacNode buildField(JCVariableDecl field) { if (setAndGetAsHandled(field)) return null; List<JavacNode> childNodes = new ArrayList<JavacNode>(); for (JCAnnotation annotation : field.mods.annotations) addIfNotNull(childNodes, buildAnnotation(annotation, true)); addIfNotNull(childNodes, buildExpression(field.init)); return putInMap(new JavacNode(this, field, childNodes, Kind.FIELD)); }
private JavacNode buildLocalVar(JCVariableDecl local, Kind kind) { if (setAndGetAsHandled(local)) return null; List<JavacNode> childNodes = new ArrayList<JavacNode>(); for (JCAnnotation annotation : local.mods.annotations) addIfNotNull(childNodes, buildAnnotation(annotation, true)); addIfNotNull(childNodes, buildExpression(local.init)); return putInMap(new JavacNode(this, local, childNodes, kind)); }
private JavacNode buildMethod(JCMethodDecl method) { if (setAndGetAsHandled(method)) return null; List<JavacNode> childNodes = new ArrayList<JavacNode>(); for (JCAnnotation annotation : method.mods.annotations) addIfNotNull(childNodes, buildAnnotation(annotation, false)); for (JCVariableDecl param : method.params) addIfNotNull(childNodes, buildLocalVar(param, Kind.ARGUMENT)); if (method.body != null && method.body.stats != null) { for (JCStatement statement : method.body.stats) addIfNotNull(childNodes, buildStatement(statement)); } return putInMap(new JavacNode(this, method, childNodes, Kind.METHOD)); }
private JavacNode buildAnnotation(JCAnnotation annotation, boolean varDecl) { boolean handled = setAndGetAsHandled(annotation); if (!varDecl && handled) { // @Foo int x, y; is handled in javac by putting the same annotation node on 2 JCVariableDecls. return null; } return putInMap(new JavacNode(this, annotation, null, Kind.ANNOTATION)); }
private JavacNode buildStatementOrExpression(JCTree statement) { if (statement == null) return null; if (statement instanceof JCAnnotation) return null; if (statement instanceof JCClassDecl) return buildType((JCClassDecl)statement); if (statement instanceof JCVariableDecl) return buildLocalVar((JCVariableDecl)statement, Kind.LOCAL); if (statement instanceof JCTry) return buildTry((JCTry) statement); if (setAndGetAsHandled(statement)) return null; return drill(statement); }
public void generateConstructor(JavacNode typeNode, AccessLevel level, List<JCAnnotation> onConstructor, List<JavacNode> fields, boolean allToDefault, String staticName, SkipIfConstructorExists skipIfConstructorExists, Boolean suppressConstructorProperties, JavacNode source) { boolean staticConstrRequired = staticName != null && !staticName.equals(""); if (skipIfConstructorExists != SkipIfConstructorExists.NO && constructorExists(typeNode) != MemberExistsResult.NOT_EXISTS) return; if (skipIfConstructorExists != SkipIfConstructorExists.NO) { for (JavacNode child : typeNode.down()) { if (child.getKind() == Kind.ANNOTATION) { boolean skipGeneration = annotationTypeMatches(NoArgsConstructor.class, child) || annotationTypeMatches(AllArgsConstructor.class, child) || annotationTypeMatches(RequiredArgsConstructor.class, child); if (!skipGeneration && skipIfConstructorExists == SkipIfConstructorExists.YES) { skipGeneration = annotationTypeMatches(Builder.class, child); } if (skipGeneration) { if (staticConstrRequired) { // @Data has asked us to generate a constructor, but we're going to skip this instruction, as an explicit 'make a constructor' annotation // will take care of it. However, @Data also wants a specific static name; this will be ignored; the appropriate way to do this is to use // the 'staticName' parameter of the @XArgsConstructor you've stuck on your type. // We should warn that we're ignoring @Data's 'staticConstructor' param. source.addWarning("Ignoring static constructor name: explicit @XxxArgsConstructor annotation present; its `staticName` parameter will be used."); } return; } } } } JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, onConstructor, typeNode, fields, allToDefault, suppressConstructorProperties, source); injectMethod(typeNode, constr); if (staticConstrRequired) { JCMethodDecl staticConstr = createStaticConstructor(staticName, level, typeNode, allToDefault ? List.<JavacNode>nil() : fields, source.get()); injectMethod(typeNode, staticConstr); } }
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); }
@Override public void handle(AnnotationValues<Getter> annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.GETTER_FLAG_USAGE, "@Getter"); Collection<JavacNode> fields = annotationNode.upFromAnnotationToFields(); deleteAnnotationIfNeccessary(annotationNode, Getter.class); deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode node = annotationNode.up(); Getter annotationInstance = annotation.getInstance(); AccessLevel level = annotationInstance.value(); boolean lazy = annotationInstance.lazy(); if (lazy) handleFlagUsage(annotationNode, ConfigurationKeys.GETTER_LAZY_FLAG_USAGE, "@Getter(lazy=true)"); if (level == AccessLevel.NONE) { if (lazy) annotationNode.addWarning("'lazy' does not work with AccessLevel.NONE."); return; } if (node == null) return; List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Getter(onMethod=", annotationNode); switch (node.getKind()) { case FIELD: createGetterForFields(level, fields, annotationNode, true, lazy, onMethod); break; case TYPE: if (!onMethod.isEmpty()) { annotationNode.addError("'onMethod' is not supported for @Getter on a type."); } if (lazy) annotationNode.addError("'lazy' is not supported for @Getter on a type."); generateGetterForType(node, annotationNode, level, false); break; } }
@Override public void handle(AnnotationValues<Value> annotation, JCAnnotation ast, JavacNode annotationNode) { @SuppressWarnings("deprecation") Class<? extends Annotation> oldExperimentalValue = lombok.experimental.Value.class; handleFlagUsage(annotationNode, ConfigurationKeys.VALUE_FLAG_USAGE, "@Value"); deleteAnnotationIfNeccessary(annotationNode, Value.class, oldExperimentalValue); JavacNode typeNode = annotationNode.up(); boolean notAClass = !isClass(typeNode); if (notAClass) { annotationNode.addError("@Value is only supported on a class."); return; } String staticConstructorName = annotation.getInstance().staticConstructor(); if (!hasAnnotationAndDeleteIfNeccessary(NonFinal.class, typeNode)) { JCModifiers jcm = ((JCClassDecl) typeNode.get()).mods; if ((jcm.flags & Flags.FINAL) == 0) { jcm.flags |= Flags.FINAL; typeNode.rebuild(); } } new HandleFieldDefaults().generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true); // TODO move this to the end OR move it to the top in eclipse. new HandleConstructor().generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, staticConstructorName, SkipIfConstructorExists.YES, annotationNode); new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true); new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode); new HandleToString().generateToStringForType(typeNode, annotationNode); }