[Lombok] Properly support Guava collections with @Singular
^KT-53683 Fixed
This commit is contained in:
committed by
teamcity
parent
69a857649f
commit
2aadaee69f
+1
-1
@@ -111,7 +111,7 @@ object EnvironmentBasedStandardLibrariesPathProvider : KotlinStandardLibrariesPa
|
|||||||
const val KOTLIN_SCRIPT_RUNTIME_PROP = "org.jetbrains.kotlin.test.kotlin-script-runtime"
|
const val KOTLIN_SCRIPT_RUNTIME_PROP = "org.jetbrains.kotlin.test.kotlin-script-runtime"
|
||||||
const val KOTLIN_ANNOTATIONS_JVM_PROP = "org.jetbrains.kotlin.test.kotlin-annotations-jvm"
|
const val KOTLIN_ANNOTATIONS_JVM_PROP = "org.jetbrains.kotlin.test.kotlin-annotations-jvm"
|
||||||
|
|
||||||
private fun getFile(propertyName: String): File {
|
fun getFile(propertyName: String): File {
|
||||||
return System.getProperty(propertyName)
|
return System.getProperty(propertyName)
|
||||||
?.let(::File)
|
?.let(::File)
|
||||||
?.takeIf { it.exists() }
|
?.takeIf { it.exists() }
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ dependencies {
|
|||||||
|
|
||||||
testApi(commonDependency("junit:junit"))
|
testApi(commonDependency("junit:junit"))
|
||||||
|
|
||||||
|
testRuntimeOnly(commonDependency("com.google.guava:guava"))
|
||||||
testRuntimeOnly(toolsJar())
|
testRuntimeOnly(toolsJar())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +54,16 @@ sourceSets {
|
|||||||
|
|
||||||
projectTest(parallel = true) {
|
projectTest(parallel = true) {
|
||||||
workingDir = rootDir
|
workingDir = rootDir
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
project.configurations
|
||||||
|
.testRuntimeClasspath.get()
|
||||||
|
.files
|
||||||
|
.find { "guava" in it.name }
|
||||||
|
?.absolutePath
|
||||||
|
?.let { systemProperty("org.jetbrains.kotlin.test.guava-location", it) }
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimeJar()
|
runtimeJar()
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ object LombokNames {
|
|||||||
val BUILDER = FqName("lombok.Builder")
|
val BUILDER = FqName("lombok.Builder")
|
||||||
val SINGULAR = FqName("lombok.Singular")
|
val SINGULAR = FqName("lombok.Singular")
|
||||||
|
|
||||||
|
val TABLE = FqName("com.google.common.collect.Table")
|
||||||
|
|
||||||
val ACCESSORS_ID = ClassId.topLevel(ACCESSORS)
|
val ACCESSORS_ID = ClassId.topLevel(ACCESSORS)
|
||||||
val GETTER_ID = ClassId.topLevel(GETTER)
|
val GETTER_ID = ClassId.topLevel(GETTER)
|
||||||
@@ -35,6 +36,8 @@ object LombokNames {
|
|||||||
val ALL_ARGS_CONSTRUCTOR_ID = ClassId.topLevel(ALL_ARGS_CONSTRUCTOR)
|
val ALL_ARGS_CONSTRUCTOR_ID = ClassId.topLevel(ALL_ARGS_CONSTRUCTOR)
|
||||||
val REQUIRED_ARGS_CONSTRUCTOR_ID = ClassId.topLevel(REQUIRED_ARGS_CONSTRUCTOR)
|
val REQUIRED_ARGS_CONSTRUCTOR_ID = ClassId.topLevel(REQUIRED_ARGS_CONSTRUCTOR)
|
||||||
|
|
||||||
|
val TABLE_CLASS_ID = ClassId.topLevel(TABLE)
|
||||||
|
|
||||||
//taken from idea lombok plugin
|
//taken from idea lombok plugin
|
||||||
val NON_NULL_ANNOTATIONS = listOf(
|
val NON_NULL_ANNOTATIONS = listOf(
|
||||||
"androidx.annotation.NonNull",
|
"androidx.annotation.NonNull",
|
||||||
@@ -83,36 +86,23 @@ object LombokNames {
|
|||||||
"kotlin.collections.MutableMap",
|
"kotlin.collections.MutableMap",
|
||||||
)
|
)
|
||||||
|
|
||||||
private val SUPPORTED_COLLECTIONS = SUPPORTED_JAVA_COLLECTIONS + SUPPORTED_KOTLIN_COLLECTIONS
|
val SUPPORTED_GUAVA_COLLECTIONS = setOf(
|
||||||
private val SUPPORTED_MAPS = SUPPORTED_JAVA_MAPS + SUPPORTED_KOTLIN_MAPS
|
|
||||||
|
|
||||||
private val SUPPORTED_COLLECTIONS_WITH_GUAVA = SUPPORTED_COLLECTIONS + setOf(
|
|
||||||
"com.google.common.collect.ImmutableCollection",
|
"com.google.common.collect.ImmutableCollection",
|
||||||
"com.google.common.collect.ImmutableList",
|
"com.google.common.collect.ImmutableList",
|
||||||
"com.google.common.collect.ImmutableSet",
|
"com.google.common.collect.ImmutableSet",
|
||||||
"com.google.common.collect.ImmutableSortedSet",
|
"com.google.common.collect.ImmutableSortedSet",
|
||||||
)
|
)
|
||||||
|
|
||||||
private val SUPPORTED_MAPS_WITH_GUAVA = SUPPORTED_MAPS + setOf(
|
private val SUPPORTED_GUAVA_MAPS = setOf(
|
||||||
"com.google.common.collect.ImmutableMap",
|
"com.google.common.collect.ImmutableMap",
|
||||||
"com.google.common.collect.ImmutableBiMap",
|
"com.google.common.collect.ImmutableBiMap",
|
||||||
"com.google.common.collect.ImmutableSortedMap",
|
"com.google.common.collect.ImmutableSortedMap",
|
||||||
|
)
|
||||||
|
val SUPPORTED_COLLECTIONS = SUPPORTED_JAVA_COLLECTIONS + SUPPORTED_KOTLIN_COLLECTIONS + SUPPORTED_GUAVA_COLLECTIONS
|
||||||
|
|
||||||
|
val SUPPORTED_MAPS = SUPPORTED_JAVA_MAPS + SUPPORTED_KOTLIN_MAPS + SUPPORTED_GUAVA_MAPS
|
||||||
|
|
||||||
|
val SUPPORTED_TABLES = setOf(
|
||||||
"com.google.common.collect.ImmutableTable",
|
"com.google.common.collect.ImmutableTable",
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getSupportedCollectionsForSingular(includeGuava: Boolean): Set<String> {
|
|
||||||
return if (includeGuava) {
|
|
||||||
SUPPORTED_COLLECTIONS_WITH_GUAVA
|
|
||||||
} else {
|
|
||||||
SUPPORTED_COLLECTIONS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSupportedMapsForSingular(includeGuava: Boolean): Set<String> {
|
|
||||||
return if (includeGuava) {
|
|
||||||
SUPPORTED_MAPS_WITH_GUAVA
|
|
||||||
} else {
|
|
||||||
SUPPORTED_MAPS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-10
@@ -9,6 +9,7 @@ import com.intellij.openapi.util.text.StringUtil
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.CompositeAnnotations
|
import org.jetbrains.kotlin.descriptors.annotations.CompositeAnnotations
|
||||||
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.SyntheticJavaClassDescriptor
|
import org.jetbrains.kotlin.load.java.lazy.descriptors.SyntheticJavaClassDescriptor
|
||||||
@@ -146,26 +147,28 @@ class BuilderProcessor(private val config: LombokConfig) : Processor {
|
|||||||
val nameInSingularForm = (singular.singularName ?: field.name.identifier.singularForm)?.let(Name::identifier) ?: return
|
val nameInSingularForm = (singular.singularName ?: field.name.identifier.singularForm)?.let(Name::identifier) ?: return
|
||||||
val typeName = field.type.constructor.declarationDescriptor?.fqNameSafe?.asString() ?: return
|
val typeName = field.type.constructor.declarationDescriptor?.fqNameSafe?.asString() ?: return
|
||||||
|
|
||||||
val useGuava = config.useGuava
|
|
||||||
val supportedCollections = LombokNames.getSupportedCollectionsForSingular(useGuava)
|
|
||||||
val supportedMaps = LombokNames.getSupportedMapsForSingular(useGuava)
|
|
||||||
|
|
||||||
val addMultipleParameterType: KotlinType
|
val addMultipleParameterType: KotlinType
|
||||||
val valueParameters: List<LombokValueParameter>
|
val valueParameters: List<LombokValueParameter>
|
||||||
|
|
||||||
when (typeName) {
|
when (typeName) {
|
||||||
in supportedCollections -> {
|
in LombokNames.SUPPORTED_COLLECTIONS -> {
|
||||||
val parameterType = field.parameterType(0, singular.allowNull) ?: return
|
val parameterType = field.parameterType(0, singular.allowNull) ?: return
|
||||||
valueParameters = listOf(
|
valueParameters = listOf(
|
||||||
LombokValueParameter(nameInSingularForm, parameterType)
|
LombokValueParameter(nameInSingularForm, parameterType)
|
||||||
)
|
)
|
||||||
|
|
||||||
addMultipleParameterType = field.module.builtIns.collection.defaultType.replace(
|
val builtIns = field.module.builtIns
|
||||||
|
val baseType = when (typeName) {
|
||||||
|
in LombokNames.SUPPORTED_GUAVA_COLLECTIONS -> builtIns.iterable.defaultType
|
||||||
|
else -> builtIns.collection.defaultType
|
||||||
|
}
|
||||||
|
|
||||||
|
addMultipleParameterType = baseType.replace(
|
||||||
newArguments = listOf(TypeProjectionImpl(parameterType))
|
newArguments = listOf(TypeProjectionImpl(parameterType))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
in supportedMaps -> {
|
in LombokNames.SUPPORTED_MAPS -> {
|
||||||
val keyType = field.parameterType(0, singular.allowNull) ?: return
|
val keyType = field.parameterType(0, singular.allowNull) ?: return
|
||||||
val valueType = field.parameterType(1, singular.allowNull) ?: return
|
val valueType = field.parameterType(1, singular.allowNull) ?: return
|
||||||
valueParameters = listOf(
|
valueParameters = listOf(
|
||||||
@@ -178,6 +181,28 @@ class BuilderProcessor(private val config: LombokConfig) : Processor {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
in LombokNames.SUPPORTED_TABLES -> {
|
||||||
|
val rowKeyType = field.parameterType(0, singular.allowNull) ?: return
|
||||||
|
val columnKeyType = field.parameterType(1, singular.allowNull) ?: return
|
||||||
|
val valueType = field.parameterType(2, singular.allowNull) ?: return
|
||||||
|
|
||||||
|
val tableDescriptor = field.module.resolveClassByFqName(LombokNames.TABLE, NoLookupLocation.FROM_SYNTHETIC_SCOPE) ?: return
|
||||||
|
|
||||||
|
valueParameters = listOf(
|
||||||
|
LombokValueParameter(Name.identifier("rowKey"), rowKeyType),
|
||||||
|
LombokValueParameter(Name.identifier("columnKey"), columnKeyType),
|
||||||
|
LombokValueParameter(Name.identifier("value"), valueType),
|
||||||
|
)
|
||||||
|
|
||||||
|
addMultipleParameterType = tableDescriptor.defaultType.replace(
|
||||||
|
newArguments = listOf(
|
||||||
|
TypeProjectionImpl(rowKeyType),
|
||||||
|
TypeProjectionImpl(columnKeyType),
|
||||||
|
TypeProjectionImpl(valueType),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
else -> return
|
else -> return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,9 +242,6 @@ class BuilderProcessor(private val config: LombokConfig) : Processor {
|
|||||||
|
|
||||||
private class BuilderData(val builder: Builder, val constructingClass: ClassDescriptor)
|
private class BuilderData(val builder: Builder, val constructingClass: ClassDescriptor)
|
||||||
|
|
||||||
private val LombokConfig.useGuava: Boolean
|
|
||||||
get() = getBoolean("lombok.singular.useGuava") ?: false
|
|
||||||
|
|
||||||
private fun PropertyDescriptor.parameterType(index: Int, allowNull: Boolean): KotlinType? {
|
private fun PropertyDescriptor.parameterType(index: Int, allowNull: Boolean): KotlinType? {
|
||||||
val type = returnType?.arguments?.getOrNull(index)?.type ?: return null
|
val type = returnType?.arguments?.getOrNull(index)?.type ?: return null
|
||||||
val typeWithProperNullability = if (allowNull) type.makeNullable() else type.makeNotNullable()
|
val typeWithProperNullability = if (allowNull) type.makeNullable() else type.makeNotNullable()
|
||||||
|
|||||||
+25
-10
@@ -184,24 +184,25 @@ class BuilderGenerator(session: FirSession) : FirDeclarationGenerationExtension(
|
|||||||
|
|
||||||
val nameInSingularForm = (singular.singularName ?: field.name.identifier.singularForm)?.let(Name::identifier) ?: return
|
val nameInSingularForm = (singular.singularName ?: field.name.identifier.singularForm)?.let(Name::identifier) ?: return
|
||||||
|
|
||||||
val useGuava = lombokService.config.useGuava
|
|
||||||
val supportedCollections = LombokNames.getSupportedCollectionsForSingular(useGuava)
|
|
||||||
val supportedMaps = LombokNames.getSupportedMapsForSingular(useGuava)
|
|
||||||
|
|
||||||
val addMultipleParameterType: FirTypeRef
|
val addMultipleParameterType: FirTypeRef
|
||||||
val valueParameters: List<ConeLombokValueParameter>
|
val valueParameters: List<ConeLombokValueParameter>
|
||||||
|
|
||||||
when (typeName) {
|
when (typeName) {
|
||||||
in supportedCollections -> {
|
in LombokNames.SUPPORTED_COLLECTIONS -> {
|
||||||
val parameterType = javaClassifierType.parameterType(0, singular.allowNull) ?: return
|
val parameterType = javaClassifierType.parameterType(0, singular.allowNull) ?: return
|
||||||
valueParameters = listOf(
|
valueParameters = listOf(
|
||||||
ConeLombokValueParameter(nameInSingularForm, parameterType.toRef())
|
ConeLombokValueParameter(nameInSingularForm, parameterType.toRef())
|
||||||
)
|
)
|
||||||
|
|
||||||
addMultipleParameterType = DummyJavaClassType(JavaClasses.Collection, typeArguments = listOf(parameterType)).toRef()
|
val baseType = when (typeName) {
|
||||||
|
in LombokNames.SUPPORTED_GUAVA_COLLECTIONS -> JavaClasses.Iterable
|
||||||
|
else -> JavaClasses.Collection
|
||||||
|
}
|
||||||
|
|
||||||
|
addMultipleParameterType = DummyJavaClassType(baseType, typeArguments = listOf(parameterType)).toRef()
|
||||||
}
|
}
|
||||||
|
|
||||||
in supportedMaps -> {
|
in LombokNames.SUPPORTED_MAPS -> {
|
||||||
val keyType = javaClassifierType.parameterType(0, singular.allowNull) ?: return
|
val keyType = javaClassifierType.parameterType(0, singular.allowNull) ?: return
|
||||||
val valueType = javaClassifierType.parameterType(1, singular.allowNull) ?: return
|
val valueType = javaClassifierType.parameterType(1, singular.allowNull) ?: return
|
||||||
valueParameters = listOf(
|
valueParameters = listOf(
|
||||||
@@ -212,6 +213,23 @@ class BuilderGenerator(session: FirSession) : FirDeclarationGenerationExtension(
|
|||||||
addMultipleParameterType = DummyJavaClassType(JavaClasses.Map, typeArguments = listOf(keyType, valueType)).toRef()
|
addMultipleParameterType = DummyJavaClassType(JavaClasses.Map, typeArguments = listOf(keyType, valueType)).toRef()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
in LombokNames.SUPPORTED_TABLES -> {
|
||||||
|
val rowKeyType = javaClassifierType.parameterType(0, singular.allowNull) ?: return
|
||||||
|
val columnKeyType = javaClassifierType.parameterType(1, singular.allowNull) ?: return
|
||||||
|
val valueType = javaClassifierType.parameterType(2, singular.allowNull) ?: return
|
||||||
|
|
||||||
|
valueParameters = listOf(
|
||||||
|
ConeLombokValueParameter(Name.identifier("rowKey"), rowKeyType.toRef()),
|
||||||
|
ConeLombokValueParameter(Name.identifier("columnKey"), columnKeyType.toRef()),
|
||||||
|
ConeLombokValueParameter(Name.identifier("value"), valueType.toRef()),
|
||||||
|
)
|
||||||
|
|
||||||
|
addMultipleParameterType = DummyJavaClassType(
|
||||||
|
JavaClasses.Table,
|
||||||
|
typeArguments = listOf(rowKeyType, columnKeyType, valueType)
|
||||||
|
).toRef()
|
||||||
|
}
|
||||||
|
|
||||||
else -> return
|
else -> return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,9 +273,6 @@ class BuilderGenerator(session: FirSession) : FirDeclarationGenerationExtension(
|
|||||||
private val String.singularForm: String?
|
private val String.singularForm: String?
|
||||||
get() = StringUtil.unpluralize(this)
|
get() = StringUtil.unpluralize(this)
|
||||||
|
|
||||||
private val LombokConfig.useGuava: Boolean
|
|
||||||
get() = getBoolean("lombok.singular.useGuava") ?: false
|
|
||||||
|
|
||||||
private fun JavaClassifierType.parameterType(index: Int, allowNull: Boolean): JavaType? {
|
private fun JavaClassifierType.parameterType(index: Int, allowNull: Boolean): JavaType? {
|
||||||
val type = typeArguments.getOrNull(index) ?: return null
|
val type = typeArguments.getOrNull(index) ?: return null
|
||||||
return if (allowNull) type.makeNullable() else type.makeNotNullable()
|
return if (allowNull) type.makeNullable() else type.makeNotNullable()
|
||||||
|
|||||||
@@ -7,17 +7,24 @@ package org.jetbrains.kotlin.lombok.k2.java
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.load.java.structure.*
|
import org.jetbrains.kotlin.load.java.structure.*
|
||||||
|
import org.jetbrains.kotlin.lombok.utils.LombokNames
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
object JavaClasses {
|
object JavaClasses {
|
||||||
|
val Iterable = DummyJavaClass("Iterable", javaLangName("Iterable"), numberOfTypeParameters = 1)
|
||||||
val Collection = DummyJavaClass("Collection", javaUtilName("Collection"), numberOfTypeParameters = 1)
|
val Collection = DummyJavaClass("Collection", javaUtilName("Collection"), numberOfTypeParameters = 1)
|
||||||
val Map = DummyJavaClass("Map", javaUtilName("Map"), numberOfTypeParameters = 2)
|
val Map = DummyJavaClass("Map", javaUtilName("Map"), numberOfTypeParameters = 2)
|
||||||
|
val Table = DummyJavaClass("Table", LombokNames.TABLE, numberOfTypeParameters = 3)
|
||||||
|
|
||||||
|
|
||||||
private fun javaUtilName(name: String): FqName {
|
private fun javaUtilName(name: String): FqName {
|
||||||
return FqName.fromSegments(listOf("java", "util", name))
|
return FqName.fromSegments(listOf("java", "util", name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun javaLangName(name: String): FqName {
|
||||||
|
return FqName.fromSegments(listOf("java", "lang", name))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DummyJavaClass(name: String, override val fqName: FqName, numberOfTypeParameters: Int) : JavaClass {
|
class DummyJavaClass(name: String, override val fqName: FqName, numberOfTypeParameters: Int) : JavaClass {
|
||||||
|
|||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
// WITH_GUAVA
|
||||||
|
// WITH_STDLIB
|
||||||
|
// FULL_JDK
|
||||||
|
// FILE: User.java
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Singular;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
@Data
|
||||||
|
public class User {
|
||||||
|
@Singular private com.google.common.collect.ImmutableMap<String, Integer> numbers;
|
||||||
|
@Singular private com.google.common.collect.ImmutableList<String> statuses;
|
||||||
|
@Singular private com.google.common.collect.ImmutableTable<String, String, String> values;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Other.java
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Singular;
|
||||||
|
|
||||||
|
@Builder(setterPrefix = "with")
|
||||||
|
@Data
|
||||||
|
public class Other {
|
||||||
|
@Singular("singleSome") private java.util.List<Integer> some;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
import com.google.common.collect.ImmutableTable
|
||||||
|
import com.google.common.collect.HashBasedTable
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val userBuilder = User.builder()
|
||||||
|
.status("wrong")
|
||||||
|
.clearStatuses()
|
||||||
|
.status("hello")
|
||||||
|
.statuses(listOf("world", "!"))
|
||||||
|
.number("1", 1)
|
||||||
|
.numbers(mapOf("2" to 2, "3" to 3))
|
||||||
|
.value("1", "a", "hello")
|
||||||
|
.values(ImmutableTable.of("2", "b", "world"))
|
||||||
|
|
||||||
|
val user = userBuilder.build()
|
||||||
|
|
||||||
|
val outer = Other.builder()
|
||||||
|
.withSingleSome(1)
|
||||||
|
.withSome(listOf(2, 3))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val expectedNumbers = mapOf("1" to 1, "2" to 2, "3" to 3)
|
||||||
|
val expectedStatuses = listOf("hello", "world", "!")
|
||||||
|
val expectedSome = listOf(1, 2, 3)
|
||||||
|
val expectedValues = HashBasedTable.create<String, String, String>().apply {
|
||||||
|
put("1", "a", "hello")
|
||||||
|
put("2", "b", "world")
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (
|
||||||
|
user.numbers == expectedNumbers &&
|
||||||
|
user.statuses == expectedStatuses &&
|
||||||
|
user.values == expectedValues &&
|
||||||
|
outer.some == expectedSome
|
||||||
|
) {
|
||||||
|
"OK"
|
||||||
|
} else {
|
||||||
|
"Error: $user"
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+6
@@ -55,6 +55,12 @@ public class BlackBoxCodegenTestForLombokGenerated extends AbstractBlackBoxCodeg
|
|||||||
runTest("plugins/lombok/testData/box/builder.kt");
|
runTest("plugins/lombok/testData/box/builder.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("builderGuava.kt")
|
||||||
|
public void testBuilderGuava() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/builderGuava.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("builderSingular.kt")
|
@TestMetadata("builderSingular.kt")
|
||||||
public void testBuilderSingular() throws Exception {
|
public void testBuilderSingular() throws Exception {
|
||||||
|
|||||||
Generated
+6
@@ -55,6 +55,12 @@ public class FirBlackBoxCodegenTestForLombokGenerated extends AbstractFirBlackBo
|
|||||||
runTest("plugins/lombok/testData/box/builder.kt");
|
runTest("plugins/lombok/testData/box/builder.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("builderGuava.kt")
|
||||||
|
public void testBuilderGuava() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/builderGuava.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("builderSingular.kt")
|
@TestMetadata("builderSingular.kt")
|
||||||
public void testBuilderSingular() throws Exception {
|
public void testBuilderSingular() throws Exception {
|
||||||
|
|||||||
Generated
+6
@@ -55,6 +55,12 @@ public class IrBlackBoxCodegenTestForLombokGenerated extends AbstractIrBlackBoxC
|
|||||||
runTest("plugins/lombok/testData/box/builder.kt");
|
runTest("plugins/lombok/testData/box/builder.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("builderGuava.kt")
|
||||||
|
public void testBuilderGuava() throws Exception {
|
||||||
|
runTest("plugins/lombok/testData/box/builderGuava.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("builderSingular.kt")
|
@TestMetadata("builderSingular.kt")
|
||||||
public void testBuilderSingular() throws Exception {
|
public void testBuilderSingular() throws Exception {
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.lombok
|
||||||
|
|
||||||
|
import lombok.Getter
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoot
|
||||||
|
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar.ExtensionStorage
|
||||||
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
|
import org.jetbrains.kotlin.lombok.LombokDirectives.WITH_GUAVA
|
||||||
|
import org.jetbrains.kotlin.lombok.LombokEnvironmentConfigurator.Companion.GUAVA_JAR
|
||||||
|
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
|
||||||
|
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
|
||||||
|
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
|
||||||
|
import org.jetbrains.kotlin.test.model.TestFile
|
||||||
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
|
import org.jetbrains.kotlin.test.services.*
|
||||||
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class LombokAdditionalSourceFileProvider(testServices: TestServices) : AdditionalSourceProvider(testServices) {
|
||||||
|
companion object {
|
||||||
|
const val COMMON_SOURCE_PATH = "plugins/lombok/testData/common.kt"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun produceAdditionalFiles(globalDirectives: RegisteredDirectives, module: TestModule): List<TestFile> {
|
||||||
|
return listOf(File(COMMON_SOURCE_PATH).toTestFile())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LombokEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) {
|
||||||
|
companion object {
|
||||||
|
const val LOMBOK_CONFIG_NAME = "lombok.config"
|
||||||
|
private const val guavaPropertyName = "org.jetbrains.kotlin.test.guava-location"
|
||||||
|
|
||||||
|
val GUAVA_JAR: File
|
||||||
|
get() = EnvironmentBasedStandardLibrariesPathProvider.getFile(guavaPropertyName)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val directiveContainers: List<DirectivesContainer>
|
||||||
|
get() = listOf(LombokDirectives)
|
||||||
|
|
||||||
|
override fun configureCompilerConfiguration(configuration: CompilerConfiguration, module: TestModule) {
|
||||||
|
configuration.addJvmClasspathRoot(PathUtil.getResourcePathForClass(Getter::class.java))
|
||||||
|
if (WITH_GUAVA in module.directives) {
|
||||||
|
configuration.addJvmClasspathRoot(GUAVA_JAR)
|
||||||
|
}
|
||||||
|
|
||||||
|
val lombokConfig = findLombokConfig(module) ?: return
|
||||||
|
lombokConfig.copyTo(testServices.sourceFileProvider.javaSourceDirectory.resolve(lombokConfig.name))
|
||||||
|
configuration.put(LombokConfigurationKeys.CONFIG_FILE, lombokConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findLombokConfig(module: TestModule): File? {
|
||||||
|
return module.files.singleOrNull { it.name == LOMBOK_CONFIG_NAME }?.let {
|
||||||
|
testServices.sourceFileProvider.getRealFileForSourceFile(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ExtensionStorage.registerCompilerExtensions(module: TestModule, configuration: CompilerConfiguration) {
|
||||||
|
LombokComponentRegistrar.registerComponents(this, configuration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LombokRuntimeClassPathProvider(testServices: TestServices) : RuntimeClasspathProvider(testServices) {
|
||||||
|
override fun runtimeClassPaths(module: TestModule): List<File> {
|
||||||
|
return if (WITH_GUAVA in module.directives) {
|
||||||
|
listOf(GUAVA_JAR)
|
||||||
|
} else {
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object LombokDirectives : SimpleDirectivesContainer() {
|
||||||
|
val WITH_GUAVA by directive("Add guava to classpath")
|
||||||
|
}
|
||||||
@@ -5,26 +5,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.lombok
|
package org.jetbrains.kotlin.lombok
|
||||||
|
|
||||||
import lombok.Getter
|
|
||||||
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoot
|
|
||||||
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar.ExtensionStorage
|
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
|
||||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||||
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
|
|
||||||
import org.jetbrains.kotlin.test.model.TestFile
|
|
||||||
import org.jetbrains.kotlin.test.model.TestModule
|
|
||||||
import org.jetbrains.kotlin.test.runners.AbstractDiagnosticTest
|
import org.jetbrains.kotlin.test.runners.AbstractDiagnosticTest
|
||||||
import org.jetbrains.kotlin.test.runners.AbstractFirDiagnosticTest
|
import org.jetbrains.kotlin.test.runners.AbstractFirDiagnosticTest
|
||||||
import org.jetbrains.kotlin.test.runners.codegen.AbstractBlackBoxCodegenTest
|
import org.jetbrains.kotlin.test.runners.codegen.AbstractBlackBoxCodegenTest
|
||||||
import org.jetbrains.kotlin.test.runners.codegen.AbstractFirBlackBoxCodegenTest
|
import org.jetbrains.kotlin.test.runners.codegen.AbstractFirBlackBoxCodegenTest
|
||||||
import org.jetbrains.kotlin.test.runners.codegen.AbstractIrBlackBoxCodegenTest
|
import org.jetbrains.kotlin.test.runners.codegen.AbstractIrBlackBoxCodegenTest
|
||||||
import org.jetbrains.kotlin.test.runners.configurationForClassicAndFirTestsAlongside
|
import org.jetbrains.kotlin.test.runners.configurationForClassicAndFirTestsAlongside
|
||||||
import org.jetbrains.kotlin.test.services.AdditionalSourceProvider
|
|
||||||
import org.jetbrains.kotlin.test.services.EnvironmentConfigurator
|
|
||||||
import org.jetbrains.kotlin.test.services.TestServices
|
|
||||||
import org.jetbrains.kotlin.test.services.sourceFileProvider
|
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
// ---------------------------- box ----------------------------
|
// ---------------------------- box ----------------------------
|
||||||
|
|
||||||
@@ -71,38 +58,5 @@ open class AbstractFirDiagnosticTestForLombok : AbstractFirDiagnosticTest() {
|
|||||||
fun TestConfigurationBuilder.enableLombok() {
|
fun TestConfigurationBuilder.enableLombok() {
|
||||||
useConfigurators(::LombokEnvironmentConfigurator)
|
useConfigurators(::LombokEnvironmentConfigurator)
|
||||||
useAdditionalSourceProviders(::LombokAdditionalSourceFileProvider)
|
useAdditionalSourceProviders(::LombokAdditionalSourceFileProvider)
|
||||||
}
|
useCustomRuntimeClasspathProviders(::LombokRuntimeClassPathProvider)
|
||||||
|
|
||||||
class LombokAdditionalSourceFileProvider(testServices: TestServices) : AdditionalSourceProvider(testServices) {
|
|
||||||
companion object {
|
|
||||||
const val COMMON_SOURCE_PATH = "plugins/lombok/testData/common.kt"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun produceAdditionalFiles(globalDirectives: RegisteredDirectives, module: TestModule): List<TestFile> {
|
|
||||||
return listOf(File(COMMON_SOURCE_PATH).toTestFile())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class LombokEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) {
|
|
||||||
companion object {
|
|
||||||
const val LOMBOK_CONFIG_NAME = "lombok.config"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun configureCompilerConfiguration(configuration: CompilerConfiguration, module: TestModule) {
|
|
||||||
configuration.addJvmClasspathRoot(PathUtil.getResourcePathForClass(Getter::class.java))
|
|
||||||
|
|
||||||
val lombokConfig = findLombokConfig(module) ?: return
|
|
||||||
lombokConfig.copyTo(testServices.sourceFileProvider.javaSourceDirectory.resolve(lombokConfig.name))
|
|
||||||
configuration.put(LombokConfigurationKeys.CONFIG_FILE, lombokConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findLombokConfig(module: TestModule): File? {
|
|
||||||
return module.files.singleOrNull { it.name == LOMBOK_CONFIG_NAME }?.let {
|
|
||||||
testServices.sourceFileProvider.getRealFileForSourceFile(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun ExtensionStorage.registerCompilerExtensions(module: TestModule, configuration: CompilerConfiguration) {
|
|
||||||
LombokComponentRegistrar.registerComponents(this, configuration)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user