[lombok] Generate no-arg static factory method

This commit is contained in:
Andrey Zinovyev
2021-03-26 15:14:55 +03:00
committed by TeamCityServer
parent 37926f333e
commit 59f936fdef
11 changed files with 103 additions and 22 deletions
@@ -78,7 +78,7 @@ class LazyJavaClassMemberScope(
addAll(declaredMemberIndex().getMethodNames())
addAll(declaredMemberIndex().getRecordComponentNames())
addAll(computeClassNames(kindFilter, nameFilter))
addAll(c.components.syntheticPartsProvider.getSyntheticFunctionNames(ownerDescriptor))
addAll(c.components.syntheticPartsProvider.getMethodNames(ownerDescriptor))
}
internal val constructors = c.storageManager.createLazyValue {
@@ -99,7 +99,7 @@ class LazyJavaClassMemberScope(
}
}
c.components.syntheticPartsProvider.generateSyntheticConstructors(ownerDescriptor, result)
c.components.syntheticPartsProvider.generateConstructors(ownerDescriptor, result)
c.components.signatureEnhancement.enhanceSignatures(
c,
@@ -500,7 +500,7 @@ class LazyJavaClassMemberScope(
result.add(resolveRecordComponentToFunctionDescriptor(declaredMemberIndex().findRecordComponentByName(name)!!))
}
c.components.syntheticPartsProvider.generateSyntheticMethods(ownerDescriptor, name, result)
c.components.syntheticPartsProvider.generateMethods(ownerDescriptor, name, result)
}
private fun resolveRecordComponentToFunctionDescriptor(recordComponent: JavaRecordComponent): JavaMethodDescriptor {
@@ -48,6 +48,7 @@ class LazyJavaStaticClassScope(
if (jClass.isEnum) {
addAll(listOf(StandardNames.ENUM_VALUE_OF, StandardNames.ENUM_VALUES))
}
addAll(c.components.syntheticPartsProvider.getStaticFunctionNames(ownerDescriptor))
}
override fun computePropertyNames(kindFilter: DescriptorKindFilter, nameFilter: ((Name) -> Boolean)?) =
@@ -81,6 +82,10 @@ class LazyJavaStaticClassScope(
}
}
override fun computeImplicitlyDeclaredFunctions(result: MutableCollection<SimpleFunctionDescriptor>, name: Name) {
c.components.syntheticPartsProvider.generateStaticFunctions(ownerDescriptor, name, result)
}
override fun computeNonDeclaredProperties(name: Name, result: MutableCollection<PropertyDescriptor>) {
val propertiesFromSupertypes = flatMapJavaStaticSupertypesScopes(ownerDescriptor, mutableSetOf()) {
it.getContributedVariables(name, NoLookupLocation.WHEN_GET_SUPER_MEMBERS)
@@ -16,31 +16,46 @@ interface SyntheticJavaPartsProvider {
val EMPTY = CompositeSyntheticJavaPartsProvider(emptyList())
}
fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List<Name>
fun getMethodNames(thisDescriptor: ClassDescriptor): List<Name>
fun generateSyntheticMethods(
fun generateMethods(
thisDescriptor: ClassDescriptor,
name: Name,
result: MutableCollection<SimpleFunctionDescriptor>
)
fun generateSyntheticConstructors(thisDescriptor: ClassDescriptor, result: MutableList<ClassConstructorDescriptor>)
fun getStaticFunctionNames(thisDescriptor: ClassDescriptor): List<Name>
fun generateStaticFunctions(
thisDescriptor: ClassDescriptor,
name: Name,
result: MutableCollection<SimpleFunctionDescriptor>
)
fun generateConstructors(thisDescriptor: ClassDescriptor, result: MutableList<ClassConstructorDescriptor>)
}
class CompositeSyntheticJavaPartsProvider(private val inner: List<SyntheticJavaPartsProvider>) : SyntheticJavaPartsProvider {
override fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List<Name> =
inner.flatMap { it.getSyntheticFunctionNames(thisDescriptor) }
override fun getMethodNames(thisDescriptor: ClassDescriptor): List<Name> =
inner.flatMap { it.getMethodNames(thisDescriptor) }
override fun generateSyntheticMethods(
override fun generateMethods(
thisDescriptor: ClassDescriptor,
name: Name,
result: MutableCollection<SimpleFunctionDescriptor>
) {
inner.forEach { it.generateSyntheticMethods(thisDescriptor, name, result) }
inner.forEach { it.generateMethods(thisDescriptor, name, result) }
}
override fun generateSyntheticConstructors(thisDescriptor: ClassDescriptor, result: MutableList<ClassConstructorDescriptor>) {
inner.forEach { it.generateSyntheticConstructors(thisDescriptor, result) }
override fun getStaticFunctionNames(thisDescriptor: ClassDescriptor): List<Name> =
inner.flatMap { it.getStaticFunctionNames(thisDescriptor) }
override fun generateStaticFunctions(thisDescriptor: ClassDescriptor, name: Name, result: MutableCollection<SimpleFunctionDescriptor>) {
inner.forEach { it.generateStaticFunctions(thisDescriptor, name, result) }
}
override fun generateConstructors(thisDescriptor: ClassDescriptor, result: MutableList<ClassConstructorDescriptor>) {
inner.forEach { it.generateConstructors(thisDescriptor, result) }
}
}
@@ -23,9 +23,10 @@ Features support:
- [x] Basic support
- [ ] Copy annotations
[ ] [@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor](https://projectlombok.org/features/constructor)
- [ ] Generate constructors
- [ ] Generate static factory method
[~] [@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor](https://projectlombok.org/features/constructor)
- [x] @NoArgsConstructor
- [ ] @AllArgsConstructor
- [ ] @RequiredArgsConstructor
[ ] [@Data](https://projectlombok.org/features/Data)
@@ -30,10 +30,10 @@ class LombokSyntheticJavaPartsProvider(private val config: LombokConfig) : Synth
private val partsCache: MutableMap<ClassDescriptor, Parts> = WeakHashMap()
override fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List<Name> =
override fun getMethodNames(thisDescriptor: ClassDescriptor): List<Name> =
getSyntheticParts(thisDescriptor).methods.map { it.name }
override fun generateSyntheticMethods(
override fun generateMethods(
thisDescriptor: ClassDescriptor,
name: Name,
result: MutableCollection<SimpleFunctionDescriptor>
@@ -42,7 +42,15 @@ class LombokSyntheticJavaPartsProvider(private val config: LombokConfig) : Synth
result.addAll(methods)
}
override fun generateSyntheticConstructors(thisDescriptor: ClassDescriptor, result: MutableList<ClassConstructorDescriptor>) {
override fun getStaticFunctionNames(thisDescriptor: ClassDescriptor): List<Name> =
getSyntheticParts(thisDescriptor).staticFunctions.map { it.name }
override fun generateStaticFunctions(thisDescriptor: ClassDescriptor, name: Name, result: MutableCollection<SimpleFunctionDescriptor>) {
val functions = getSyntheticParts(thisDescriptor).staticFunctions.filter { it.name == name }
result.addAll(functions)
}
override fun generateConstructors(thisDescriptor: ClassDescriptor, result: MutableList<ClassConstructorDescriptor>) {
val constructors = getSyntheticParts(thisDescriptor).constructors
result.addAll(constructors)
}
@@ -9,6 +9,8 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
import org.jetbrains.kotlin.lombok.config.NoArgsConstructor
import org.jetbrains.kotlin.lombok.utils.createConstructor
import org.jetbrains.kotlin.lombok.utils.createFunction
import org.jetbrains.kotlin.name.Name
class NoArgsConstructorProcessor : Processor {
@@ -21,7 +23,14 @@ class NoArgsConstructorProcessor : Processor {
)
Parts(constructors = listOfNotNull(constructor))
} else {
null
val function = classDescriptor.createFunction(
Name.identifier(annotation.staticName),
emptyList(),
classDescriptor.defaultType,
visibility = annotation.visibility,
receiver = null
)
Parts(staticFunctions = listOf(function))
}
}
return result ?: Parts.Empty
@@ -10,10 +10,15 @@ import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
data class Parts(
val methods: List<SimpleFunctionDescriptor> = emptyList(),
val staticFunctions: List<SimpleFunctionDescriptor> = emptyList(),
val constructors: List<ClassConstructorDescriptor> = emptyList()
) {
operator fun plus(other: Parts): Parts = Parts(methods + other.methods, constructors + other.constructors)
operator fun plus(other: Parts): Parts = Parts(
methods + other.methods,
staticFunctions + other.staticFunctions,
constructors + other.constructors
)
companion object {
val Empty = Parts()
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.descriptors.java.JavaVisibilities
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.BooleanValue
import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.resolve.constants.StringValue
internal fun getVisibility(annotation: AnnotationDescriptor, field: String = "value"): DescriptorVisibility {
val value = annotation.getStringArgument(field) ?: "PUBLIC"
@@ -32,6 +33,7 @@ internal fun AnnotationDescriptor.getStringArgument(argumentName: String): Strin
return when (argument) {
is EnumValue -> argument.enumEntryName.identifier
is StringValue -> argument.value
else -> throw RuntimeException("Argument $argument is not supported")
}
}
@@ -21,7 +21,8 @@ internal fun ClassDescriptor.createFunction(
valueParameters: List<ValueParameter>,
returnType: KotlinType?,
modality: Modality? = Modality.OPEN,
visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC
visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC,
receiver: ReceiverParameterDescriptor? = this.thisAsReceiverParameter
): SimpleFunctionDescriptor {
val methodDescriptor = SimpleFunctionDescriptorImpl.create(
this,
@@ -35,7 +36,7 @@ internal fun ClassDescriptor.createFunction(
methodDescriptor.initialize(
null,
this.thisAsReceiverParameter,
receiver,
mutableListOf(),
paramDescriptors,
returnType,
@@ -0,0 +1,30 @@
//FILE: ConstructorExample.java
import lombok.*;
@NoArgsConstructor(staticName = "make")
public class ConstructorExample {
public ConstructorExample(String arg) {
}
@Getter @Setter private int age = 10;
@Getter(AccessLevel.PROTECTED) private String name;
static void javaUsage() {
ConstructorExample existing = new ConstructorExample("existing");
ConstructorExample generated = ConstructorExample.make();
}
}
//FILE: test.kt
object Test {
fun usage() {
val existing: ConstructorExample = ConstructorExample("existing")
val generated: ConstructorExample = ConstructorExample.make()
}
}
@@ -51,6 +51,11 @@ public class LombokCompileTestGenerated extends AbstractLombokCompileTest {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/noArgsConstructor.kt");
}
@TestMetadata("noArgsConstructorStatic.kt")
public void testNoArgsConstructorStatic() throws Exception {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/noArgsConstructorStatic.kt");
}
@TestMetadata("getters.kt")
public void testGetters() throws Exception {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/getters.kt");