[lombok] Some cleaning and docs

This commit is contained in:
Andrey Zinovyev
2021-03-31 16:42:43 +03:00
committed by TeamCityServer
parent 9ebce7849c
commit 1fb4590978
9 changed files with 76 additions and 68 deletions
@@ -17,21 +17,27 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.jvm.SyntheticJavaPartsProvider
import java.util.*
class LombokSyntheticJavaPartsProvider(private val config: LombokConfig) : SyntheticJavaPartsProvider {
/**
* Provides synthetic parts to java classes (from current compilation unit), which will be generated by lombok AnnotationProcessor
* So kotlin can reference lombok members.
*/
class LombokSyntheticJavaPartsProvider(config: LombokConfig) : SyntheticJavaPartsProvider {
private val processors = initProcessors()
private val processors = listOf(
GetterProcessor(config),
SetterProcessor(config),
WithProcessor(),
NoArgsConstructorProcessor(),
AllArgsConstructorProcessor(),
RequiredArgsConstructorProcessor()
)
private fun initProcessors(): List<Processor> =
listOf(
GetterProcessor(config),
SetterProcessor(config),
WithProcessor(),
NoArgsConstructorProcessor(),
AllArgsConstructorProcessor(),
RequiredArgsConstructorProcessor()
)
private val partsCache: MutableMap<ClassDescriptor, Parts> = WeakHashMap()
/**
* kotlin resolve references in two calls - first it gets names, then actual member descriptor
* but for us it is much easier to run full generation for class once
* hence we cache results and reuse it
*/
private val partsCache: MutableMap<ClassDescriptor, SyntheticParts> = WeakHashMap()
override fun getMethodNames(thisDescriptor: ClassDescriptor): List<Name> =
getSyntheticParts(thisDescriptor).methods.map { it.name }
@@ -61,16 +67,19 @@ class LombokSyntheticJavaPartsProvider(private val config: LombokConfig) : Synth
private fun extractClass(descriptor: ClassDescriptor): JavaClassImpl? =
(descriptor as? LazyJavaClassDescriptor)?.jClass as? JavaClassImpl
private fun getSyntheticParts(descriptor: ClassDescriptor): Parts =
private fun getSyntheticParts(descriptor: ClassDescriptor): SyntheticParts =
extractClass(descriptor)?.let { jClass ->
partsCache.getOrPut(descriptor) {
computeSyntheticParts(descriptor, jClass)
}
} ?: Parts.Empty
} ?: SyntheticParts.Empty
private fun computeSyntheticParts(descriptor: ClassDescriptor, jClass: JavaClassImpl): Parts =
processors.map { it.contribute(descriptor, jClass) }.reduce { a, b -> a + b }
private fun computeSyntheticParts(descriptor: ClassDescriptor, jClass: JavaClassImpl): SyntheticParts =
processors.map { it.contribute(descriptor) }.reduce { a, b -> a + b }
/**
* Deduplicates generated functions using name and argument counts, as lombok does
*/
private fun <T : FunctionDescriptor> addNonExistent(result: MutableCollection<T>, toAdd: List<T>) {
if (toAdd.isEmpty()) return
@@ -7,8 +7,6 @@ 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.AnnotationCompanion
import org.jetbrains.kotlin.lombok.config.ConstructorAnnotation
import org.jetbrains.kotlin.lombok.utils.ValueParameter
import org.jetbrains.kotlin.lombok.utils.createJavaConstructor
@@ -17,7 +15,7 @@ import org.jetbrains.kotlin.name.Name
abstract class AbstractConstructorProcessor<A : ConstructorAnnotation> : Processor {
override fun contribute(classDescriptor: ClassDescriptor, jClass: JavaClassImpl): Parts {
override fun contribute(classDescriptor: ClassDescriptor): SyntheticParts {
val valueParameters = getPropertiesForParameters(classDescriptor).map { property ->
ValueParameter(property.name, property.type)
}
@@ -28,7 +26,7 @@ abstract class AbstractConstructorProcessor<A : ConstructorAnnotation> : Process
valueParameters = valueParameters,
visibility = annotation.visibility
)
Parts(constructors = listOfNotNull(constructor))
SyntheticParts(constructors = listOfNotNull(constructor))
} else {
val function = classDescriptor.createFunction(
Name.identifier(annotation.staticName!!),
@@ -38,10 +36,10 @@ abstract class AbstractConstructorProcessor<A : ConstructorAnnotation> : Process
visibility = annotation.visibility,
receiver = null
)
Parts(staticFunctions = listOf(function))
SyntheticParts(staticFunctions = listOf(function))
}
}
return result ?: Parts.Empty
return result ?: SyntheticParts.Empty
}
protected abstract fun getAnnotation(classDescriptor: ClassDescriptor): A?
@@ -8,14 +8,13 @@ package org.jetbrains.kotlin.lombok.processor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
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.*
import org.jetbrains.kotlin.lombok.utils.*
import org.jetbrains.kotlin.name.Name
class GetterProcessor(private val config: LombokConfig) : Processor {
override fun contribute(classDescriptor: ClassDescriptor, jClass: JavaClassImpl): Parts {
override fun contribute(classDescriptor: ClassDescriptor): SyntheticParts {
val globalAccessors = Accessors.get(classDescriptor, config)
val clGetter =
Getter.getOrNull(classDescriptor)
@@ -27,7 +26,7 @@ class GetterProcessor(private val config: LombokConfig) : Processor {
.collectWithNotNull { Getter.getOrNull(it) ?: clGetter }
.mapNotNull { (field, annotation) -> createGetter(classDescriptor, field, annotation, globalAccessors) }
return Parts(functions)
return SyntheticParts(functions)
}
private fun createGetter(
@@ -39,7 +38,7 @@ class GetterProcessor(private val config: LombokConfig) : Processor {
if (getter.visibility == AccessLevel.NONE) return null
val accessors = Accessors.getIfAnnotated(field, config) ?: globalAccessors
return field.toPropertyName(accessors)?.let { propertyName ->
return field.toAccessorBaseName(accessors)?.let { propertyName ->
val functionName =
if (accessors.fluent) {
propertyName
@@ -6,9 +6,11 @@
package org.jetbrains.kotlin.lombok.processor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
/**
* Generates synthetic parts for [ClassDescriptor]
*/
interface Processor {
fun contribute(classDescriptor: ClassDescriptor, jClass: JavaClassImpl): Parts
fun contribute(classDescriptor: ClassDescriptor): SyntheticParts
}
@@ -6,7 +6,6 @@
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.*
import org.jetbrains.kotlin.lombok.utils.*
import org.jetbrains.kotlin.name.Name
@@ -14,9 +13,9 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
class SetterProcessor(private val config: LombokConfig) : Processor {
override fun contribute(classDescriptor: ClassDescriptor, jClass: JavaClassImpl): Parts {
override fun contribute(classDescriptor: ClassDescriptor): SyntheticParts {
//lombok doesn't generate setters for enums
if (classDescriptor.kind == ClassKind.ENUM_CLASS) return Parts.Empty
if (classDescriptor.kind == ClassKind.ENUM_CLASS) return SyntheticParts.Empty
val globalAccessors = Accessors.get(classDescriptor, config)
val clSetter = Setter.getOrNull(classDescriptor) ?: Data.getOrNull(classDescriptor)?.asSetter()
@@ -25,7 +24,7 @@ class SetterProcessor(private val config: LombokConfig) : Processor {
.getJavaFields()
.collectWithNotNull { field -> Setter.getOrNull(field) ?: clSetter.takeIf { field.isVar } }
.mapNotNull { (field, setter) -> createSetter(classDescriptor, field, setter, globalAccessors) }
return Parts(functions)
return SyntheticParts(functions)
}
private fun createSetter(
@@ -37,7 +36,7 @@ class SetterProcessor(private val config: LombokConfig) : Processor {
if (getter.visibility == AccessLevel.NONE) return null
val accessors = Accessors.getIfAnnotated(field, config) ?: globalAccessors
return field.toPropertyName(accessors)?.let { propertyName ->
return field.toAccessorBaseName(accessors)?.let { propertyName ->
val functionName =
if (accessors.fluent) propertyName
else AccessorNames.SET + propertyName.capitalize()
@@ -8,19 +8,19 @@ package org.jetbrains.kotlin.lombok.processor
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
data class Parts(
data class SyntheticParts(
val methods: List<SimpleFunctionDescriptor> = emptyList(),
val staticFunctions: List<SimpleFunctionDescriptor> = emptyList(),
val constructors: List<ClassConstructorDescriptor> = emptyList()
) {
operator fun plus(other: Parts): Parts = Parts(
operator fun plus(other: SyntheticParts): SyntheticParts = SyntheticParts(
methods + other.methods,
staticFunctions + other.staticFunctions,
constructors + other.constructors
)
companion object {
val Empty = Parts()
val Empty = SyntheticParts()
}
}
@@ -8,14 +8,13 @@ package org.jetbrains.kotlin.lombok.processor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
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.AccessLevel
import org.jetbrains.kotlin.lombok.config.With
import org.jetbrains.kotlin.lombok.utils.*
import org.jetbrains.kotlin.name.Name
class WithProcessor : Processor {
override fun contribute(classDescriptor: ClassDescriptor, jClass: JavaClassImpl): Parts {
override fun contribute(classDescriptor: ClassDescriptor): SyntheticParts {
val clWith = With.getOrNull(classDescriptor)
@@ -24,7 +23,7 @@ class WithProcessor : Processor {
.collectWithNotNull { With.getOrNull(it) ?: clWith }
.mapNotNull { (field, annotation) -> createWith(classDescriptor, field, annotation) }
return Parts(functions)
return SyntheticParts(functions)
}
private fun createWith(
@@ -14,7 +14,11 @@ object AccessorNames {
const val SET = "set"
}
fun PropertyDescriptor.toPropertyName(config: Accessors): String? {
/**
* Make property name from variable name
* Returns null in case getter/setter shouldn't be generated at all
*/
fun PropertyDescriptor.toAccessorBaseName(config: Accessors): String? {
val isPrimitiveBoolean = type.isPrimitiveBoolean()
return if (config.prefix.isEmpty()) {
val prefixes = if (isPrimitiveBoolean) listOf(AccessorNames.IS) else emptyList()
@@ -15,9 +15,7 @@ import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/**
* This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY
*/
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("plugins/lombok/lombok-compiler-plugin/testData/compile")
@TestDataPath("$PROJECT_ROOT")
@@ -27,10 +25,6 @@ public class LombokCompileTestGenerated extends AbstractLombokCompileTest {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInCompile() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/lombok/lombok-compiler-plugin/testData/compile"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@TestMetadata("accessorsStripPrefix.kt")
public void testAccessorsStripPrefix() throws Exception {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/accessorsStripPrefix.kt");
@@ -51,6 +45,10 @@ public class LombokCompileTestGenerated extends AbstractLombokCompileTest {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/allArgsConstructorStatic.kt");
}
public void testAllFilesPresentInCompile() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/lombok/lombok-compiler-plugin/testData/compile"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@TestMetadata("clashAccessors.kt")
public void testClashAccessors() throws Exception {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/clashAccessors.kt");
@@ -76,6 +74,26 @@ public class LombokCompileTestGenerated extends AbstractLombokCompileTest {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/data.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");
}
@TestMetadata("gettersClassLevel.kt")
public void testGettersClassLevel() throws Exception {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/gettersClassLevel.kt");
@@ -106,26 +124,6 @@ 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");
}
@TestMetadata("setters.kt")
public void testSetters() throws Exception {
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/setters.kt");