diff --git a/plugins/lombok/lombok-compiler-plugin/README.md b/plugins/lombok/lombok-compiler-plugin/README.md index 60c736bdb33..dfc2d678179 100644 --- a/plugins/lombok/lombok-compiler-plugin/README.md +++ b/plugins/lombok/lombok-compiler-plugin/README.md @@ -13,7 +13,13 @@ Features support: - [x] Basic support - [x] Class-level - [x] @Accessors config support: chain and fluent - - [ ] Config support (_lombok.getter.noIsPrefix_ only supported atm) + - [~] Config support + - [x] lombok.getter.noIsPrefix + - [x] lombok.accessors.fluent + - [x] lombok.accessors.chain + - [ ] lombok.accessors.prefix + - [ ] lombok.noArgsConstructor.extraPrivate + - [ ] lombok.copyableAnnotations - [ ] Copy annotations - [ ] Strip defined prefixes - in config and @Accessors - [ ] Skip generation with AccessLevel.NONE diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/config/annotationConfig.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/config/annotationConfig.kt index 0c0ded53d5d..a4df656932c 100644 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/config/annotationConfig.kt +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/config/annotationConfig.kt @@ -15,6 +15,14 @@ import org.jetbrains.kotlin.lombok.utils.getNonBlankStringArgument import org.jetbrains.kotlin.lombok.utils.getVisibility import org.jetbrains.kotlin.name.FqName +/* + * Lombok has two ways of configuration - lombok.config file and directly in annotations. Annotations has priority. + * Not all things can be configured in annotations + * So to make things easier I put all configuration in 'annotations' classes, but populate them from config too. So far it allows + * keeping processors' code unaware about configuration origin. + * + */ + abstract class AnnotationCompanion { abstract val name: FqName @@ -25,19 +33,44 @@ abstract class AnnotationCompanion { annotated.annotations.findAnnotation(name)?.let(this::extract) } +abstract class AnnotationAndConfigCompanion { + + abstract val annotationName: FqName + + + abstract fun extract(annotation: AnnotationDescriptor?, config: LombokConfig): T + + /** + * Get from annotation or config or default + */ + fun get(annotated: Annotated, config: LombokConfig): T = + extract(annotated.annotations.findAnnotation(annotationName), config) + + /** + * If element is annotated, get from it or config or default + */ + fun getIfAnnotated(annotated: Annotated, config: LombokConfig): T? = + annotated.annotations.findAnnotation(annotationName)?.let { annotation -> + extract(annotation, config) + } + +} + data class Accessors(val fluent: Boolean = false, val chain: Boolean = false) { - companion object : AnnotationCompanion() { + companion object : AnnotationAndConfigCompanion() { - val default = Accessors() + override val annotationName: FqName = LombokNames.ACCESSORS - override val name: FqName = LombokNames.ACCESSORS - - override fun extract(annotation: AnnotationDescriptor): Accessors { - val fluent = annotation.getBooleanArgument("fluent") - return Accessors( - fluent = fluent, - chain = annotation.getBooleanArgument("chain", default = fluent) - ) + override fun extract(annotation: AnnotationDescriptor?, config: LombokConfig): Accessors { + val fluent = + annotation?.getBooleanArgument("fluent") + ?: config.getBoolean("lombok.accessors.fluent") + ?: false + val chain = + annotation?.getBooleanArgument("chain") + ?: config.getBoolean("lombok.accessors.chain") + ?: fluent + return Accessors(fluent, chain) } } } diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/GetterProcessor.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/GetterProcessor.kt index 609f65f598b..53ca8bc4fbe 100644 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/GetterProcessor.kt +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/GetterProcessor.kt @@ -24,7 +24,7 @@ class GetterProcessor(private val config: LombokConfig) : Processor { private val noIsPrefix by lazy { config.getBooleanOrDefault("lombok.getter.noIsPrefix") } override fun contribute(classDescriptor: ClassDescriptor, jClass: JavaClassImpl): Parts { - val clAccessors = Accessors.getOrNull(classDescriptor) + val globalAccessors = Accessors.get(classDescriptor, config) val clGetter = Getter.getOrNull(classDescriptor) ?: Data.getOrNull(classDescriptor)?.asGetter() @@ -33,7 +33,7 @@ class GetterProcessor(private val config: LombokConfig) : Processor { val functions = classDescriptor .getJavaFields() .collectWithNotNull { Getter.getOrNull(it) ?: clGetter } - .mapNotNull { (field, annotation) -> createGetter(classDescriptor, field, annotation, clAccessors) } + .mapNotNull { (field, annotation) -> createGetter(classDescriptor, field, annotation, globalAccessors) } return Parts(functions) } @@ -42,9 +42,9 @@ class GetterProcessor(private val config: LombokConfig) : Processor { classDescriptor: ClassDescriptor, field: PropertyDescriptor, getter: Getter, - classLevelAccessors: Accessors? + globalAccessors: Accessors ): SimpleFunctionDescriptor? { - val accessors = Accessors.getOrNull(field) ?: classLevelAccessors ?: Accessors.default + val accessors = Accessors.getIfAnnotated(field, config) ?: globalAccessors val functionName = if (accessors.fluent) { diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/SetterProcessor.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/SetterProcessor.kt index 23353090402..4b9134c3196 100644 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/SetterProcessor.kt +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/SetterProcessor.kt @@ -21,13 +21,13 @@ class SetterProcessor(private val config: LombokConfig) : Processor { //lombok doesn't generate setters for enums if (classDescriptor.kind == ClassKind.ENUM_CLASS) return Parts.Empty - val clAccessors = Accessors.getOrNull(classDescriptor) + val globalAccessors = Accessors.get(classDescriptor, config) val clSetter = Setter.getOrNull(classDescriptor) ?: Data.getOrNull(classDescriptor)?.asSetter() val functions = classDescriptor .getJavaFields() .collectWithNotNull { field -> Setter.getOrNull(field) ?: clSetter.takeIf { field.isVar } } - .mapNotNull { (field, setter) -> createSetter(classDescriptor, field, setter, clAccessors) } + .mapNotNull { (field, setter) -> createSetter(classDescriptor, field, setter, globalAccessors) } return Parts(functions) } @@ -35,9 +35,9 @@ class SetterProcessor(private val config: LombokConfig) : Processor { classDescriptor: ClassDescriptor, field: PropertyDescriptor, getter: Setter, - classLevelAccessors: Accessors? + globalAccessors: Accessors ): SimpleFunctionDescriptor? { - val accessors = Accessors.getOrNull(field) ?: classLevelAccessors ?: Accessors.default + val accessors = Accessors.getIfAnnotated(field, config) ?: globalAccessors val functionName = if (accessors.fluent) { diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/utils/annotationUtils.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/utils/annotationUtils.kt index 0c4e4e67e1d..210959a8031 100644 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/utils/annotationUtils.kt +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/utils/annotationUtils.kt @@ -42,9 +42,9 @@ fun AnnotationDescriptor.getStringArgument(argumentName: String): String? { fun AnnotationDescriptor.getNonBlankStringArgument(argumentName: String): String? = getStringArgument(argumentName).trimToNull() -fun AnnotationDescriptor.getBooleanArgument(argumentName: String, default: Boolean = false): Boolean { +fun AnnotationDescriptor.getBooleanArgument(argumentName: String): Boolean? { val argument = allValueArguments[Name.identifier(argumentName)] - ?: return default + ?: return null return when (argument) { is BooleanValue -> argument.value diff --git a/plugins/lombok/lombok-compiler-plugin/testData/compile/configAccessors.kt b/plugins/lombok/lombok-compiler-plugin/testData/compile/configAccessors.kt new file mode 100644 index 00000000000..d648d1c4453 --- /dev/null +++ b/plugins/lombok/lombok-compiler-plugin/testData/compile/configAccessors.kt @@ -0,0 +1,33 @@ +//FILE: GetterTest.java + +import lombok.*; + +@Getter @Setter +public class GetterTest { + private String name; + private int age; + + static void test() { + val obj = new GetterTest(); + GetterTest ref = obj.name("some").age(34); + obj.name(); + obj.age(); + } + +} + + +//FILE: test.kt + +class Test { + fun run() { + val obj = GetterTest() + val ref: GetterTest = obj.name("some").age(34) + obj.name() + obj.age() + } +} + +//FILE: lombok.config +lombok.accessors.fluent=true +//lombok.accessors.chain=false diff --git a/plugins/lombok/lombok-compiler-plugin/testData/compile/configAccessorsOverride.kt b/plugins/lombok/lombok-compiler-plugin/testData/compile/configAccessorsOverride.kt new file mode 100644 index 00000000000..19667c15edd --- /dev/null +++ b/plugins/lombok/lombok-compiler-plugin/testData/compile/configAccessorsOverride.kt @@ -0,0 +1,36 @@ +//FILE: GetterTest.java + +import lombok.*; +import lombok.experimental.*; + +@Getter @Setter +public class GetterTest { + private String name; + private int age; + @Accessors(chain = true) + private boolean fluent; + + static void test() { + val obj = new GetterTest(); + GetterTest ref = obj.fluent(true); + obj.name(); + obj.age(); + } + +} + + +//FILE: test.kt + +class Test { + fun run() { + val obj = GetterTest() + val ref: GetterTest = obj.fluent(true) + obj.name() + obj.age() + } +} + +//FILE: lombok.config +lombok.accessors.fluent=true +lombok.accessors.chain=false diff --git a/plugins/lombok/lombok-compiler-plugin/tests/org/jetbrains/kotlin/lombok/LombokCompileTestGenerated.java b/plugins/lombok/lombok-compiler-plugin/tests/org/jetbrains/kotlin/lombok/LombokCompileTestGenerated.java index 77541b296df..b6a7cb0f440 100644 --- a/plugins/lombok/lombok-compiler-plugin/tests/org/jetbrains/kotlin/lombok/LombokCompileTestGenerated.java +++ b/plugins/lombok/lombok-compiler-plugin/tests/org/jetbrains/kotlin/lombok/LombokCompileTestGenerated.java @@ -31,11 +31,6 @@ public class LombokCompileTestGenerated extends AbstractLombokCompileTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/lombok/lombok-compiler-plugin/testData/compile"), Pattern.compile("^(.+)\\.kt$"), null, true); } - @TestMetadata("configSimple.kt") - public void testConfigSimple() throws Exception { - runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/configSimple.kt"); - } - @TestMetadata("allArgsConstructor.kt") public void testAllArgsConstructor() throws Exception { runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/allArgsConstructor.kt"); @@ -51,6 +46,21 @@ public class LombokCompileTestGenerated extends AbstractLombokCompileTest { runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/clashAccessors.kt"); } + @TestMetadata("configAccessors.kt") + public void testConfigAccessors() throws Exception { + runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/configAccessors.kt"); + } + + @TestMetadata("configAccessorsOverride.kt") + public void testConfigAccessorsOverride() throws Exception { + runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/configAccessorsOverride.kt"); + } + + @TestMetadata("configSimple.kt") + public void testConfigSimple() throws Exception { + runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/configSimple.kt"); + } + @TestMetadata("data.kt") public void testData() throws Exception { runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/data.kt");