[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: Other todos:
- [ ] Generic classes - [x] Generic classes
- [ ] Actually run compiled code - [ ] Actually run compiled code
- [ ] Don't generate members that already exist (if having a duplicate is a problem) - [ ] 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) - [ ] 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.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl 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.AnnotationCompanion
import org.jetbrains.kotlin.lombok.config.ConstructorAnnotation import org.jetbrains.kotlin.lombok.config.ConstructorAnnotation
import org.jetbrains.kotlin.lombok.utils.ValueParameter 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.createFunction
import org.jetbrains.kotlin.lombok.utils.getJavaFields
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
abstract class AbstractConstructorProcessor<A : ConstructorAnnotation>( abstract class AbstractConstructorProcessor<A : ConstructorAnnotation>(
@@ -28,7 +26,7 @@ abstract class AbstractConstructorProcessor<A : ConstructorAnnotation>(
val result = annotationCompanion.getOrNull(classDescriptor)?.let { annotation -> val result = annotationCompanion.getOrNull(classDescriptor)?.let { annotation ->
if (annotation.staticName == null) { if (annotation.staticName == null) {
val constructor = classDescriptor.createConstructor( val constructor = classDescriptor.createJavaConstructor(
valueParameters = valueParameters, valueParameters = valueParameters,
visibility = annotation.visibility visibility = annotation.visibility
) )
@@ -38,6 +36,7 @@ abstract class AbstractConstructorProcessor<A : ConstructorAnnotation>(
Name.identifier(annotation.staticName!!), Name.identifier(annotation.staticName!!),
valueParameters, valueParameters,
classDescriptor.defaultType, classDescriptor.defaultType,
typeParameters = classDescriptor.declaredTypeParameters,
visibility = annotation.visibility, visibility = annotation.visibility,
receiver = null 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.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation 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.load.java.lazy.descriptors.isJavaField
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -21,6 +22,7 @@ fun ClassDescriptor.createFunction(
name: Name, name: Name,
valueParameters: List<ValueParameter>, valueParameters: List<ValueParameter>,
returnType: KotlinType?, returnType: KotlinType?,
typeParameters: List<TypeParameterDescriptor> = emptyList(),
modality: Modality? = Modality.OPEN, modality: Modality? = Modality.OPEN,
visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC, visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC,
receiver: ReceiverParameterDescriptor? = this.thisAsReceiverParameter receiver: ReceiverParameterDescriptor? = this.thisAsReceiverParameter
@@ -38,7 +40,7 @@ fun ClassDescriptor.createFunction(
methodDescriptor.initialize( methodDescriptor.initialize(
null, null,
receiver, receiver,
mutableListOf(), typeParameters,
paramDescriptors, paramDescriptors,
returnType, returnType,
modality, modality,
@@ -47,11 +49,11 @@ fun ClassDescriptor.createFunction(
return methodDescriptor return methodDescriptor
} }
fun ClassDescriptor.createConstructor( fun ClassDescriptor.createJavaConstructor(
valueParameters: List<ValueParameter>, valueParameters: List<ValueParameter>,
visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC
): ClassConstructorDescriptor { ): ClassConstructorDescriptor {
val constructor = ClassConstructorDescriptorImpl.create( val constructor = JavaClassConstructorDescriptor.create(
this, this,
Annotations.EMPTY, Annotations.EMPTY,
false, false,
@@ -61,7 +63,7 @@ fun ClassDescriptor.createConstructor(
constructor.initialize( constructor.initialize(
null, null,
constructor.calculateDispatchReceiverParameter(), constructor.calculateDispatchReceiverParameter(),
emptyList(), this.declaredTypeParameters,
paramDescriptors, paramDescriptors,
this.defaultType, this.defaultType,
Modality.OPEN, 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 getter = obj.getAge()
val property = obj.age 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.primitiveBoolean
obj.isPrimitiveBoolean() obj.isPrimitiveBoolean()
@@ -76,6 +76,21 @@ public class LombokCompileTestGenerated extends AbstractLombokCompileTest {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/requiredArgsConstructorStatic.kt"); 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") @TestMetadata("getters.kt")
public void testGetters() throws Exception { public void testGetters() throws Exception {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/getters.kt"); runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/getters.kt");