FIR/LC: create synthetic members of enum class

^KTIJ-17414 In Progress
^KTIJ-17444 In Progress
This commit is contained in:
Jinseong Jeon
2022-02-12 01:16:37 -08:00
committed by Ilya Kirillov
parent 790f2d13ae
commit 1b6ded6005
13 changed files with 133 additions and 10 deletions
@@ -96,8 +96,10 @@ internal open class FirLightClassForSymbol(
val declaredMemberScope = classOrObjectSymbol.getDeclaredMemberScope() val declaredMemberScope = classOrObjectSymbol.getDeclaredMemberScope()
val visibleDeclarations = declaredMemberScope.getCallableSymbols().applyIf(isEnum) { 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 -> filterNot { function ->
function is KtFunctionSymbol && function is KtFunctionSymbol && function.origin == KtSymbolOrigin.SOURCE_MEMBER_GENERATED &&
(function.name == ENUM_VALUES || function.name == ENUM_VALUE_OF) (function.name == ENUM_VALUES || function.name == ENUM_VALUE_OF)
} }
}.applyIf(classOrObjectSymbol.isObject) { }.applyIf(classOrObjectSymbol.isObject) {
@@ -120,6 +122,7 @@ internal open class FirLightClassForSymbol(
addMethodsFromCompanionIfNeeded(result) addMethodsFromCompanionIfNeeded(result)
addMethodsFromEnumClass(result)
addMethodsFromDataClass(result) addMethodsFromDataClass(result)
addDelegatesToInterfaceMethods(result) addDelegatesToInterfaceMethods(result)
@@ -137,6 +140,19 @@ internal open class FirLightClassForSymbol(
} }
} }
private fun addMethodsFromEnumClass(result: MutableList<KtLightMethod>) {
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<KtFunctionSymbol>()
createMethods(valuesAndValueOfFunctions, result)
}
}
private fun addMethodsFromDataClass(result: MutableList<KtLightMethod>) { private fun addMethodsFromDataClass(result: MutableList<KtLightMethod>) {
if (!classOrObjectSymbol.isData) return if (!classOrObjectSymbol.isData) return
@@ -31,7 +31,7 @@ internal abstract class FirLightParameterBaseForSymbol(
protected val nullabilityType: NullabilityType protected val nullabilityType: NullabilityType
get() { get() {
val nullabilityApplicable = !containingMethod.containingClass.let { it.isAnnotationType || it.isEnum } && val nullabilityApplicable = !containingMethod.containingClass.let { it.isAnnotationType } &&
!containingMethod.hasModifierProperty(PsiModifier.PRIVATE) !containingMethod.hasModifierProperty(PsiModifier.PRIVATE)
return if (nullabilityApplicable) { return if (nullabilityApplicable) {
@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.StandardNames 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.JvmCodegenUtil
import org.jetbrains.kotlin.codegen.kotlinType import org.jetbrains.kotlin.codegen.kotlinType
import org.jetbrains.kotlin.config.JvmAnalysisFlags 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.annotations.argumentValue
import org.jetbrains.kotlin.resolve.constants.EnumValue import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind 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.KotlinType
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
@@ -312,6 +315,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
} }
} }
addMethodsFromEnumClass(result)
addMethodsFromDataClass(result) addMethodsFromDataClass(result)
addDelegatesToInterfaceMethods(result) addDelegatesToInterfaceMethods(result)
@@ -337,9 +341,29 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
}, false }, false
) )
private fun addMethodsFromDataClass(result: MutableList<KtLightMethod>) { private fun addMethodsFromEnumClass(result: MutableList<KtLightMethod>) {
if (!classOrObject.hasModifier(DATA_KEYWORD)) return
val ktClass = classOrObject as? KtClass ?: return 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<KtLightMethod>) {
val ktClass = classOrObject as? KtClass ?: return
if (!ktClass.isData()) return
val descriptor = classOrObject.resolve() as? ClassDescriptor ?: return val descriptor = classOrObject.resolve() as? ClassDescriptor ?: return
val bindingContext = classOrObject.analyze() val bindingContext = classOrObject.analyze()
@@ -1,6 +1,12 @@
public enum AnnotatedParameterInEnumConstructor /* test.AnnotatedParameterInEnumConstructor*/ { public enum AnnotatedParameterInEnumConstructor /* test.AnnotatedParameterInEnumConstructor*/ {
A; 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) private AnnotatedParameterInEnumConstructor(@test.Anno(x = "a") java.lang.String, @test.Anno(x = "b") java.lang.String);// .ctor(java.lang.String, java.lang.String)
} }
@@ -7,4 +7,5 @@ enum class AnnotatedParameterInEnumConstructor(@Anno("a") a: String, @Anno("b")
A("1", "b") A("1", "b")
} }
// FIR_COMPARISON // FIR_COMPARISON
// SKIP_SANITY_TEST
@@ -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)
}
@@ -3,6 +3,12 @@ public enum E /* p.E*/ {
Entry2, Entry2,
Entry3; 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() private E();// .ctor()
} }
@@ -11,4 +11,5 @@ enum class E {
Entry3 Entry3
} }
// FIR_COMPARISON // FIR_COMPARISON
// SKIP_SANITY_TEST
@@ -0,0 +1,8 @@
public enum E /* p.E*/ {
Entry1,
Entry2,
Entry3;
private E();// .ctor()
}
@@ -1,6 +1,12 @@
public enum EnumNameOverride /* EnumNameOverride*/ implements Bar { 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() private EnumNameOverride();// .ctor()
} }
@@ -10,4 +10,5 @@ interface Bar : Foo {
enum class EnumNameOverride : Bar enum class EnumNameOverride : Bar
// FIR_COMPARISON // FIR_COMPARISON
// SKIP_SANITY_TEST
@@ -4,6 +4,12 @@ public enum Direction /* Direction*/ {
WEST, WEST,
EAST; 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() private Direction();// .ctor()
} }
@@ -15,6 +21,12 @@ public enum Color /* Color*/ {
private final int rgb; 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(int);// .ctor(int)
private Color(java.lang.String);// .ctor(java.lang.String) private Color(java.lang.String);// .ctor(java.lang.String)
@@ -42,6 +54,12 @@ public enum ProtocolState /* ProtocolState*/ {
@org.jetbrains.annotations.NotNull() @org.jetbrains.annotations.NotNull()
public abstract ProtocolState signal();// signal() 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() private ProtocolState();// .ctor()
} }
@@ -79,6 +97,12 @@ public enum IntArithmetics /* IntArithmetics*/ {
@org.jetbrains.annotations.NotNull() @org.jetbrains.annotations.NotNull()
public IntArithmetics applyAsInt(int, int);// applyAsInt(int, int) 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() private IntArithmetics();// .ctor()
} }
+24
View File
@@ -4,6 +4,12 @@ public enum Direction /* Direction*/ {
WEST, WEST,
EAST; 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() private Direction();// .ctor()
} }
@@ -15,6 +21,12 @@ public enum Color /* Color*/ {
private final int rgb; 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(@org.jetbrains.annotations.NotNull() java.lang.String);// .ctor(java.lang.String)
private Color(int);// .ctor(int) private Color(int);// .ctor(int)
@@ -42,6 +54,12 @@ public enum ProtocolState /* ProtocolState*/ {
@org.jetbrains.annotations.NotNull() @org.jetbrains.annotations.NotNull()
public abstract ProtocolState signal();// signal() 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() 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() private IntArithmetics();// .ctor()
public int applyAsInt(int, int);// applyAsInt(int, int) public int applyAsInt(int, int);// applyAsInt(int, int)