diff --git a/plugins/lombok/lombok-compiler-plugin/README.md b/plugins/lombok/lombok-compiler-plugin/README.md index 64821ae3ea9..e11f5f0f723 100644 --- a/plugins/lombok/lombok-compiler-plugin/README.md +++ b/plugins/lombok/lombok-compiler-plugin/README.md @@ -24,12 +24,12 @@ Features support: - [x] Basic support - [ ] Copy annotations -[~] [@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor](https://projectlombok.org/features/constructor) +[x] [@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor](https://projectlombok.org/features/constructor) - [x] @NoArgsConstructor - [x] @AllArgsConstructor - [x] @RequiredArgsConstructor -[ ] [@Data](https://projectlombok.org/features/Data) +[x] [@Data](https://projectlombok.org/features/Data) [ ] [@Value](https://projectlombok.org/features/Value) 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 53f6e5d6341..d0da33436b6 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 @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.lombok.config +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.annotations.Annotated import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor @@ -41,7 +42,7 @@ data class Accessors(val fluent: Boolean = false, val chain: Boolean = false) { } } -data class Getter(val visibility: DescriptorVisibility) { +data class Getter(val visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC) { companion object : AnnotationCompanion() { override val name: FqName = LombokNames.GETTER @@ -52,7 +53,7 @@ data class Getter(val visibility: DescriptorVisibility) { } } -data class Setter(val visibility: DescriptorVisibility) { +data class Setter(val visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC) { companion object : AnnotationCompanion() { override val name: FqName = LombokNames.SETTER @@ -110,8 +111,8 @@ data class AllArgsConstructor( } data class RequiredArgsConstructor( - override val visibility: DescriptorVisibility, - override val staticName: String? + override val visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC, + override val staticName: String? = null ) : ConstructorAnnotation { companion object : AnnotationCompanion() { override val name: FqName = LombokNames.REQUIRED_ARGS_CONSTRUCTOR @@ -123,3 +124,24 @@ data class RequiredArgsConstructor( ) } } + +data class Data(val staticConstructor: String?) { + + fun asSetter(): Setter = Setter() + + fun asGetter(): Getter = Getter() + + fun asRequiredArgsConstructor(): RequiredArgsConstructor = RequiredArgsConstructor( + staticName = staticConstructor + ) + + companion object : AnnotationCompanion() { + override val name: FqName = LombokNames.DATA + + override fun extract(annotation: AnnotationDescriptor): Data = + Data( + staticConstructor = annotation.getNonBlankStringArgument("staticConstructor") + ) + + } +} diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/AbstractConstructorProcessor.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/AbstractConstructorProcessor.kt index a37611ee9db..1a7048c4927 100644 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/AbstractConstructorProcessor.kt +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/AbstractConstructorProcessor.kt @@ -15,16 +15,14 @@ import org.jetbrains.kotlin.lombok.utils.createJavaConstructor import org.jetbrains.kotlin.lombok.utils.createFunction import org.jetbrains.kotlin.name.Name -abstract class AbstractConstructorProcessor( - private val annotationCompanion: AnnotationCompanion -) : Processor { +abstract class AbstractConstructorProcessor : Processor { override fun contribute(classDescriptor: ClassDescriptor, jClass: JavaClassImpl): Parts { val valueParameters = getPropertiesForParameters(classDescriptor).map { property -> ValueParameter(property.name, property.type) } - val result = annotationCompanion.getOrNull(classDescriptor)?.let { annotation -> + val result = getAnnotation(classDescriptor)?.let { annotation -> if (annotation.staticName == null) { val constructor = classDescriptor.createJavaConstructor( valueParameters = valueParameters, @@ -46,6 +44,8 @@ abstract class AbstractConstructorProcessor( return result ?: Parts.Empty } + protected abstract fun getAnnotation(classDescriptor: ClassDescriptor): A? + protected abstract fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/AllArgsConstructorProcessor.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/AllArgsConstructorProcessor.kt index cfba5d2e227..f734fac45a0 100644 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/AllArgsConstructorProcessor.kt +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/AllArgsConstructorProcessor.kt @@ -10,8 +10,12 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.lombok.config.AllArgsConstructor import org.jetbrains.kotlin.lombok.utils.getJavaFields -class AllArgsConstructorProcessor : AbstractConstructorProcessor(AllArgsConstructor) { +class AllArgsConstructorProcessor : AbstractConstructorProcessor() { - override fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List = classDescriptor.getJavaFields() + override fun getAnnotation(classDescriptor: ClassDescriptor): AllArgsConstructor? = + AllArgsConstructor.getOrNull(classDescriptor) + + override fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List = + classDescriptor.getJavaFields() } 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 0f212cf74a2..a37981b9dc4 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 @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.lombok.config.Accessors +import org.jetbrains.kotlin.lombok.config.Data import org.jetbrains.kotlin.lombok.config.Getter import org.jetbrains.kotlin.lombok.config.LombokConfig import org.jetbrains.kotlin.lombok.utils.collectWithNotNull @@ -27,7 +28,7 @@ class GetterProcessor(private val config: LombokConfig) : Processor { override fun contribute(classDescriptor: ClassDescriptor, jClass: JavaClassImpl): Parts { val clAccessors = Accessors.getOrNull(classDescriptor) - val clGetter = Getter.getOrNull(classDescriptor) + val clGetter = Getter.getOrNull(classDescriptor) ?: Data.getOrNull(classDescriptor)?.asGetter() val functions = classDescriptor .getJavaFields() diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/NoArgsConstructorProcessor.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/NoArgsConstructorProcessor.kt index 75bdce22982..474c5bb343e 100644 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/NoArgsConstructorProcessor.kt +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/NoArgsConstructorProcessor.kt @@ -9,7 +9,9 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.lombok.config.NoArgsConstructor -class NoArgsConstructorProcessor : AbstractConstructorProcessor(NoArgsConstructor) { +class NoArgsConstructorProcessor : AbstractConstructorProcessor() { + + override fun getAnnotation(classDescriptor: ClassDescriptor): NoArgsConstructor? = NoArgsConstructor.getOrNull(classDescriptor) override fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List = emptyList() } diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/RequiredArgsConstructorProcessor.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/RequiredArgsConstructorProcessor.kt index 674b4686d2f..1c1d91e01df 100644 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/RequiredArgsConstructorProcessor.kt +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/processor/RequiredArgsConstructorProcessor.kt @@ -9,12 +9,16 @@ import com.intellij.psi.PsiField import com.intellij.psi.PsiModifier import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.lombok.config.Data import org.jetbrains.kotlin.lombok.config.RequiredArgsConstructor import org.jetbrains.kotlin.lombok.utils.LombokNames import org.jetbrains.kotlin.lombok.utils.getJavaFields import org.jetbrains.kotlin.resolve.source.getPsi -class RequiredArgsConstructorProcessor : AbstractConstructorProcessor(RequiredArgsConstructor) { +class RequiredArgsConstructorProcessor : AbstractConstructorProcessor() { + + override fun getAnnotation(classDescriptor: ClassDescriptor): RequiredArgsConstructor? = + RequiredArgsConstructor.getOrNull(classDescriptor) ?: Data.getOrNull(classDescriptor)?.asRequiredArgsConstructor() override fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List = classDescriptor.getJavaFields().filter(this::isFieldRequired) 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 7ae3802a457..23353090402 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 @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.lombok.processor import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.lombok.config.Accessors +import org.jetbrains.kotlin.lombok.config.Data import org.jetbrains.kotlin.lombok.config.LombokConfig import org.jetbrains.kotlin.lombok.config.Setter import org.jetbrains.kotlin.lombok.utils.* @@ -21,7 +22,7 @@ class SetterProcessor(private val config: LombokConfig) : Processor { if (classDescriptor.kind == ClassKind.ENUM_CLASS) return Parts.Empty val clAccessors = Accessors.getOrNull(classDescriptor) - val clSetter = Setter.getOrNull(classDescriptor) + val clSetter = Setter.getOrNull(classDescriptor) ?: Data.getOrNull(classDescriptor)?.asSetter() val functions = classDescriptor .getJavaFields() diff --git a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/utils/LombokNames.kt b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/utils/LombokNames.kt index 22d29aeea89..0ab602e1c8d 100644 --- a/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/utils/LombokNames.kt +++ b/plugins/lombok/lombok-compiler-plugin/src/org/jetbrains/kotlin/lombok/utils/LombokNames.kt @@ -13,7 +13,8 @@ object LombokNames { val GETTER = FqName("lombok.Getter") val SETTER = FqName("lombok.Setter") val WITH = FqName("lombok.With") - val VALUE = FqName("lombok.lombok.Value") + val DATA = FqName("lombok.Data") + val VALUE = FqName("lombok.Value") val NO_ARGS_CONSTRUCTOR = FqName("lombok.NoArgsConstructor") val ALL_ARGS_CONSTRUCTOR = FqName("lombok.AllArgsConstructor") val REQUIRED_ARGS_CONSTRUCTOR = FqName("lombok.RequiredArgsConstructor") 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 bfa4f4262d7..0c4e4e67e1d 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 @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.java.JavaVisibilities +import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.constants.BooleanValue import org.jetbrains.kotlin.resolve.constants.EnumValue @@ -24,7 +25,7 @@ fun getVisibility(annotation: AnnotationDescriptor, field: String = "value"): De "PACKAGE" -> JavaVisibilities.PackageVisibility else -> Visibilities.Public } - return DescriptorVisibilities.toDescriptorVisibility(visibility) + return JavaDescriptorVisibilities.toDescriptorVisibility(visibility) } fun AnnotationDescriptor.getStringArgument(argumentName: String): String? { diff --git a/plugins/lombok/lombok-compiler-plugin/testData/compile/data.kt b/plugins/lombok/lombok-compiler-plugin/testData/compile/data.kt new file mode 100644 index 00000000000..3c4bcb4ddb9 --- /dev/null +++ b/plugins/lombok/lombok-compiler-plugin/testData/compile/data.kt @@ -0,0 +1,42 @@ +//FILE: DataExample.java + +import lombok.*; + +@Data public class DataExample { + private final String name; + @Setter(AccessLevel.PACKAGE) private int age; + private double score; + private String[] tags; + + @ToString(includeFieldNames=true) + @Data(staticConstructor="of") + public static class Exercise { + private final String name; + private final T value; + } + + public static void usage() { + val obj = new DataExample("name"); + obj.getName(); + obj.getTags(); + obj.setScore(1.5); + + Exercise ex = Exercise.of("name", 12); + } +} + +//FILE: test.kt + +class Test { + fun run() { + val obj = DataExample("name") + obj.getName() + val name = obj.name + obj.getTags() + val tags = obj.tags + obj.setScore(1.5) + obj.score = 2.5 + + val ex: DataExample.Exercise = DataExample.Exercise.of("name", 12) + } +} 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 7b1efebccb7..3a8b3bec209 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 @@ -51,6 +51,11 @@ public class LombokCompileTestGenerated extends AbstractLombokCompileTest { runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/clashAccessors.kt"); } + @TestMetadata("data.kt") + public void testData() throws Exception { + runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/data.kt"); + } + @TestMetadata("gettersClassLevel.kt") public void testGettersClassLevel() throws Exception { runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/gettersClassLevel.kt");