diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassForSymbol.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassForSymbol.kt index ab5e626c5d4..8bda180b4ee 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassForSymbol.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/FirLightClassForSymbol.kt @@ -96,8 +96,10 @@ internal open class FirLightClassForSymbol( val declaredMemberScope = classOrObjectSymbol.getDeclaredMemberScope() val visibleDeclarations = declaredMemberScope.getCallableSymbols().applyIf(isEnum) { + // Technically, synthetic members of `enum` class, such as `values` or `valueOf`, are visible. + // They're just needed to be added later (to be in a backward-compatible order of members). filterNot { function -> - function is KtFunctionSymbol && + function is KtFunctionSymbol && function.origin == KtSymbolOrigin.SOURCE_MEMBER_GENERATED && (function.name == ENUM_VALUES || function.name == ENUM_VALUE_OF) } }.applyIf(classOrObjectSymbol.isObject) { @@ -120,6 +122,7 @@ internal open class FirLightClassForSymbol( addMethodsFromCompanionIfNeeded(result) + addMethodsFromEnumClass(result) addMethodsFromDataClass(result) addDelegatesToInterfaceMethods(result) @@ -137,6 +140,19 @@ internal open class FirLightClassForSymbol( } } + private fun addMethodsFromEnumClass(result: MutableList) { + if (!isEnum) return + + analyzeWithSymbolAsContext(classOrObjectSymbol) { + val valuesAndValueOfFunctions = classOrObjectSymbol.getDeclaredMemberScope() + .getCallableSymbols { name -> name == ENUM_VALUES || name == ENUM_VALUE_OF } + .filter { it.origin == KtSymbolOrigin.SOURCE_MEMBER_GENERATED } + .filterIsInstance() + + createMethods(valuesAndValueOfFunctions, result) + } + } + private fun addMethodsFromDataClass(result: MutableList) { if (!classOrObjectSymbol.isData) return diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterBaseForSymbol.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterBaseForSymbol.kt index 7be188eb988..fb7a106619b 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterBaseForSymbol.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterBaseForSymbol.kt @@ -31,7 +31,7 @@ internal abstract class FirLightParameterBaseForSymbol( protected val nullabilityType: NullabilityType get() { - val nullabilityApplicable = !containingMethod.containingClass.let { it.isAnnotationType || it.isEnum } && + val nullabilityApplicable = !containingMethod.containingClass.let { it.isAnnotationType } && !containingMethod.hasModifierProperty(PsiModifier.PRIVATE) return if (nullabilityApplicable) { diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt index 0ef9d5d6796..111edfd589e 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt @@ -23,6 +23,8 @@ import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.builtins.StandardNames.ENUM_VALUES +import org.jetbrains.kotlin.builtins.StandardNames.ENUM_VALUE_OF import org.jetbrains.kotlin.codegen.JvmCodegenUtil import org.jetbrains.kotlin.codegen.kotlinType import org.jetbrains.kotlin.config.JvmAnalysisFlags @@ -45,6 +47,7 @@ import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.annotations.argumentValue import org.jetbrains.kotlin.resolve.constants.EnumValue import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind +import org.jetbrains.kotlin.resolve.scopes.findFirstFunction import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny @@ -312,6 +315,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor } } + addMethodsFromEnumClass(result) addMethodsFromDataClass(result) addDelegatesToInterfaceMethods(result) @@ -337,9 +341,29 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor }, false ) - private fun addMethodsFromDataClass(result: MutableList) { - if (!classOrObject.hasModifier(DATA_KEYWORD)) return + private fun addMethodsFromEnumClass(result: MutableList) { val ktClass = classOrObject as? KtClass ?: return + if (!ktClass.isEnum()) return + val descriptor = classOrObject.resolve() as? ClassDescriptor ?: return + + val valuesFunction = descriptor.staticScope.findFirstFunction(ENUM_VALUES.identifier) { + it.dispatchReceiverParameter == null && + it.extensionReceiverParameter == null && + it.valueParameters.size == 0 + } + result.add(createGeneratedMethodFromDescriptor(valuesFunction, JvmDeclarationOriginKind.SYNTHETIC)) + + val valueOfFunction = descriptor.staticScope.findFirstFunction(ENUM_VALUE_OF.identifier) { + it.dispatchReceiverParameter == null && + it.extensionReceiverParameter == null && + it.valueParameters.size == 1 + } + result.add(createGeneratedMethodFromDescriptor(valueOfFunction, JvmDeclarationOriginKind.SYNTHETIC)) + } + + private fun addMethodsFromDataClass(result: MutableList) { + val ktClass = classOrObject as? KtClass ?: return + if (!ktClass.isData()) return val descriptor = classOrObject.resolve() as? ClassDescriptor ?: return val bindingContext = classOrObject.analyze() diff --git a/compiler/testData/asJava/lightClasses/AnnotatedParameterInEnumConstructor.java b/compiler/testData/asJava/lightClasses/AnnotatedParameterInEnumConstructor.java index 38682f8f4a7..4e3243993d3 100644 --- a/compiler/testData/asJava/lightClasses/AnnotatedParameterInEnumConstructor.java +++ b/compiler/testData/asJava/lightClasses/AnnotatedParameterInEnumConstructor.java @@ -1,6 +1,12 @@ public enum AnnotatedParameterInEnumConstructor /* test.AnnotatedParameterInEnumConstructor*/ { A; + @org.jetbrains.annotations.NotNull() + public final test.AnnotatedParameterInEnumConstructor valueOf(@org.jetbrains.annotations.NotNull() java.lang.String);// valueOf(java.lang.String) + + @org.jetbrains.annotations.NotNull() + public final test.AnnotatedParameterInEnumConstructor[] values();// values() + private AnnotatedParameterInEnumConstructor(@test.Anno(x = "a") java.lang.String, @test.Anno(x = "b") java.lang.String);// .ctor(java.lang.String, java.lang.String) -} \ No newline at end of file +} diff --git a/compiler/testData/asJava/lightClasses/AnnotatedParameterInEnumConstructor.kt b/compiler/testData/asJava/lightClasses/AnnotatedParameterInEnumConstructor.kt index 98c92e0a37f..5c8dad9c67a 100644 --- a/compiler/testData/asJava/lightClasses/AnnotatedParameterInEnumConstructor.kt +++ b/compiler/testData/asJava/lightClasses/AnnotatedParameterInEnumConstructor.kt @@ -7,4 +7,5 @@ enum class AnnotatedParameterInEnumConstructor(@Anno("a") a: String, @Anno("b") A("1", "b") } -// FIR_COMPARISON \ No newline at end of file +// FIR_COMPARISON +// SKIP_SANITY_TEST diff --git a/compiler/testData/asJava/lightClasses/AnnotatedParameterInEnumConstructor.lib.java b/compiler/testData/asJava/lightClasses/AnnotatedParameterInEnumConstructor.lib.java new file mode 100644 index 00000000000..dc767b2984d --- /dev/null +++ b/compiler/testData/asJava/lightClasses/AnnotatedParameterInEnumConstructor.lib.java @@ -0,0 +1,6 @@ +public enum AnnotatedParameterInEnumConstructor /* test.AnnotatedParameterInEnumConstructor*/ { + A; + + private AnnotatedParameterInEnumConstructor(@test.Anno(x = "a") java.lang.String, @test.Anno(x = "b") java.lang.String);// .ctor(java.lang.String, java.lang.String) + +} diff --git a/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.java b/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.java index 70d38298344..7ca08f04d36 100644 --- a/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.java +++ b/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.java @@ -3,6 +3,12 @@ public enum E /* p.E*/ { Entry2, Entry3; + @org.jetbrains.annotations.NotNull() + public final p.E valueOf(@org.jetbrains.annotations.NotNull() java.lang.String);// valueOf(java.lang.String) + + @org.jetbrains.annotations.NotNull() + public final p.E[] values();// values() + private E();// .ctor() -} \ No newline at end of file +} diff --git a/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.kt b/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.kt index 66da0e415b5..898767c0a58 100644 --- a/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.kt +++ b/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.kt @@ -11,4 +11,5 @@ enum class E { Entry3 } -// FIR_COMPARISON \ No newline at end of file +// FIR_COMPARISON +// SKIP_SANITY_TEST diff --git a/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.lib.java b/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.lib.java new file mode 100644 index 00000000000..bcaab962ab4 --- /dev/null +++ b/compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.lib.java @@ -0,0 +1,8 @@ +public enum E /* p.E*/ { + Entry1, + Entry2, + Entry3; + + private E();// .ctor() + +} diff --git a/compiler/testData/asJava/lightClasses/compilationErrors/EnumNameOverride.java b/compiler/testData/asJava/lightClasses/compilationErrors/EnumNameOverride.java index bc55d50cd3f..ef848ca66b4 100644 --- a/compiler/testData/asJava/lightClasses/compilationErrors/EnumNameOverride.java +++ b/compiler/testData/asJava/lightClasses/compilationErrors/EnumNameOverride.java @@ -1,6 +1,12 @@ public enum EnumNameOverride /* EnumNameOverride*/ implements Bar { ; + @org.jetbrains.annotations.NotNull() + public final EnumNameOverride valueOf(@org.jetbrains.annotations.NotNull() java.lang.String);// valueOf(java.lang.String) + + @org.jetbrains.annotations.NotNull() + public final EnumNameOverride[] values();// values() + private EnumNameOverride();// .ctor() -} \ No newline at end of file +} diff --git a/compiler/testData/asJava/lightClasses/compilationErrors/EnumNameOverride.kt b/compiler/testData/asJava/lightClasses/compilationErrors/EnumNameOverride.kt index ed136384d39..780adac9b7e 100644 --- a/compiler/testData/asJava/lightClasses/compilationErrors/EnumNameOverride.kt +++ b/compiler/testData/asJava/lightClasses/compilationErrors/EnumNameOverride.kt @@ -10,4 +10,5 @@ interface Bar : Foo { enum class EnumNameOverride : Bar -// FIR_COMPARISON \ No newline at end of file +// FIR_COMPARISON +// SKIP_SANITY_TEST diff --git a/compiler/testData/asJava/ultraLightClasses/enums.fir.java b/compiler/testData/asJava/ultraLightClasses/enums.fir.java index f4cd5c7836c..6ad1126c4a3 100644 --- a/compiler/testData/asJava/ultraLightClasses/enums.fir.java +++ b/compiler/testData/asJava/ultraLightClasses/enums.fir.java @@ -4,6 +4,12 @@ public enum Direction /* Direction*/ { WEST, EAST; + @org.jetbrains.annotations.NotNull() + public final Direction valueOf(@org.jetbrains.annotations.NotNull() java.lang.String);// valueOf(java.lang.String) + + @org.jetbrains.annotations.NotNull() + public final Direction[] values();// values() + private Direction();// .ctor() } @@ -15,6 +21,12 @@ public enum Color /* Color*/ { private final int rgb; + @org.jetbrains.annotations.NotNull() + public final Color valueOf(@org.jetbrains.annotations.NotNull() java.lang.String);// valueOf(java.lang.String) + + @org.jetbrains.annotations.NotNull() + public final Color[] values();// values() + private Color(int);// .ctor(int) private Color(java.lang.String);// .ctor(java.lang.String) @@ -42,6 +54,12 @@ public enum ProtocolState /* ProtocolState*/ { @org.jetbrains.annotations.NotNull() public abstract ProtocolState signal();// signal() + @org.jetbrains.annotations.NotNull() + public final ProtocolState valueOf(@org.jetbrains.annotations.NotNull() java.lang.String);// valueOf(java.lang.String) + + @org.jetbrains.annotations.NotNull() + public final ProtocolState[] values();// values() + private ProtocolState();// .ctor() } @@ -79,6 +97,12 @@ public enum IntArithmetics /* IntArithmetics*/ { @org.jetbrains.annotations.NotNull() public IntArithmetics applyAsInt(int, int);// applyAsInt(int, int) + @org.jetbrains.annotations.NotNull() + public final IntArithmetics valueOf(@org.jetbrains.annotations.NotNull() java.lang.String);// valueOf(java.lang.String) + + @org.jetbrains.annotations.NotNull() + public final IntArithmetics[] values();// values() + private IntArithmetics();// .ctor() } diff --git a/compiler/testData/asJava/ultraLightClasses/enums.java b/compiler/testData/asJava/ultraLightClasses/enums.java index a9ae6e76277..2dc674c6818 100644 --- a/compiler/testData/asJava/ultraLightClasses/enums.java +++ b/compiler/testData/asJava/ultraLightClasses/enums.java @@ -4,6 +4,12 @@ public enum Direction /* Direction*/ { WEST, EAST; + @org.jetbrains.annotations.NotNull() + public final Direction valueOf(@org.jetbrains.annotations.NotNull() java.lang.String);// valueOf(java.lang.String) + + @org.jetbrains.annotations.NotNull() + public final Direction[] values();// values() + private Direction();// .ctor() } @@ -15,6 +21,12 @@ public enum Color /* Color*/ { private final int rgb; + @org.jetbrains.annotations.NotNull() + public final Color valueOf(@org.jetbrains.annotations.NotNull() java.lang.String);// valueOf(java.lang.String) + + @org.jetbrains.annotations.NotNull() + public final Color[] values();// values() + private Color(@org.jetbrains.annotations.NotNull() java.lang.String);// .ctor(java.lang.String) private Color(int);// .ctor(int) @@ -42,6 +54,12 @@ public enum ProtocolState /* ProtocolState*/ { @org.jetbrains.annotations.NotNull() public abstract ProtocolState signal();// signal() + @org.jetbrains.annotations.NotNull() + public final ProtocolState valueOf(@org.jetbrains.annotations.NotNull() java.lang.String);// valueOf(java.lang.String) + + @org.jetbrains.annotations.NotNull() + public final ProtocolState[] values();// values() + private ProtocolState();// .ctor() @@ -84,6 +102,12 @@ public enum IntArithmetics /* IntArithmetics*/ implements java.util.function.Bin }; + @org.jetbrains.annotations.NotNull() + public final IntArithmetics valueOf(@org.jetbrains.annotations.NotNull() java.lang.String);// valueOf(java.lang.String) + + @org.jetbrains.annotations.NotNull() + public final IntArithmetics[] values();// values() + private IntArithmetics();// .ctor() public int applyAsInt(int, int);// applyAsInt(int, int)