[lombok] Generic classes support

This commit is contained in:
Andrey Zinovyev
2021-03-26 17:48:38 +03:00
committed by TeamCityServer
parent afcb2ca904
commit 411441c332
8 changed files with 122 additions and 10 deletions
@@ -36,7 +36,7 @@ Features support:
Other todos:
- [ ] Generic classes
- [x] Generic classes
- [ ] Actually run compiled code
- [ ] Don't generate members that already exist (if having a duplicate is a problem)
- [ ] Gradle integration (as subplugin or just a way to enable lombok support)
@@ -8,13 +8,11 @@ package org.jetbrains.kotlin.lombok.processor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
import org.jetbrains.kotlin.lombok.config.AllArgsConstructor
import org.jetbrains.kotlin.lombok.config.AnnotationCompanion
import org.jetbrains.kotlin.lombok.config.ConstructorAnnotation
import org.jetbrains.kotlin.lombok.utils.ValueParameter
import org.jetbrains.kotlin.lombok.utils.createConstructor
import org.jetbrains.kotlin.lombok.utils.createJavaConstructor
import org.jetbrains.kotlin.lombok.utils.createFunction
import org.jetbrains.kotlin.lombok.utils.getJavaFields
import org.jetbrains.kotlin.name.Name
abstract class AbstractConstructorProcessor<A : ConstructorAnnotation>(
@@ -28,7 +26,7 @@ abstract class AbstractConstructorProcessor<A : ConstructorAnnotation>(
val result = annotationCompanion.getOrNull(classDescriptor)?.let { annotation ->
if (annotation.staticName == null) {
val constructor = classDescriptor.createConstructor(
val constructor = classDescriptor.createJavaConstructor(
valueParameters = valueParameters,
visibility = annotation.visibility
)
@@ -38,6 +36,7 @@ abstract class AbstractConstructorProcessor<A : ConstructorAnnotation>(
Name.identifier(annotation.staticName!!),
valueParameters,
classDescriptor.defaultType,
typeParameters = classDescriptor.declaredTypeParameters,
visibility = annotation.visibility,
receiver = null
)
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor
import org.jetbrains.kotlin.load.java.lazy.descriptors.isJavaField
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
@@ -21,6 +22,7 @@ fun ClassDescriptor.createFunction(
name: Name,
valueParameters: List<ValueParameter>,
returnType: KotlinType?,
typeParameters: List<TypeParameterDescriptor> = emptyList(),
modality: Modality? = Modality.OPEN,
visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC,
receiver: ReceiverParameterDescriptor? = this.thisAsReceiverParameter
@@ -38,7 +40,7 @@ fun ClassDescriptor.createFunction(
methodDescriptor.initialize(
null,
receiver,
mutableListOf(),
typeParameters,
paramDescriptors,
returnType,
modality,
@@ -47,11 +49,11 @@ fun ClassDescriptor.createFunction(
return methodDescriptor
}
fun ClassDescriptor.createConstructor(
fun ClassDescriptor.createJavaConstructor(
valueParameters: List<ValueParameter>,
visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC
): ClassConstructorDescriptor {
val constructor = ClassConstructorDescriptorImpl.create(
val constructor = JavaClassConstructorDescriptor.create(
this,
Annotations.EMPTY,
false,
@@ -61,7 +63,7 @@ fun ClassDescriptor.createConstructor(
constructor.initialize(
null,
constructor.calculateDispatchReceiverParameter(),
emptyList(),
this.declaredTypeParameters,
paramDescriptors,
this.defaultType,
Modality.OPEN,
@@ -0,0 +1,38 @@
//FILE: GenericsTest.java
import lombok.*;
import java.util.*;
public class GenericsTest<A, B> {
@Getter private int age = 10;
@Getter @Setter private A fieldA;
@Getter private B fieldB;
@Setter private Map<A, B> fieldC;
static void test() {
val obj = new GenericsTest<String, Boolean>();
int age = obj.getAge();
String a = obj.getFieldA();
obj.setFieldA("fooo");
Boolean b = obj.getFieldB();
obj.setFieldC(new HashMap<String, Boolean>());
}
}
//FILE: test.kt
object Test {
fun usage() {
val obj = GenericsTest<String, Boolean>()
val age: Int = obj.getAge();
val a: String = obj.getFieldA();
obj.setFieldA("fooo");
val b: Boolean = obj.getFieldB();
obj.setFieldC(java.util.HashMap<String, Boolean>());
}
}
@@ -0,0 +1,29 @@
//FILE: ConstructorExample.java
import lombok.*;
@AllArgsConstructor
@RequiredArgsConstructor
public class ConstructorExample<A, B> {
@Getter @Setter private int age = 10;
@Getter private final A name;
private B otherField;
static void javaUsage() {
val generated = new ConstructorExample<Long, Boolean>(12, 42L, true);
val generatedReq = new ConstructorExample<String, Boolean>("234");
}
}
//FILE: test.kt
object Test {
fun usage() {
val generated = ConstructorExample<Long, Boolean>(12, 42L, true)
val generatedReq = ConstructorExample<String, Boolean>("234");
}
}
@@ -0,0 +1,29 @@
//FILE: ConstructorExample.java
import lombok.*;
@AllArgsConstructor(staticName = "of")
@RequiredArgsConstructor(staticName = "of")
public class ConstructorExample<A, B> {
@Getter @Setter private int age = 10;
@Getter private final A name;
private B otherField;
static void javaUsage() {
ConstructorExample<Long, Boolean> generated = ConstructorExample.of(12, 42L, true);
ConstructorExample<String, Boolean> generatedReq = ConstructorExample.of("234");
}
}
//FILE: test.kt
object Test {
fun usage() {
val generated: ConstructorExample<Long, Boolean> = ConstructorExample.of(12, 42L, true)
val generatedReq: ConstructorExample<String, Boolean> = ConstructorExample.of("234");
}
}
@@ -28,7 +28,7 @@ object Test {
val getter = obj.getAge()
val property = obj.age
//todo kotlin doesn't see isBoolean methods as properties
//todo kotlin doesn't see isBoolean methods as property
// obj.primitiveBoolean
obj.isPrimitiveBoolean()
@@ -76,6 +76,21 @@ public class LombokCompileTestGenerated extends AbstractLombokCompileTest {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/requiredArgsConstructorStatic.kt");
}
@TestMetadata("genericsAccessors.kt")
public void testGenericsAccessors() throws Exception {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/genericsAccessors.kt");
}
@TestMetadata("genericsConstructors.kt")
public void testGenericsConstructors() throws Exception {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/genericsConstructors.kt");
}
@TestMetadata("genericsConstructorsStatic.kt")
public void testGenericsConstructorsStatic() throws Exception {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/genericsConstructorsStatic.kt");
}
@TestMetadata("getters.kt")
public void testGetters() throws Exception {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/getters.kt");