[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
@@ -17,7 +17,7 @@ interface SyntheticJavaResolveExtension {
) {
fun getProvider(project: Project): SyntheticJavaPartsProvider {
val instances = getInstances(project)
val providers = instances.map { it.getProvider() }
val providers = instances.map { it.buildProvider() }
return if (providers.isEmpty()) {
SyntheticJavaPartsProvider.EMPTY
} else {
@@ -26,7 +26,7 @@ interface SyntheticJavaResolveExtension {
}
}
fun getProvider(): SyntheticJavaPartsProvider
fun buildProvider(): SyntheticJavaPartsProvider
}
+19
View File
@@ -0,0 +1,19 @@
Copyright (C) 2009-2021 The Project Lombok Authors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -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) {