diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt index 874965240ca..c10665359da 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt @@ -292,7 +292,7 @@ abstract class LazyJavaScope( } private fun resolveProperty(field: JavaField): PropertyDescriptor { - val propertyDescriptor = createPropertyDescriptor(field) + var propertyDescriptor = createPropertyDescriptor(field) // Annotations on Java fields are loaded as property annotations, therefore backingField = null below propertyDescriptor.initialize(null, null, null, null) @@ -305,6 +305,9 @@ abstract class LazyJavaScope( null, emptyList() ) + (ownerDescriptor as? ClassDescriptor)?.let { classDescriptor -> + propertyDescriptor = with(c) { c.components.syntheticPartsProvider.modifyField(classDescriptor, propertyDescriptor) } + } if (DescriptorUtils.shouldRecordInitializerForProperty(propertyDescriptor, propertyDescriptor.type)) { propertyDescriptor.setCompileTimeInitializerFactory { diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/resolve/jvm/SyntheticJavaPartsProvider.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/resolve/jvm/SyntheticJavaPartsProvider.kt index 0eb241bd617..e2a7ec38b6b 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/resolve/jvm/SyntheticJavaPartsProvider.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/resolve/jvm/SyntheticJavaPartsProvider.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve.jvm import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor +import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext import org.jetbrains.kotlin.name.Name @@ -45,6 +46,9 @@ interface SyntheticJavaPartsProvider { context(LazyJavaResolverContext) fun generateNestedClass(thisDescriptor: ClassDescriptor, name: Name, result: MutableList) + + context(LazyJavaResolverContext) + fun modifyField(thisDescriptor: ClassDescriptor, propertyDescriptor: PropertyDescriptorImpl): PropertyDescriptorImpl } @Suppress("IncorrectFormatting") // KTIJ-22227 @@ -86,4 +90,12 @@ class CompositeSyntheticJavaPartsProvider(private val inner: List) { inner.forEach { it.generateNestedClass(thisDescriptor, name, result) } } + + context(LazyJavaResolverContext) + override fun modifyField( + thisDescriptor: ClassDescriptor, + propertyDescriptor: PropertyDescriptorImpl + ): PropertyDescriptorImpl { + return inner.fold(propertyDescriptor) { property, provider -> provider.modifyField(thisDescriptor, property) } + } } diff --git a/plugins/lombok/lombok.common/src/org/jetbrains/kotlin/lombok/utils/LombokNames.kt b/plugins/lombok/lombok.common/src/org/jetbrains/kotlin/lombok/utils/LombokNames.kt index 83e4b6e5892..7a8342f116f 100644 --- a/plugins/lombok/lombok.common/src/org/jetbrains/kotlin/lombok/utils/LombokNames.kt +++ b/plugins/lombok/lombok.common/src/org/jetbrains/kotlin/lombok/utils/LombokNames.kt @@ -16,6 +16,7 @@ object LombokNames { val WITH = FqName("lombok.With") val DATA = FqName("lombok.Data") val VALUE = FqName("lombok.Value") + val PACKAGE_PRIVATE = FqName("lombok.PackagePrivate") val NO_ARGS_CONSTRUCTOR = FqName("lombok.NoArgsConstructor") val ALL_ARGS_CONSTRUCTOR = FqName("lombok.AllArgsConstructor") val REQUIRED_ARGS_CONSTRUCTOR = FqName("lombok.RequiredArgsConstructor") diff --git a/plugins/lombok/lombok.k1/src/org/jetbrains/kotlin/lombok/LombokSyntheticJavaPartsProvider.kt b/plugins/lombok/lombok.k1/src/org/jetbrains/kotlin/lombok/LombokSyntheticJavaPartsProvider.kt index 72f690f783e..31d1a7952a7 100644 --- a/plugins/lombok/lombok.k1/src/org/jetbrains/kotlin/lombok/LombokSyntheticJavaPartsProvider.kt +++ b/plugins/lombok/lombok.k1/src/org/jetbrains/kotlin/lombok/LombokSyntheticJavaPartsProvider.kt @@ -5,16 +5,13 @@ package org.jetbrains.kotlin.lombok -import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor import org.jetbrains.kotlin.load.java.lazy.descriptors.SyntheticJavaClassDescriptor import org.jetbrains.kotlin.lombok.config.LombokConfig import org.jetbrains.kotlin.lombok.processor.* -import org.jetbrains.kotlin.lombok.utils.getJavaClass import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.jvm.SyntheticJavaPartsProvider import java.util.* @@ -36,6 +33,8 @@ class LombokSyntheticJavaPartsProvider(config: LombokConfig) : SyntheticJavaPart BuilderProcessor(config) ) + private val valueFieldModifier = ValueFieldModifier(config) + /** * kotlin resolve references in two calls - first it gets names, then actual member descriptor * but for us it is much easier to run full generation for class once @@ -102,6 +101,14 @@ class LombokSyntheticJavaPartsProvider(config: LombokConfig) : SyntheticJavaPart return builder.build() } + context(LazyJavaResolverContext) + override fun modifyField( + thisDescriptor: ClassDescriptor, + propertyDescriptor: PropertyDescriptorImpl + ): PropertyDescriptorImpl { + return valueFieldModifier.modifyField(thisDescriptor, propertyDescriptor) ?: propertyDescriptor + } + /** * Deduplicates generated functions using name and argument counts, as lombok does */ @@ -113,9 +120,7 @@ class LombokSyntheticJavaPartsProvider(config: LombokConfig) : SyntheticJavaPart } } - companion object { - /** * 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 diff --git a/plugins/lombok/lombok.k1/src/org/jetbrains/kotlin/lombok/processor/ValueFieldModifier.kt b/plugins/lombok/lombok.k1/src/org/jetbrains/kotlin/lombok/processor/ValueFieldModifier.kt new file mode 100644 index 00000000000..bf12964edcc --- /dev/null +++ b/plugins/lombok/lombok.k1/src/org/jetbrains/kotlin/lombok/processor/ValueFieldModifier.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2023 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.processor + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl +import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities +import org.jetbrains.kotlin.lombok.config.LombokAnnotations +import org.jetbrains.kotlin.lombok.config.LombokConfig + +class ValueFieldModifier(val config: LombokConfig) { + fun modifyField(thisDescriptor: ClassDescriptor, propertyDescriptor: PropertyDescriptorImpl): PropertyDescriptorImpl? { + // Explicit visibility + if (propertyDescriptor.visibility != JavaDescriptorVisibilities.PACKAGE_VISIBILITY) return null + if (LombokAnnotations.Value.getOrNull(thisDescriptor) == null) return null + return propertyDescriptor.newCopyBuilder().apply { + setVisibility(DescriptorVisibilities.PRIVATE) + }.build() as? PropertyDescriptorImpl + } +} diff --git a/plugins/lombok/testData/box/valueFieldAccess.kt b/plugins/lombok/testData/box/valueFieldAccess.kt new file mode 100644 index 00000000000..2961946a017 --- /dev/null +++ b/plugins/lombok/testData/box/valueFieldAccess.kt @@ -0,0 +1,18 @@ +// IGNORE_BACKEND_K2: JVM_IR +// ISSUE: KT-51092 +// FILE: MyValue.java +import lombok.Value; + +@Value +public class MyValue { + String defaultValue; + private String privateValue; + public String publicValue; +} + +// FILE: main.kt +fun box(): String { + val x = MyValue("A", "B", "C") + val result = x.defaultValue + x.privateValue + x.publicValue; + return if (result == "ABC") "OK" else "Error: $x" +} diff --git a/plugins/lombok/tests-gen/org/jetbrains/kotlin/lombok/BlackBoxCodegenTestForLombokGenerated.java b/plugins/lombok/tests-gen/org/jetbrains/kotlin/lombok/BlackBoxCodegenTestForLombokGenerated.java index aabca0c5054..da83017f772 100644 --- a/plugins/lombok/tests-gen/org/jetbrains/kotlin/lombok/BlackBoxCodegenTestForLombokGenerated.java +++ b/plugins/lombok/tests-gen/org/jetbrains/kotlin/lombok/BlackBoxCodegenTestForLombokGenerated.java @@ -187,6 +187,12 @@ public class BlackBoxCodegenTestForLombokGenerated extends AbstractBlackBoxCodeg runTest("plugins/lombok/testData/box/value.kt"); } + @Test + @TestMetadata("valueFieldAccess.kt") + public void testValueFieldAccess() throws Exception { + runTest("plugins/lombok/testData/box/valueFieldAccess.kt"); + } + @Test @TestMetadata("with.kt") public void testWith() throws Exception { diff --git a/plugins/lombok/tests-gen/org/jetbrains/kotlin/lombok/FirBlackBoxCodegenTestForLombokGenerated.java b/plugins/lombok/tests-gen/org/jetbrains/kotlin/lombok/FirBlackBoxCodegenTestForLombokGenerated.java index bf8e5e2d462..bfdfe1bf61f 100644 --- a/plugins/lombok/tests-gen/org/jetbrains/kotlin/lombok/FirBlackBoxCodegenTestForLombokGenerated.java +++ b/plugins/lombok/tests-gen/org/jetbrains/kotlin/lombok/FirBlackBoxCodegenTestForLombokGenerated.java @@ -187,6 +187,12 @@ public class FirBlackBoxCodegenTestForLombokGenerated extends AbstractFirBlackBo runTest("plugins/lombok/testData/box/value.kt"); } + @Test + @TestMetadata("valueFieldAccess.kt") + public void testValueFieldAccess() throws Exception { + runTest("plugins/lombok/testData/box/valueFieldAccess.kt"); + } + @Test @TestMetadata("with.kt") public void testWith() throws Exception { diff --git a/plugins/lombok/tests-gen/org/jetbrains/kotlin/lombok/IrBlackBoxCodegenTestForLombokGenerated.java b/plugins/lombok/tests-gen/org/jetbrains/kotlin/lombok/IrBlackBoxCodegenTestForLombokGenerated.java index 22873da3908..6217f1c8a7a 100644 --- a/plugins/lombok/tests-gen/org/jetbrains/kotlin/lombok/IrBlackBoxCodegenTestForLombokGenerated.java +++ b/plugins/lombok/tests-gen/org/jetbrains/kotlin/lombok/IrBlackBoxCodegenTestForLombokGenerated.java @@ -187,6 +187,12 @@ public class IrBlackBoxCodegenTestForLombokGenerated extends AbstractIrBlackBoxC runTest("plugins/lombok/testData/box/value.kt"); } + @Test + @TestMetadata("valueFieldAccess.kt") + public void testValueFieldAccess() throws Exception { + runTest("plugins/lombok/testData/box/valueFieldAccess.kt"); + } + @Test @TestMetadata("with.kt") public void testWith() throws Exception {