[lombok] @Data support

This commit is contained in:
Andrey Zinovyev
2021-03-30 13:13:36 +03:00
committed by TeamCityServer
parent 99f9b79c87
commit 97fc187e77
12 changed files with 101 additions and 18 deletions
@@ -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)
@@ -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<Getter>() {
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<Setter>() {
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<RequiredArgsConstructor>() {
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<Data>() {
override val name: FqName = LombokNames.DATA
override fun extract(annotation: AnnotationDescriptor): Data =
Data(
staticConstructor = annotation.getNonBlankStringArgument("staticConstructor")
)
}
}
@@ -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<A : ConstructorAnnotation>(
private val annotationCompanion: AnnotationCompanion<A>
) : Processor {
abstract class AbstractConstructorProcessor<A : ConstructorAnnotation> : 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<A : ConstructorAnnotation>(
return result ?: Parts.Empty
}
protected abstract fun getAnnotation(classDescriptor: ClassDescriptor): A?
protected abstract fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List<PropertyDescriptor>
@@ -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>(AllArgsConstructor) {
class AllArgsConstructorProcessor : AbstractConstructorProcessor<AllArgsConstructor>() {
override fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List<PropertyDescriptor> = classDescriptor.getJavaFields()
override fun getAnnotation(classDescriptor: ClassDescriptor): AllArgsConstructor? =
AllArgsConstructor.getOrNull(classDescriptor)
override fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List<PropertyDescriptor> =
classDescriptor.getJavaFields()
}
@@ -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()
@@ -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>(NoArgsConstructor) {
class NoArgsConstructorProcessor : AbstractConstructorProcessor<NoArgsConstructor>() {
override fun getAnnotation(classDescriptor: ClassDescriptor): NoArgsConstructor? = NoArgsConstructor.getOrNull(classDescriptor)
override fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List<PropertyDescriptor> = emptyList()
}
@@ -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>(RequiredArgsConstructor) {
class RequiredArgsConstructorProcessor : AbstractConstructorProcessor<RequiredArgsConstructor>() {
override fun getAnnotation(classDescriptor: ClassDescriptor): RequiredArgsConstructor? =
RequiredArgsConstructor.getOrNull(classDescriptor) ?: Data.getOrNull(classDescriptor)?.asRequiredArgsConstructor()
override fun getPropertiesForParameters(classDescriptor: ClassDescriptor): List<PropertyDescriptor> =
classDescriptor.getJavaFields().filter(this::isFieldRequired)
@@ -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()
@@ -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")
@@ -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? {
@@ -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<T> {
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<Integer> 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<Int> = DataExample.Exercise.of("name", 12)
}
}
@@ -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");