diff options
author | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2021-03-22 08:03:42 +0100 |
---|---|---|
committer | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2021-03-22 08:03:42 +0100 |
commit | bcd05a01b14705678dfd280989fa5071b627a234 (patch) | |
tree | 55f5af9b2b158c37f9d04b7ec27aad048d4e1ffd /src/core/lombok/javac | |
parent | ade900b82b8205bb439ac9d6d99dff0c3af6e10f (diff) | |
parent | fa0b5249cf5fee28d9be13ecdf0225f651f686aa (diff) | |
download | lombok-bcd05a01b14705678dfd280989fa5071b627a234.tar.gz lombok-bcd05a01b14705678dfd280989fa5071b627a234.tar.bz2 lombok-bcd05a01b14705678dfd280989fa5071b627a234.zip |
Merge branch 'records'
# Conflicts:
# src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
# src/core/lombok/eclipse/handlers/HandleBuilder.java
# src/core/lombok/eclipse/handlers/HandleData.java
# src/core/lombok/eclipse/handlers/HandleNonNull.java
# src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
# src/core/lombok/javac/handlers/HandleBuilder.java
# src/core/lombok/javac/handlers/HandleNonNull.java
# src/core/lombok/javac/handlers/HandleSuperBuilder.java
# test/core/src/lombok/RunTestsViaEcj.java
Diffstat (limited to 'src/core/lombok/javac')
16 files changed, 116 insertions, 84 deletions
diff --git a/src/core/lombok/javac/JavacNode.java b/src/core/lombok/javac/JavacNode.java index 3de3f38b..035f7c53 100644 --- a/src/core/lombok/javac/JavacNode.java +++ b/src/core/lombok/javac/JavacNode.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2020 The Project Lombok Authors. + * Copyright (C) 2009-2021 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -186,16 +186,6 @@ public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTre return false; } - @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; - } - /** * Convenient shortcut to the owning JavacAST object's getTreeMaker method. * diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 911a2e39..a25baeb0 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -192,6 +192,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } @Override public void handle(AnnotationValues<Builder> annotation, JCAnnotation ast, JavacNode annotationNode) { + final String BUILDER_NODE_NOT_SUPPORTED_ERR = "@Builder is only supported on classes, records, constructors, and methods."; + handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder"); BuilderJob job = new BuilderJob(); job.sourceNode = annotationNode; @@ -229,6 +231,11 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { ArrayList<JavacNode> nonFinalNonDefaultedFields = null; if (parent.get() instanceof JCClassDecl) { + if (!isClass(parent) && !isRecord(parent)) { + annotationNode.addError(BUILDER_NODE_NOT_SUPPORTED_ERR); + return; + } + job.parentType = parent; JCClassDecl td = (JCClassDecl) parent.get(); @@ -279,7 +286,11 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { allFields.append(fieldNode); } - handleConstructor.generateConstructor(parent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode); + if (!isRecord(parent)) { + // Records ship with a canonical constructor that acts as @AllArgsConstructor - just use that one. + + handleConstructor.generateConstructor(parent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode); + } buildMethodReturnType = namePlusTypeParamsToTypeReference(parent.getTreeMaker(), parent, td.typarams); job.typeParams = job.builderTypeParams = td.typarams; @@ -387,7 +398,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { } } } else { - annotationNode.addError("@Builder is only supported on types, constructors, and methods."); + annotationNode.addError(BUILDER_NODE_NOT_SUPPORTED_ERR); return; } diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java index 0defdefd..9c74ca0e 100644 --- a/src/core/lombok/javac/handlers/HandleConstructor.java +++ b/src/core/lombok/javac/handlers/HandleConstructor.java @@ -181,12 +181,7 @@ public class HandleConstructor { } public static boolean checkLegality(JavacNode typeNode, JavacNode errorNode, String name) { - JCClassDecl typeDecl = null; - if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); - long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags; - boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION)) != 0; - - if (typeDecl == null || notAClass) { + if (!isClassOrEnum(typeNode)) { errorNode.addError(name + " is only supported on a class or an enum."); return false; } diff --git a/src/core/lombok/javac/handlers/HandleData.java b/src/core/lombok/javac/handlers/HandleData.java index 5fe1e4fe..06524aa8 100644 --- a/src/core/lombok/javac/handlers/HandleData.java +++ b/src/core/lombok/javac/handlers/HandleData.java @@ -51,9 +51,8 @@ public class HandleData extends JavacAnnotationHandler<Data> { deleteAnnotationIfNeccessary(annotationNode, Data.class); JavacNode typeNode = annotationNode.up(); - boolean notAClass = !isClass(typeNode); - if (notAClass) { + if (!isClass(typeNode)) { annotationNode.addError("@Data is only supported on a class."); return; } diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index a75d551f..ffe882d8 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -95,9 +95,9 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas Boolean doNotUseGettersConfiguration = annotationNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS); boolean doNotUseGetters = annotation.isExplicit("doNotUseGetters") || doNotUseGettersConfiguration == null ? ann.doNotUseGetters() : doNotUseGettersConfiguration; FieldAccess fieldAccess = doNotUseGetters ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER; - + boolean cacheHashCode = ann.cacheStrategy() == CacheStrategy.LAZY; - + generateMethods(typeNode, annotationNode, members, callSuper, true, cacheHashCode, fieldAccess, onParam); } @@ -118,13 +118,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas public void generateMethods(JavacNode typeNode, JavacNode source, java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members, Boolean callSuper, boolean whineIfExists, boolean cacheHashCode, FieldAccess fieldAccess, List<JCAnnotation> onParam) { - boolean notAClass = true; - if (typeNode.get() instanceof JCClassDecl) { - long flags = ((JCClassDecl) typeNode.get()).mods.flags; - notAClass = (flags & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0; - } - - if (notAClass) { + if (!isClass(typeNode)) { source.addError("@EqualsAndHashCode is only supported on a class."); return; } diff --git a/src/core/lombok/javac/handlers/HandleFieldDefaults.java b/src/core/lombok/javac/handlers/HandleFieldDefaults.java index 4a87c138..ebab67e3 100644 --- a/src/core/lombok/javac/handlers/HandleFieldDefaults.java +++ b/src/core/lombok/javac/handlers/HandleFieldDefaults.java @@ -56,12 +56,7 @@ public class HandleFieldDefaults extends JavacASTAdapter { } } - JCClassDecl typeDecl = null; - if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); - long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags; - boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION)) != 0; - - if (typeDecl == null || notAClass) { + if (!isClassOrEnum(typeNode)) { errorNode.addError("@FieldDefaults is only supported on a class or an enum."); return false; } diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java index 4cfa3276..8f6de9bb 100644 --- a/src/core/lombok/javac/handlers/HandleGetter.java +++ b/src/core/lombok/javac/handlers/HandleGetter.java @@ -51,7 +51,6 @@ import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCBinary; 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.JCExpressionStatement; import com.sun.tools.javac.tree.JCTree.JCIf; @@ -72,6 +71,8 @@ import com.sun.tools.javac.util.Name; */ @Provides public class HandleGetter extends JavacAnnotationHandler<Getter> { + private static final String GETTER_NODE_NOT_SUPPORTED_ERR = "@Getter is only supported on a class, an enum, or a field."; + public void generateGetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelGetter, List<JCAnnotation> onMethod) { if (checkForTypeLevelGetter) { if (hasAnnotation(Getter.class, typeNode)) { @@ -80,13 +81,8 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { } } - JCClassDecl typeDecl = null; - if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); - long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags; - boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION)) != 0; - - if (typeDecl == null || notAClass) { - errorNode.addError("@Getter is only supported on a class, an enum, or a field."); + if (!isClassOrEnum(typeNode)) { + errorNode.addError(GETTER_NODE_NOT_SUPPORTED_ERR); return; } @@ -170,7 +166,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> { JavacNode fieldNode, JavacNode source, boolean whineIfExists, boolean lazy, List<JCAnnotation> onMethod) { if (fieldNode.getKind() != Kind.FIELD) { - source.addError("@Getter is only supported on a class or a field."); + source.addError(GETTER_NODE_NOT_SUPPORTED_ERR); return; } diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java index 674aa62c..47c4098f 100644 --- a/src/core/lombok/javac/handlers/HandleLog.java +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -31,6 +31,7 @@ import lombok.core.configuration.IdentifierName; import lombok.core.configuration.LogDeclaration; import lombok.core.configuration.LogDeclaration.LogFactoryParameter; import lombok.core.handlers.LoggingFramework; +import lombok.javac.Javac; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; import lombok.javac.JavacTreeMaker; @@ -74,9 +75,14 @@ public class HandleLog { return; } + if (isRecord(typeNode) && !useStatic) { + annotationNode.addError("Logger fields must be static in records."); + return; + } + Object valueGuess = annotation.getValueGuess("topic"); JCExpression loggerTopic = (JCExpression) annotation.getActualExpression("topic"); - + if (valueGuess instanceof String && ((String) valueGuess).trim().isEmpty()) loggerTopic = null; if (framework.getDeclaration().getParametersWithTopic() == null && loggerTopic != null) { annotationNode.addError(framework.getAnnotationAsString() + " does not allow a topic."); @@ -118,7 +124,14 @@ public class HandleLog { maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (useStatic ? Flags.STATIC : 0)), typeNode.toName(logFieldName), loggerType, factoryMethodCall), source); - injectFieldAndMarkGenerated(typeNode, fieldDecl); + if (isRecord(typeNode) && Javac.getJavaCompilerVersion() < 16) { + // This is a workaround for https://bugs.openjdk.java.net/browse/JDK-8243057 + + injectField(typeNode, fieldDecl); + } else { + injectFieldAndMarkGenerated(typeNode, fieldDecl); + } + return true; } diff --git a/src/core/lombok/javac/handlers/HandleNonNull.java b/src/core/lombok/javac/handlers/HandleNonNull.java index 174c31de..2f359c0f 100644 --- a/src/core/lombok/javac/handlers/HandleNonNull.java +++ b/src/core/lombok/javac/handlers/HandleNonNull.java @@ -49,6 +49,7 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Name; +import lombok.AccessLevel; import lombok.ConfigurationKeys; import lombok.NonNull; import lombok.core.AST.Kind; @@ -56,11 +57,14 @@ import lombok.core.AnnotationValues; import lombok.core.HandlerPriority; import lombok.javac.JavacAnnotationHandler; import lombok.javac.JavacNode; +import lombok.javac.handlers.HandleConstructor.SkipIfConstructorExists; import lombok.spi.Provides; @Provides @HandlerPriority(value = 512) // 2^9; onParameter=@__(@NonNull) has to run first. public class HandleNonNull extends JavacAnnotationHandler<NonNull> { + private HandleConstructor handleConstructor = new HandleConstructor(); + @Override public void handle(AnnotationValues<NonNull> annotation, JCAnnotation ast, JavacNode annotationNode) { handleFlagUsage(annotationNode, ConfigurationKeys.NON_NULL_FLAG_USAGE, "@NonNull"); @@ -122,6 +126,14 @@ public class HandleNonNull extends JavacAnnotationHandler<NonNull> { String expectedName = paramNode.getName(); + JavacNode typeNode = upToTypeNode(annotationNode); + + if ((declaration.mods.flags & RECORD) != 0) { + if (!lombokConstructorExists(typeNode)) { + handleConstructor.generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, null, SkipIfConstructorExists.NO, annotationNode); + } + } + /* Abort if the null check is already there, delving into try and synchronized statements */ { List<JCStatement> stats = statements; int idx = 0; diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index a4fb1b71..5c34f9f5 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -61,6 +61,8 @@ import com.sun.tools.javac.util.Name; */ @Provides public class HandleSetter extends JavacAnnotationHandler<Setter> { + private static final String SETTER_NODE_NOT_SUPPORTED_ERR = "@Setter is only supported on a class or a field."; + public void generateSetterForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelSetter, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { if (checkForTypeLevelSetter) { if (hasAnnotation(Setter.class, typeNode)) { @@ -69,13 +71,8 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { } } - JCClassDecl typeDecl = null; - if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); - long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags; - boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0; - - if (typeDecl == null || notAClass) { - errorNode.addError("@Setter is only supported on a class or a field."); + if (!isClass(typeNode)) { + errorNode.addError(SETTER_NODE_NOT_SUPPORTED_ERR); return; } @@ -149,7 +146,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { public void createSetterForField(AccessLevel level, JavacNode fieldNode, JavacNode sourceNode, boolean whineIfExists, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { if (fieldNode.getKind() != Kind.FIELD) { - fieldNode.addError("@Setter is only supported on a class or a field."); + fieldNode.addError(SETTER_NODE_NOT_SUPPORTED_ERR); return; } diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index 17b54f3c..9185cedf 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -159,14 +159,15 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { List<JCExpression> superclassTypeParams = List.nil(); boolean addCleaning = false; - if (!(parent.get() instanceof JCClassDecl)) { - annotationNode.addError("@SuperBuilder is only supported on types."); + if (!isClass(parent)) { + annotationNode.addError("@SuperBuilder is only supported on classes."); return; } - // Gather all fields of the class that should be set by the builder. job.parentType = parent; JCClassDecl td = (JCClassDecl) parent.get(); + + // Gather all fields of the class that should be set by the builder. ArrayList<JavacNode> nonFinalNonDefaultedFields = null; boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent)); diff --git a/src/core/lombok/javac/handlers/HandleSynchronized.java b/src/core/lombok/javac/handlers/HandleSynchronized.java index ca4a8293..0bf7cbe8 100644 --- a/src/core/lombok/javac/handlers/HandleSynchronized.java +++ b/src/core/lombok/javac/handlers/HandleSynchronized.java @@ -76,6 +76,12 @@ public class HandleSynchronized extends JavacAnnotationHandler<Synchronized> { return; } + JavacNode typeNode = upToTypeNode(annotationNode); + if (!isClassOrEnum(typeNode)) { + annotationNode.addError("@Synchronized is legal only on methods in classes and enums."); + return; + } + boolean[] isStatic = new boolean[] {(method.mods.flags & Flags.STATIC) != 0}; String lockName = annotation.getInstance().value(); boolean autoMake = false; @@ -86,8 +92,6 @@ public class HandleSynchronized extends JavacAnnotationHandler<Synchronized> { JavacTreeMaker maker = methodNode.getTreeMaker().at(ast.pos); - JavacNode typeNode = upToTypeNode(annotationNode); - MemberExistsResult exists = MemberExistsResult.NOT_EXISTS; if (typeNode != null && typeNode.get() instanceof JCClassDecl) { diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java index 1b76285f..3fc6a4e4 100644 --- a/src/core/lombok/javac/handlers/HandleToString.java +++ b/src/core/lombok/javac/handlers/HandleToString.java @@ -105,13 +105,7 @@ public class HandleToString extends JavacAnnotationHandler<ToString> { public void generateToString(JavacNode typeNode, JavacNode source, java.util.List<Included<JavacNode, ToString.Include>> members, 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 (notAClass) { + if (!isClassOrEnum(typeNode)) { source.addError("@ToString is only supported on a class or enum."); return; } diff --git a/src/core/lombok/javac/handlers/HandleUtilityClass.java b/src/core/lombok/javac/handlers/HandleUtilityClass.java index cb8a72ad..e006cc47 100644 --- a/src/core/lombok/javac/handlers/HandleUtilityClass.java +++ b/src/core/lombok/javac/handlers/HandleUtilityClass.java @@ -67,13 +67,8 @@ public class HandleUtilityClass extends JavacAnnotationHandler<UtilityClass> { } private static boolean checkLegality(JavacNode typeNode, JavacNode errorNode) { - JCClassDecl typeDecl = null; - if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); - long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags; - boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0; - - if (typeDecl == null || notAClass) { - errorNode.addError("@UtilityClass is only supported on a class (can't be an interface, enum, or annotation)."); + if (!isClass(typeNode)) { + errorNode.addError("@UtilityClass is only supported on a class."); return false; } diff --git a/src/core/lombok/javac/handlers/HandleWithBy.java b/src/core/lombok/javac/handlers/HandleWithBy.java index b88f2c14..f1f953b3 100644 --- a/src/core/lombok/javac/handlers/HandleWithBy.java +++ b/src/core/lombok/javac/handlers/HandleWithBy.java @@ -125,7 +125,6 @@ public class HandleWithBy extends JavacAnnotationHandler<WithBy> { @Override public void handle(AnnotationValues<WithBy> annotation, JCAnnotation ast, JavacNode annotationNode) { handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.WITHBY_FLAG_USAGE, "@WithBy"); - Collection<JavacNode> fields = annotationNode.upFromAnnotationToFields(); deleteAnnotationIfNeccessary(annotationNode, WithBy.class); deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode node = annotationNode.up(); @@ -137,7 +136,7 @@ public class HandleWithBy extends JavacAnnotationHandler<WithBy> { switch (node.getKind()) { case FIELD: - createWithByForFields(level, fields, annotationNode, true, onMethod); + createWithByForFields(level, annotationNode.upFromAnnotationToFields(), annotationNode, true, onMethod); break; case TYPE: if (!onMethod.isEmpty()) annotationNode.addError("'onMethod' is not supported for @WithBy on a type."); diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 5cbe08da..b4f2acc4 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2020 The Project Lombok Authors. + * Copyright (C) 2009-2021 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -807,7 +807,7 @@ public class JavacHandlerUtil { node = upToTypeNode(node); if (node != null && node.get() instanceof JCClassDecl) { - for (JCTree def : ((JCClassDecl)node.get()).defs) { + for (JCTree def : ((JCClassDecl) node.get()).defs) { if (def instanceof JCMethodDecl) { JCMethodDecl md = (JCMethodDecl) def; if (md.name.contentEquals("<init>")) { @@ -822,6 +822,30 @@ public class JavacHandlerUtil { return MemberExistsResult.NOT_EXISTS; } + /** + * Checks if there is at least one constructor that is generated by lombok. + * + * @param node Any node that represents the Type (TypeDeclaration) to look in, or any child node thereof. + */ + public static boolean lombokConstructorExists(JavacNode node) { + node = upToTypeNode(node); + + if (node != null && node.get() instanceof JCClassDecl) { + 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; + if (isTolerate(node, md)) continue; + if (getGeneratedBy(def) != null) return true; + } + } + } + } + + return false; + } + public static boolean isConstructorCall(final JCStatement statement) { if (!(statement instanceof JCExpressionStatement)) return false; JCExpression expr = ((JCExpressionStatement) statement).expr; @@ -1924,17 +1948,30 @@ public class JavacHandlerUtil { return out.toList(); } - static boolean isClass(JavacNode typeNode) { - return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ENUM | Flags.ANNOTATION); + /** + * Returns {@code true} if the provided node is an actual class and not some other type declaration (so, not an annotation definition, interface, enum, or record). + */ + public static boolean isClass(JavacNode typeNode) { + return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ENUM | Flags.ANNOTATION | RECORD); + } + + /** + * Returns {@code true} if the provided node is an actual class or enum and not some other type declaration (so, not an annotation definition, interface, or record). + */ + public static boolean isClassOrEnum(JavacNode typeNode) { + return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ANNOTATION | RECORD); } - static boolean isClassOrEnum(JavacNode typeNode) { - return isClassAndDoesNotHaveFlags(typeNode, Flags.INTERFACE | Flags.ANNOTATION); + /** + * Returns {@code true} if the provided node is a record declaration (so, not an annotation definition, interface, enum, or plain class). + */ + public static boolean isRecord(JavacNode typeNode) { + return typeNode.getKind() == Kind.TYPE && (((JCClassDecl) typeNode.get()).mods.flags & RECORD) != 0; } - public static boolean isClassAndDoesNotHaveFlags(JavacNode typeNode, int flags) { + public static boolean isClassAndDoesNotHaveFlags(JavacNode typeNode, long flags) { JCClassDecl typeDecl = null; - if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl)typeNode.get(); + if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); else return false; long typeDeclflags = typeDecl == null ? 0 : typeDecl.mods.flags; |