[lombok] Strip 'is' prefix in boolean properties
This commit is contained in:
committed by
TeamCityServer
parent
8a2279de2b
commit
f2c0b8c68d
@@ -23,7 +23,7 @@ Features support:
|
|||||||
- [ ] Copy annotations
|
- [ ] Copy annotations
|
||||||
- [ ] Strip defined prefixes - in config and @Accessors
|
- [ ] Strip defined prefixes - in config and @Accessors
|
||||||
- [ ] Skip generation with AccessLevel.NONE
|
- [ ] Skip generation with AccessLevel.NONE
|
||||||
- [ ] Strip 'is' prefix for boolean fields
|
- [x] Strip 'is' prefix for boolean fields
|
||||||
|
|
||||||
[~] [@With](https://projectlombok.org/features/With)
|
[~] [@With](https://projectlombok.org/features/With)
|
||||||
|
|
||||||
|
|||||||
+12
-6
@@ -9,10 +9,7 @@ import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
|||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.lombok.utils.LombokNames
|
import org.jetbrains.kotlin.lombok.utils.*
|
||||||
import org.jetbrains.kotlin.lombok.utils.getBooleanArgument
|
|
||||||
import org.jetbrains.kotlin.lombok.utils.getNonBlankStringArgument
|
|
||||||
import org.jetbrains.kotlin.lombok.utils.getVisibility
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -56,7 +53,12 @@ abstract class AnnotationAndConfigCompanion<T> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Accessors(val fluent: Boolean = false, val chain: Boolean = false) {
|
data class Accessors(
|
||||||
|
val fluent: Boolean = false,
|
||||||
|
val chain: Boolean = false,
|
||||||
|
val noIsPrefix: Boolean = false,
|
||||||
|
val prefix: List<String> = emptyList()
|
||||||
|
) {
|
||||||
companion object : AnnotationAndConfigCompanion<Accessors>() {
|
companion object : AnnotationAndConfigCompanion<Accessors>() {
|
||||||
|
|
||||||
override val annotationName: FqName = LombokNames.ACCESSORS
|
override val annotationName: FqName = LombokNames.ACCESSORS
|
||||||
@@ -70,7 +72,11 @@ data class Accessors(val fluent: Boolean = false, val chain: Boolean = false) {
|
|||||||
annotation?.getBooleanArgument("chain")
|
annotation?.getBooleanArgument("chain")
|
||||||
?: config.getBoolean("lombok.accessors.chain")
|
?: config.getBoolean("lombok.accessors.chain")
|
||||||
?: fluent
|
?: fluent
|
||||||
return Accessors(fluent, chain)
|
val noIsPrefix = config.getBoolean("lombok.getter.noIsPrefix") ?: false
|
||||||
|
val prefix = annotation?.getStringArrayArgument("prefix")
|
||||||
|
?: emptyList()
|
||||||
|
|
||||||
|
return Accessors(fluent, chain, noIsPrefix, prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-15
@@ -10,19 +10,11 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
|
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
|
||||||
import org.jetbrains.kotlin.lombok.config.*
|
import org.jetbrains.kotlin.lombok.config.*
|
||||||
import org.jetbrains.kotlin.lombok.utils.collectWithNotNull
|
import org.jetbrains.kotlin.lombok.utils.*
|
||||||
import org.jetbrains.kotlin.lombok.utils.createFunction
|
|
||||||
import org.jetbrains.kotlin.lombok.utils.getJavaFields
|
|
||||||
import org.jetbrains.kotlin.lombok.utils.toPreparedBase
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isBoolean
|
|
||||||
|
|
||||||
class GetterProcessor(private val config: LombokConfig) : Processor {
|
class GetterProcessor(private val config: LombokConfig) : Processor {
|
||||||
|
|
||||||
private val noIsPrefix by lazy { config.getBooleanOrDefault("lombok.getter.noIsPrefix") }
|
|
||||||
|
|
||||||
override fun contribute(classDescriptor: ClassDescriptor, jClass: JavaClassImpl): Parts {
|
override fun contribute(classDescriptor: ClassDescriptor, jClass: JavaClassImpl): Parts {
|
||||||
val globalAccessors = Accessors.get(classDescriptor, config)
|
val globalAccessors = Accessors.get(classDescriptor, config)
|
||||||
val clGetter =
|
val clGetter =
|
||||||
@@ -45,13 +37,13 @@ class GetterProcessor(private val config: LombokConfig) : Processor {
|
|||||||
globalAccessors: Accessors
|
globalAccessors: Accessors
|
||||||
): SimpleFunctionDescriptor? {
|
): SimpleFunctionDescriptor? {
|
||||||
val accessors = Accessors.getIfAnnotated(field, config) ?: globalAccessors
|
val accessors = Accessors.getIfAnnotated(field, config) ?: globalAccessors
|
||||||
|
val propertyName = field.toPropertyName(accessors)
|
||||||
val functionName =
|
val functionName =
|
||||||
if (accessors.fluent) {
|
if (accessors.fluent) {
|
||||||
field.name.identifier
|
propertyName
|
||||||
} else {
|
} else {
|
||||||
val prefix = if (field.type.isPrimitiveBoolean() && !noIsPrefix) "is" else "get"
|
val prefix = if (field.type.isPrimitiveBoolean() && !accessors.noIsPrefix) AccessorNames.IS else AccessorNames.GET
|
||||||
prefix + toPreparedBase(field.name.identifier)
|
prefix + propertyName.capitalize()
|
||||||
}
|
}
|
||||||
return classDescriptor.createFunction(
|
return classDescriptor.createFunction(
|
||||||
Name.identifier(functionName),
|
Name.identifier(functionName),
|
||||||
@@ -61,6 +53,4 @@ class GetterProcessor(private val config: LombokConfig) : Processor {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinType.isPrimitiveBoolean(): Boolean = this is SimpleTypeMarker && isBoolean() //todo
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-5
@@ -38,13 +38,11 @@ class SetterProcessor(private val config: LombokConfig) : Processor {
|
|||||||
globalAccessors: Accessors
|
globalAccessors: Accessors
|
||||||
): SimpleFunctionDescriptor? {
|
): SimpleFunctionDescriptor? {
|
||||||
val accessors = Accessors.getIfAnnotated(field, config) ?: globalAccessors
|
val accessors = Accessors.getIfAnnotated(field, config) ?: globalAccessors
|
||||||
|
val propertyName = field.toPropertyName(accessors)
|
||||||
|
|
||||||
val functionName =
|
val functionName =
|
||||||
if (accessors.fluent) {
|
if (accessors.fluent) propertyName
|
||||||
field.name.identifier
|
else AccessorNames.SET + propertyName.capitalize()
|
||||||
} else {
|
|
||||||
"set" + toPreparedBase(field.name.identifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
val returnType = if (accessors.chain) classDescriptor.defaultType else classDescriptor.builtIns.unitType
|
val returnType = if (accessors.chain) classDescriptor.defaultType else classDescriptor.builtIns.unitType
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ class WithProcessor(private val config: LombokConfig) : Processor {
|
|||||||
with: With
|
with: With
|
||||||
): SimpleFunctionDescriptor? {
|
): SimpleFunctionDescriptor? {
|
||||||
|
|
||||||
val functionName = "with" + toPreparedBase(field.name.identifier)
|
val functionName = "with" + toPropertyNameCapitalized(field.name.identifier)
|
||||||
|
|
||||||
return classDescriptor.createFunction(
|
return classDescriptor.createFunction(
|
||||||
Name.identifier(functionName),
|
Name.identifier(functionName),
|
||||||
|
|||||||
+14
-8
@@ -12,9 +12,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.java.JavaVisibilities
|
import org.jetbrains.kotlin.descriptors.java.JavaVisibilities
|
||||||
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.constants.BooleanValue
|
import org.jetbrains.kotlin.resolve.constants.*
|
||||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
|
||||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
|
||||||
|
|
||||||
fun getVisibility(annotation: AnnotationDescriptor, field: String = "value"): DescriptorVisibility {
|
fun getVisibility(annotation: AnnotationDescriptor, field: String = "value"): DescriptorVisibility {
|
||||||
val value = annotation.getStringArgument(field) ?: "PUBLIC"
|
val value = annotation.getStringArgument(field) ?: "PUBLIC"
|
||||||
@@ -32,11 +30,19 @@ fun AnnotationDescriptor.getStringArgument(argumentName: String): String? {
|
|||||||
val argument = allValueArguments[Name.identifier(argumentName)]
|
val argument = allValueArguments[Name.identifier(argumentName)]
|
||||||
?: return null
|
?: return null
|
||||||
|
|
||||||
return when (argument) {
|
return extractString(argument)
|
||||||
is EnumValue -> argument.enumEntryName.identifier
|
}
|
||||||
is StringValue -> argument.value
|
|
||||||
else -> throw RuntimeException("Argument $argument is not supported")
|
fun AnnotationDescriptor.getStringArrayArgument(argumentName: String): List<String>? {
|
||||||
}
|
val argument = allValueArguments[Name.identifier(argumentName)] ?: return emptyList()
|
||||||
|
if (argument !is ArrayValue) throw RuntimeException("Argument should be ArrayValue, got $argument")
|
||||||
|
return argument.value.map(::extractString)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun extractString(argument: ConstantValue<*>) = when (argument) {
|
||||||
|
is EnumValue -> argument.enumEntryName.identifier
|
||||||
|
is StringValue -> argument.value
|
||||||
|
else -> throw RuntimeException("Argument $argument is not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun AnnotationDescriptor.getNonBlankStringArgument(argumentName: String): String? =
|
fun AnnotationDescriptor.getNonBlankStringArgument(argumentName: String): String? =
|
||||||
|
|||||||
+4
@@ -15,6 +15,8 @@ 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
|
||||||
|
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 ValueParameter(val name: Name, val type: KotlinType)
|
||||||
|
|
||||||
@@ -93,3 +95,5 @@ fun ClassDescriptor.getJavaFields(): List<PropertyDescriptor> =
|
|||||||
.map {
|
.map {
|
||||||
this.unsubstitutedMemberScope.getContributedVariables(it, NoLookupLocation.FROM_SYNTHETIC_SCOPE).single()
|
this.unsubstitutedMemberScope.getContributedVariables(it, NoLookupLocation.FROM_SYNTHETIC_SCOPE).single()
|
||||||
}.filter { it.isJavaField }
|
}.filter { it.isJavaField }
|
||||||
|
|
||||||
|
fun KotlinType.isPrimitiveBoolean(): Boolean = this is SimpleTypeMarker && isBoolean()
|
||||||
|
|||||||
+28
-2
@@ -5,6 +5,32 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.lombok.utils
|
package org.jetbrains.kotlin.lombok.utils
|
||||||
|
|
||||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.lombok.config.Accessors
|
||||||
|
|
||||||
fun toPreparedBase(name: String): String = name.capitalizeAsciiOnly()
|
object AccessorNames {
|
||||||
|
const val IS = "is"
|
||||||
|
const val GET = "get"
|
||||||
|
const val SET = "set"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PropertyDescriptor.toPropertyName(config: Accessors): String {
|
||||||
|
val isPrimitiveBoolean = type.isPrimitiveBoolean()
|
||||||
|
val prefixes = if (isPrimitiveBoolean) config.prefix + AccessorNames.IS else config.prefix
|
||||||
|
return toPropertyName(name.identifier, prefixes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toPropertyName(name: String, prefixesToStrip: List<String> = emptyList()): String =
|
||||||
|
name.stripPrefixes(prefixesToStrip)
|
||||||
|
|
||||||
|
fun toPropertyNameCapitalized(name: String, prefixesToStrip: List<String> = emptyList()): String =
|
||||||
|
name.stripPrefixes(prefixesToStrip).capitalize()
|
||||||
|
|
||||||
|
private fun String.stripPrefixes(prefixes: List<String>): String =
|
||||||
|
prefixes.firstOrNull { isPrefix(it) }?.let { prefix ->
|
||||||
|
drop(prefix.length)
|
||||||
|
} ?: this
|
||||||
|
|
||||||
|
|
||||||
|
private fun String.isPrefix(prefix: String): Boolean =
|
||||||
|
length > prefix.length && startsWith(prefix) && get(prefix.length).isUpperCase()
|
||||||
|
|||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
//FILE: AccessorsTest.java
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
import lombok.experimental.*;
|
||||||
|
|
||||||
|
@Getter @Setter
|
||||||
|
public class AccessorsTest {
|
||||||
|
private int age = 10;
|
||||||
|
|
||||||
|
private boolean isHuman;
|
||||||
|
private Boolean isNonPrimitiveHuman;
|
||||||
|
|
||||||
|
static void test() {
|
||||||
|
val obj = new AccessorsTest();
|
||||||
|
|
||||||
|
obj.getAge();
|
||||||
|
|
||||||
|
obj.isHuman();
|
||||||
|
obj.setHuman(true);
|
||||||
|
|
||||||
|
obj.getIsNonPrimitiveHuman();
|
||||||
|
obj.setIsNonPrimitiveHuman(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//FILE: test.kt
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
fun run() {
|
||||||
|
val obj = AccessorsTest()
|
||||||
|
|
||||||
|
obj.getAge()
|
||||||
|
val age = obj.age
|
||||||
|
|
||||||
|
obj.isHuman()
|
||||||
|
obj.setHuman(true)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+5
@@ -31,6 +31,11 @@ public class LombokCompileTestGenerated extends AbstractLombokCompileTest {
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/lombok/lombok-compiler-plugin/testData/compile"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("allArgsConstructor.kt")
|
@TestMetadata("allArgsConstructor.kt")
|
||||||
public void testAllArgsConstructor() throws Exception {
|
public void testAllArgsConstructor() throws Exception {
|
||||||
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/allArgsConstructor.kt");
|
runTest("plugins/lombok/lombok-compiler-plugin/testData/compile/allArgsConstructor.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user