[lombok] Refactoring, cleaning, better tests

Add assertions to tests
Add lombok license
Provide String.[de]capitalize() implementation
Get rid of weak map because it seems it is useless here
This commit is contained in:
Andrey Zinovyev
2021-04-01 12:51:58 +03:00
committed by TeamCityServer
parent c4147bc2fd
commit 01dd3d6ed4
28 changed files with 278 additions and 234 deletions
@@ -13,5 +13,5 @@ class LombokResolveExtension(pluginConfig: LombokPluginConfig) : SyntheticJavaRe
private val config = pluginConfig.configFile?.let(LombokConfig::parse) ?: LombokConfig.Empty
override fun getProvider(): SyntheticJavaPartsProvider = LombokSyntheticJavaPartsProvider(config)
override fun buildProvider(): SyntheticJavaPartsProvider = LombokSyntheticJavaPartsProvider(config)
}
@@ -37,7 +37,7 @@ class LombokSyntheticJavaPartsProvider(config: LombokConfig) : SyntheticJavaPart
* 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()
private val partsCache: MutableMap<ClassDescriptor, SyntheticParts> = HashMap()
override fun getMethodNames(thisDescriptor: ClassDescriptor): List<Name> =
getSyntheticParts(thisDescriptor).methods.map { it.name }
@@ -75,28 +75,19 @@ class LombokSyntheticJavaPartsProvider(config: LombokConfig) : SyntheticJavaPart
}
} ?: SyntheticParts.Empty
private fun computeSyntheticParts(descriptor: ClassDescriptor): SyntheticParts =
processors.map { it.contribute(descriptor) }.reduce { a, b -> a + b }
private fun computeSyntheticParts(descriptor: ClassDescriptor): SyntheticParts {
val builder = SyntheticPartsBuilder()
processors.forEach { it.contribute(descriptor, builder) }
return builder.build()
}
/**
* 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
val index = mutableMapOf<Name, List<T>>()
fun addToIndex(f: T) {
index.merge(f.name, listOf(f)) { a, b -> a + b}
}
result.forEach(::addToIndex)
toAdd.forEach { f ->
val existing = index.getOrDefault(f.name, emptyList())
if (existing.none { sameSignature (it, f) } ) {
if (result.none { sameSignature(it, f) }) {
result += f
addToIndex(f)
}
}
}
@@ -106,6 +97,7 @@ class LombokSyntheticJavaPartsProvider(config: LombokConfig) : SyntheticJavaPart
/**
* Lombok treat functions as having the same signature by arguments count only
* Corresponding code in lombok - https://github.com/projectlombok/lombok/blob/v1.18.20/src/core/lombok/javac/handlers/JavacHandlerUtil.java#L752
*/
private fun sameSignature(a: FunctionDescriptor, b: FunctionDescriptor): Boolean {
val aVararg = a.valueParameters.any { it.varargElementType != null }
@@ -20,9 +20,7 @@ import org.jetbrains.kotlin.name.FqName
*
*/
abstract class AnnotationCompanion<T> {
abstract val name: FqName
abstract class AnnotationCompanion<T>(val name: FqName) {
abstract fun extract(annotation: AnnotationDescriptor): T
@@ -30,10 +28,7 @@ abstract class AnnotationCompanion<T> {
annotated.annotations.findAnnotation(name)?.let(this::extract)
}
abstract class AnnotationAndConfigCompanion<T> {
abstract val annotationName: FqName
abstract class AnnotationAndConfigCompanion<T>(private val annotationName: FqName) {
abstract fun extract(annotation: AnnotationDescriptor?, config: LombokConfig): T
@@ -53,155 +48,148 @@ abstract class AnnotationAndConfigCompanion<T> {
}
data class Accessors(
val fluent: Boolean = false,
val chain: Boolean = false,
val noIsPrefix: Boolean = false,
val prefix: List<String> = emptyList()
) {
companion object : AnnotationAndConfigCompanion<Accessors>() {
object LombokAnnotations {
class Accessors(
val fluent: Boolean = false,
val chain: Boolean = false,
val noIsPrefix: Boolean = false,
val prefix: List<String> = emptyList()
) {
companion object : AnnotationAndConfigCompanion<Accessors>(LombokNames.ACCESSORS) {
override val annotationName: FqName = LombokNames.ACCESSORS
override fun extract(annotation: AnnotationDescriptor?, config: LombokConfig): Accessors {
val fluent =
annotation?.getBooleanArgument("fluent")
?: config.getBoolean("lombok.accessors.fluent")
?: false
val chain =
annotation?.getBooleanArgument("chain")
?: config.getBoolean("lombok.accessors.chain")
?: fluent
val noIsPrefix = config.getBoolean("lombok.getter.noIsPrefix") ?: false
val prefix =
annotation?.getStringArrayArgument("prefix")
?: config.getMultiString("lombok.accessors.prefix")
?: emptyList()
override fun extract(annotation: AnnotationDescriptor?, config: LombokConfig): Accessors {
val fluent =
annotation?.getBooleanArgument("fluent")
?: config.getBoolean("lombok.accessors.fluent")
?: false
val chain =
annotation?.getBooleanArgument("chain")
?: config.getBoolean("lombok.accessors.chain")
?: fluent
val noIsPrefix = config.getBoolean("lombok.getter.noIsPrefix") ?: false
val prefix =
annotation?.getStringArrayArgument("prefix")
?: config.getMultiString("lombok.accessors.prefix")
?: emptyList()
return Accessors(fluent, chain, noIsPrefix, prefix)
}
}
}
class Getter(val visibility: AccessLevel = AccessLevel.PUBLIC) {
companion object : AnnotationCompanion<Getter>(LombokNames.GETTER) {
override fun extract(annotation: AnnotationDescriptor): Getter =
Getter(
visibility = getAccessLevel(annotation)
)
}
}
class Setter(val visibility: AccessLevel = AccessLevel.PUBLIC) {
companion object : AnnotationCompanion<Setter>( LombokNames.SETTER) {
override fun extract(annotation: AnnotationDescriptor): Setter =
Setter(
visibility = getAccessLevel(annotation)
)
}
}
class With(val visibility: AccessLevel = AccessLevel.PUBLIC) {
companion object : AnnotationCompanion<With>(LombokNames.WITH) {
override fun extract(annotation: AnnotationDescriptor): With =
With(
visibility = getAccessLevel(annotation)
)
}
}
interface ConstructorAnnotation {
val visibility: DescriptorVisibility
val staticName: String?
}
class NoArgsConstructor(
override val visibility: DescriptorVisibility,
override val staticName: String?
) : ConstructorAnnotation {
companion object : AnnotationCompanion<NoArgsConstructor>( LombokNames.NO_ARGS_CONSTRUCTOR) {
override fun extract(annotation: AnnotationDescriptor): NoArgsConstructor =
NoArgsConstructor(
visibility = getVisibility(annotation, "access"),
staticName = annotation.getNonBlankStringArgument("staticName")
)
}
}
class AllArgsConstructor(
override val visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC,
override val staticName: String? = null
) : ConstructorAnnotation {
companion object : AnnotationCompanion<AllArgsConstructor>(LombokNames.ALL_ARGS_CONSTRUCTOR) {
override fun extract(annotation: AnnotationDescriptor): AllArgsConstructor =
AllArgsConstructor(
visibility = getVisibility(annotation, "access"),
staticName = annotation.getNonBlankStringArgument("staticName")
)
}
}
class RequiredArgsConstructor(
override val visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC,
override val staticName: String? = null
) : ConstructorAnnotation {
companion object : AnnotationCompanion<RequiredArgsConstructor>(LombokNames.REQUIRED_ARGS_CONSTRUCTOR) {
override fun extract(annotation: AnnotationDescriptor): RequiredArgsConstructor =
RequiredArgsConstructor(
visibility = getVisibility(annotation, "access"),
staticName = annotation.getNonBlankStringArgument("staticName")
)
}
}
class Data(val staticConstructor: String?) {
fun asSetter(): Setter = Setter()
fun asGetter(): Getter = Getter()
fun asRequiredArgsConstructor(): RequiredArgsConstructor = RequiredArgsConstructor(
staticName = staticConstructor
)
companion object : AnnotationCompanion<Data>(LombokNames.DATA) {
override fun extract(annotation: AnnotationDescriptor): Data =
Data(
staticConstructor = annotation.getNonBlankStringArgument("staticConstructor")
)
}
}
class Value(val staticConstructor: String?) {
fun asGetter(): Getter = Getter()
fun asAllArgsConstructor(): AllArgsConstructor = AllArgsConstructor(
staticName = staticConstructor
)
companion object : AnnotationCompanion<Value>(LombokNames.VALUE) {
override fun extract(annotation: AnnotationDescriptor): Value =
Value(
staticConstructor = annotation.getNonBlankStringArgument("staticConstructor")
)
return Accessors(fluent, chain, noIsPrefix, prefix)
}
}
}
data class Getter(val visibility: AccessLevel = AccessLevel.PUBLIC) {
companion object : AnnotationCompanion<Getter>() {
override val name: FqName = LombokNames.GETTER
override fun extract(annotation: AnnotationDescriptor): Getter =
Getter(
visibility = getAccessLevel(annotation)
)
}
}
data class Setter(val visibility: AccessLevel = AccessLevel.PUBLIC) {
companion object : AnnotationCompanion<Setter>() {
override val name: FqName = LombokNames.SETTER
override fun extract(annotation: AnnotationDescriptor): Setter =
Setter(
visibility = getAccessLevel(annotation)
)
}
}
data class With(val visibility: AccessLevel = AccessLevel.PUBLIC) {
companion object : AnnotationCompanion<With>() {
override val name: FqName = LombokNames.WITH
override fun extract(annotation: AnnotationDescriptor): With =
With(
visibility = getAccessLevel(annotation)
)
}
}
interface ConstructorAnnotation {
val visibility: DescriptorVisibility
val staticName: String?
}
data class NoArgsConstructor(
override val visibility: DescriptorVisibility,
override val staticName: String?
) : ConstructorAnnotation {
companion object : AnnotationCompanion<NoArgsConstructor>() {
override val name: FqName = LombokNames.NO_ARGS_CONSTRUCTOR
override fun extract(annotation: AnnotationDescriptor): NoArgsConstructor =
NoArgsConstructor(
visibility = getVisibility(annotation, "access"),
staticName = annotation.getNonBlankStringArgument("staticName")
)
}
}
data class AllArgsConstructor(
override val visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC,
override val staticName: String? = null
) : ConstructorAnnotation {
companion object : AnnotationCompanion<AllArgsConstructor>() {
override val name: FqName = LombokNames.ALL_ARGS_CONSTRUCTOR
override fun extract(annotation: AnnotationDescriptor): AllArgsConstructor =
AllArgsConstructor(
visibility = getVisibility(annotation, "access"),
staticName = annotation.getNonBlankStringArgument("staticName")
)
}
}
data class RequiredArgsConstructor(
override val visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC,
override val staticName: String? = null
) : ConstructorAnnotation {
companion object : AnnotationCompanion<RequiredArgsConstructor>() {
override val name: FqName = LombokNames.REQUIRED_ARGS_CONSTRUCTOR
override fun extract(annotation: AnnotationDescriptor): RequiredArgsConstructor =
RequiredArgsConstructor(
visibility = getVisibility(annotation, "access"),
staticName = annotation.getNonBlankStringArgument("staticName")
)
}
}
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")
)
}
}
data class Value(val staticConstructor: String?) {
fun asGetter(): Getter = Getter()
fun asAllArgsConstructor(): AllArgsConstructor = AllArgsConstructor(
staticName = staticConstructor
)
companion object : AnnotationCompanion<Value>() {
override val name: FqName = LombokNames.VALUE
override fun extract(annotation: AnnotationDescriptor): Value =
Value(
staticConstructor = annotation.getNonBlankStringArgument("staticConstructor")
)
}
}
@@ -7,26 +7,26 @@ package org.jetbrains.kotlin.lombok.processor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.lombok.config.ConstructorAnnotation
import org.jetbrains.kotlin.lombok.utils.ValueParameter
import org.jetbrains.kotlin.lombok.utils.createJavaConstructor
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.ConstructorAnnotation
import org.jetbrains.kotlin.lombok.utils.LombokValueParameter
import org.jetbrains.kotlin.lombok.utils.createFunction
import org.jetbrains.kotlin.lombok.utils.createJavaConstructor
import org.jetbrains.kotlin.name.Name
abstract class AbstractConstructorProcessor<A : ConstructorAnnotation> : Processor {
override fun contribute(classDescriptor: ClassDescriptor): SyntheticParts {
override fun contribute(classDescriptor: ClassDescriptor, partsBuilder: SyntheticPartsBuilder) {
val valueParameters = getPropertiesForParameters(classDescriptor).map { property ->
ValueParameter(property.name, property.type)
LombokValueParameter(property.name, property.type)
}
val result = getAnnotation(classDescriptor)?.let { annotation ->
getAnnotation(classDescriptor)?.let { annotation ->
if (annotation.staticName == null) {
val constructor = classDescriptor.createJavaConstructor(
valueParameters = valueParameters,
visibility = annotation.visibility
)
SyntheticParts(constructors = listOfNotNull(constructor))
partsBuilder.addConstructor(constructor)
} else {
val function = classDescriptor.createFunction(
Name.identifier(annotation.staticName!!),
@@ -36,10 +36,9 @@ abstract class AbstractConstructorProcessor<A : ConstructorAnnotation> : Process
visibility = annotation.visibility,
receiver = null
)
SyntheticParts(staticFunctions = listOf(function))
partsBuilder.addStaticFunction(function)
}
}
return result ?: SyntheticParts.Empty
}
protected abstract fun getAnnotation(classDescriptor: ClassDescriptor): A?
@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.lombok.processor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.lombok.config.AllArgsConstructor
import org.jetbrains.kotlin.lombok.config.Value
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.AllArgsConstructor
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.Value
import org.jetbrains.kotlin.lombok.utils.getJavaFields
class AllArgsConstructorProcessor : AbstractConstructorProcessor<AllArgsConstructor>() {
@@ -9,24 +9,27 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.lombok.config.*
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.Accessors
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.Getter
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.Data
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.Value
import org.jetbrains.kotlin.lombok.utils.*
import org.jetbrains.kotlin.name.Name
class GetterProcessor(private val config: LombokConfig) : Processor {
override fun contribute(classDescriptor: ClassDescriptor): SyntheticParts {
override fun contribute(classDescriptor: ClassDescriptor, partsBuilder: SyntheticPartsBuilder) {
val globalAccessors = Accessors.get(classDescriptor, config)
val clGetter =
Getter.getOrNull(classDescriptor)
?: Data.getOrNull(classDescriptor)?.asGetter()
?: Value.getOrNull(classDescriptor)?.asGetter()
val functions = classDescriptor
classDescriptor
.getJavaFields()
.collectWithNotNull { Getter.getOrNull(it) ?: clGetter }
.mapNotNull { (field, annotation) -> createGetter(classDescriptor, field, annotation, globalAccessors) }
return SyntheticParts(functions)
.forEach(partsBuilder::addMethod)
}
private fun createGetter(
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.lombok.processor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.lombok.config.NoArgsConstructor
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.NoArgsConstructor
class NoArgsConstructorProcessor : AbstractConstructorProcessor<NoArgsConstructor>() {
@@ -12,5 +12,6 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
*/
interface Processor {
fun contribute(classDescriptor: ClassDescriptor): SyntheticParts
fun contribute(classDescriptor: ClassDescriptor, partsBuilder: SyntheticPartsBuilder)
}
@@ -9,8 +9,8 @@ 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.config.LombokAnnotations.Data
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.RequiredArgsConstructor
import org.jetbrains.kotlin.lombok.utils.LombokNames
import org.jetbrains.kotlin.lombok.utils.getJavaFields
import org.jetbrains.kotlin.resolve.source.getPsi
@@ -9,22 +9,25 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.lombok.config.*
import org.jetbrains.kotlin.lombok.utils.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.Accessors
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.Setter
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.Data
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
class SetterProcessor(private val config: LombokConfig) : Processor {
override fun contribute(classDescriptor: ClassDescriptor): SyntheticParts {
override fun contribute(classDescriptor: ClassDescriptor, partsBuilder: SyntheticPartsBuilder) {
//lombok doesn't generate setters for enums
if (classDescriptor.kind == ClassKind.ENUM_CLASS) return SyntheticParts.Empty
if (classDescriptor.kind == ClassKind.ENUM_CLASS) return
val globalAccessors = Accessors.get(classDescriptor, config)
val clSetter = Setter.getOrNull(classDescriptor) ?: Data.getOrNull(classDescriptor)?.asSetter()
val functions = classDescriptor
classDescriptor
.getJavaFields()
.collectWithNotNull { field -> Setter.getOrNull(field) ?: clSetter.takeIf { field.isVar } }
.mapNotNull { (field, setter) -> createSetter(classDescriptor, field, setter, globalAccessors) }
return SyntheticParts(functions)
.forEach(partsBuilder::addMethod)
}
private fun createSetter(
@@ -45,7 +48,7 @@ class SetterProcessor(private val config: LombokConfig) : Processor {
classDescriptor.createFunction(
Name.identifier(functionName),
listOf(ValueParameter(field.name, field.type)),
listOf(LombokValueParameter(field.name, field.type)),
returnType,
visibility = getter.visibility.toDescriptorVisibility()
)
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.lombok.processor
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
data class SyntheticParts(
class SyntheticParts(
val methods: List<SimpleFunctionDescriptor> = emptyList(),
val staticFunctions: List<SimpleFunctionDescriptor> = emptyList(),
val constructors: List<ClassConstructorDescriptor> = emptyList()
@@ -24,3 +24,23 @@ data class SyntheticParts(
val Empty = SyntheticParts()
}
}
class SyntheticPartsBuilder {
private val methods = mutableListOf<SimpleFunctionDescriptor>()
private val staticFunctions = mutableListOf<SimpleFunctionDescriptor>()
private val constructors = mutableListOf<ClassConstructorDescriptor>()
fun addMethod(method: SimpleFunctionDescriptor) {
methods += method
}
fun addStaticFunction(function: SimpleFunctionDescriptor) {
staticFunctions += function
}
fun addConstructor(constructor: ClassConstructorDescriptor) {
constructors += constructor
}
fun build(): SyntheticParts = SyntheticParts(methods, staticFunctions, constructors)
}
@@ -9,21 +9,19 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.lombok.config.AccessLevel
import org.jetbrains.kotlin.lombok.config.With
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.With
import org.jetbrains.kotlin.lombok.utils.*
import org.jetbrains.kotlin.name.Name
class WithProcessor : Processor {
override fun contribute(classDescriptor: ClassDescriptor): SyntheticParts {
override fun contribute(classDescriptor: ClassDescriptor, partsBuilder: SyntheticPartsBuilder) {
val clWith = With.getOrNull(classDescriptor)
val functions = classDescriptor
classDescriptor
.getJavaFields()
.collectWithNotNull { With.getOrNull(it) ?: clWith }
.mapNotNull { (field, annotation) -> createWith(classDescriptor, field, annotation) }
return SyntheticParts(functions)
.forEach(partsBuilder::addMethod)
}
private fun createWith(
@@ -37,7 +35,7 @@ class WithProcessor : Processor {
return classDescriptor.createFunction(
Name.identifier(functionName),
listOf(ValueParameter(field.name, field.type)),
listOf(LombokValueParameter(field.name, field.type)),
classDescriptor.defaultType,
visibility = with.visibility.toDescriptorVisibility()
)
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.lombok.utils
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
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
@@ -18,11 +17,11 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
import org.jetbrains.kotlin.types.typeUtil.isBoolean
data class ValueParameter(val name: Name, val type: KotlinType)
data class LombokValueParameter(val name: Name, val type: KotlinType)
fun ClassDescriptor.createFunction(
name: Name,
valueParameters: List<ValueParameter>,
valueParameters: List<LombokValueParameter>,
returnType: KotlinType?,
typeParameters: List<TypeParameterDescriptor> = emptyList(),
modality: Modality? = Modality.OPEN,
@@ -52,7 +51,7 @@ fun ClassDescriptor.createFunction(
}
fun ClassDescriptor.createJavaConstructor(
valueParameters: List<ValueParameter>,
valueParameters: List<LombokValueParameter>,
visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC
): ClassConstructorDescriptor {
val constructor = JavaClassConstructorDescriptor.create(
@@ -74,7 +73,7 @@ fun ClassDescriptor.createJavaConstructor(
return constructor
}
private fun CallableDescriptor.makeValueParameter(param: ValueParameter, index: Int): ValueParameterDescriptor {
private fun CallableDescriptor.makeValueParameter(param: LombokValueParameter, index: Int): ValueParameterDescriptor {
return ValueParameterDescriptorImpl(
containingDeclaration = this,
original = null,
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.lombok.utils
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.lombok.config.Accessors
import org.jetbrains.kotlin.lombok.config.LombokAnnotations.Accessors
object AccessorNames {
const val IS = "is"
@@ -5,8 +5,15 @@
package org.jetbrains.kotlin.lombok.utils
import java.util.*
@Suppress("UNCHECKED_CAST")
fun <E, R> Collection<E>.collectWithNotNull(f: (E) -> R?): List<Pair<E, R>> =
map { it to f(it) }.filter { it.second != null } as List<Pair<E, R>>
fun String?.trimToNull(): String? = this?.trim()?.takeIf { it.isNotEmpty() }
//because capitalize from stdlib is deprecated
fun String.capitalize(): String = replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
fun String.decapitalize(): String = replaceFirstChar { if (it.isUpperCase()) it.lowercase(Locale.getDefault()) else it.toString() }
@@ -0,0 +1,3 @@
fun <T> assertEquals(a: T, b: T) {
if (a != b) throw RuntimeException("'$a' was not equal to '$b'")
}
@@ -31,11 +31,13 @@ class Test {
fun run() {
val obj = DataExample("name")
obj.getName()
val name = obj.name
assertEquals(obj.name, "name")
obj.getTags()
val tags = obj.tags
obj.setScore(1.5)
assertEquals(obj.score, 1.5)
obj.score = 2.5
assertEquals(obj.score, 2.5)
val ex: DataExample.Exercise<Int> = DataExample.Exercise.of("name", 12)
}
@@ -24,6 +24,8 @@ public class ConstructorExample<A, B> {
class Test {
fun run() {
val generated: ConstructorExample<Long, Boolean> = ConstructorExample.of(12, 42L, true)
val generatedReq: ConstructorExample<String, Boolean> = ConstructorExample.of("234");
assertEquals(generated.name, 42L)
val generatedReq: ConstructorExample<String, Boolean> = ConstructorExample.of("234")
assertEquals(generatedReq.name, "234")
}
}
@@ -30,7 +30,7 @@ public class FluentTest {
class Test {
fun run() {
val obj = FluentTest()
val getter = obj.age()
assertEquals(obj.age(), 10)
obj.primitiveBoolean()
@@ -36,5 +36,6 @@ public class ConstructorExample {
class Test {
fun run() {
val generated = ConstructorExample("foo", true)
assertEquals(generated.foo, "foo")
}
}
@@ -38,5 +38,6 @@ public class ConstructorExample {
class Test {
fun run() {
val generated = ConstructorExample.build("foo", true, 12)
assertEquals(generated.foo, "foo")
}
}
@@ -27,7 +27,9 @@ class Test {
fun run() {
val obj = SetterTest()
obj.setAge(42)
obj.age = 42
assertEquals(obj.age, 42)
obj.age = 43
assertEquals(obj.age, 43)
obj.setPrimitiveBoolean(true)
@@ -29,8 +29,11 @@ class Test {
fun run() {
val obj = SetterTest()
obj.fluent(12)
assertEquals(obj.fluent(), 12)
obj.setChained("zz").getChained()
assertEquals(obj.getChained(), "zz")
obj.whyNotBoth("zzz").whyNotBoth()
assertEquals(obj.whyNotBoth(), "zzz")
}
}
@@ -31,12 +31,14 @@ import lombok.*;
class Test {
fun run() {
val obj = ValueExample("name", 12, 4.5)
obj.getName()
val name = obj.name
obj.getAge()
val age = obj.age
val score = obj.score
assertEquals(obj.getName(), "name")
assertEquals(obj.name, "name")
assertEquals(obj.getAge(), 12)
assertEquals(obj.age, 12)
assertEquals(obj.score, 4.5)
val ex: ValueExample.Exercise<Int> = ValueExample.Exercise.of("name", 12)
val ex: ValueExample.Exercise<Int> = ValueExample.Exercise.of("nam1e", 42)
assertEquals(ex.name, "nam1e")
assertEquals(ex.value, 42)
}
}
@@ -1,25 +1,17 @@
//FILE: WithExample.java
import lombok.AccessLevel;
import lombok.With;
import lombok.*;
@AllArgsConstructor
@NoArgsConstructor
public class WithExample {
//todo replace constructors with annotations when supported
public WithExample() {
@Getter @With private int age = 10;
}
@Getter @With private String name;
public WithExample(int age, String name) {
}
@With private int age = 10;
@With private String name;
static void test() {
WithExample obj = new WithExample().withAge(16).withName("fooo");
public static WithExample test() {
return new WithExample().withAge(16).withName("fooo");
}
}
@@ -27,7 +19,10 @@ public class WithExample {
//FILE: test.kt
class Test {
fun run() {
val obj: WithExample = WithExample().withAge(16).withName("fooo")
assertEquals(obj.getName(), "fooo")
assertEquals(obj.age, 16)
}
}
@@ -18,9 +18,13 @@ import java.net.URLClassLoader
abstract class AbstractLombokCompileTest : CodegenTestCase() {
private val commonClassLoader = URLClassLoader(arrayOf(getLombokJar().toURI().toURL()))
private val commonSourceFile = TestFile(
"common.kt",
File("plugins/lombok/lombok-compiler-plugin/testData/common.kt").readText()
)
override fun doMultiFileTest(wholeFile: File, files: List<TestFile>) {
compile(files, true, true)
compile(files + commonSourceFile, true, true)
}
override fun setupEnvironment(environment: KotlinCoreEnvironment) {