Correct descriptor shape for @JvmRecord annotated classes

This commit adds relevant functions: hashCode, toString, equals
(if the class is not a data class)
And supertype j.l.Record

It only affects descriptor contents, i.e. works for FE

^KT-43677 In Progress
This commit is contained in:
Denis.Zharkov
2020-11-25 18:42:51 +03:00
parent ca2e199b53
commit bef50c0342
12 changed files with 193 additions and 29 deletions
@@ -92,6 +92,7 @@ public class DescriptorResolver {
private final DeclarationReturnTypeSanitizer declarationReturnTypeSanitizer;
private final DataFlowValueFactory dataFlowValueFactory;
private final Iterable<DeclarationSignatureAnonymousTypeTransformer> anonymousTypeTransformers;
private final AdditionalClassPartsProvider additionalClassPartsProvider;
public DescriptorResolver(
@NotNull AnnotationResolver annotationResolver,
@@ -111,7 +112,8 @@ public class DescriptorResolver {
@NotNull TypeApproximator approximator,
@NotNull DeclarationReturnTypeSanitizer declarationReturnTypeSanitizer,
@NotNull DataFlowValueFactory dataFlowValueFactory,
@NotNull Iterable<DeclarationSignatureAnonymousTypeTransformer> anonymousTypeTransformers
@NotNull Iterable<DeclarationSignatureAnonymousTypeTransformer> anonymousTypeTransformers,
@NotNull AdditionalClassPartsProvider additionalClassPartsProvider
) {
this.annotationResolver = annotationResolver;
this.builtIns = builtIns;
@@ -131,6 +133,7 @@ public class DescriptorResolver {
this.declarationReturnTypeSanitizer = declarationReturnTypeSanitizer;
this.dataFlowValueFactory = dataFlowValueFactory;
this.anonymousTypeTransformers = anonymousTypeTransformers;
this.additionalClassPartsProvider = additionalClassPartsProvider;
}
public List<KotlinType> resolveSupertypes(
@@ -156,6 +159,7 @@ public class DescriptorResolver {
}
syntheticResolveExtension.addSyntheticSupertypes(classDescriptor, supertypes);
supertypes.addAll(additionalClassPartsProvider.getAdditionalSupertypes(classDescriptor, supertypes));
if (supertypes.isEmpty()) {
addValidSupertype(supertypes, getDefaultSupertype(classDescriptor));
@@ -19,10 +19,29 @@ object FunctionsFromAny {
val HASH_CODE_METHOD_NAME = Name.identifier("hashCode")
val TO_STRING_METHOD_NAME = Name.identifier("toString")
fun addFunctionFromAnyIfNeeded(
thisDescriptor: ClassDescriptor,
result: MutableCollection<SimpleFunctionDescriptor>,
name: Name,
fromSupertypes: Collection<SimpleFunctionDescriptor>,
) {
if (shouldAddEquals(name, result, fromSupertypes)) {
result.add(createEqualsFunctionDescriptor(thisDescriptor))
}
if (shouldAddHashCode(name, result, fromSupertypes)) {
result.add(createHashCodeFunctionDescriptor(thisDescriptor))
}
if (shouldAddToString(name, result, fromSupertypes)) {
result.add(createToStringFunctionDescriptor(thisDescriptor))
}
}
fun shouldAddEquals(
name: Name,
declaredFunctions: Collection<SimpleFunctionDescriptor>,
fromSupertypes: List<SimpleFunctionDescriptor>
fromSupertypes: Collection<SimpleFunctionDescriptor>
): Boolean {
return name == EQUALS_METHOD_NAME && shouldAddFunctionFromAny(
declaredFunctions,
@@ -36,7 +55,7 @@ object FunctionsFromAny {
fun shouldAddHashCode(
name: Name,
declaredFunctions: Collection<SimpleFunctionDescriptor>,
fromSupertypes: List<SimpleFunctionDescriptor>
fromSupertypes: Collection<SimpleFunctionDescriptor>
): Boolean {
return name == HASH_CODE_METHOD_NAME && shouldAddFunctionFromAny(
declaredFunctions,
@@ -49,7 +68,7 @@ object FunctionsFromAny {
fun shouldAddToString(
name: Name,
declaredFunctions: Collection<SimpleFunctionDescriptor>,
fromSupertypes: List<SimpleFunctionDescriptor>
fromSupertypes: Collection<SimpleFunctionDescriptor>
): Boolean {
return name == TO_STRING_METHOD_NAME && shouldAddFunctionFromAny(
declaredFunctions,
@@ -90,8 +109,8 @@ object FunctionsFromAny {
}
private fun shouldAddFunctionFromAny(
declaredFunctions: Collection <SimpleFunctionDescriptor>,
fromSupertypes: List<SimpleFunctionDescriptor>,
declaredFunctions: Collection<SimpleFunctionDescriptor>,
fromSupertypes: Collection<SimpleFunctionDescriptor>,
checkParameters: (FunctionDescriptor) -> Boolean
): Boolean {
// Add 'equals', 'hashCode', 'toString' iff there is no such declared member AND there is no such final member in supertypes
@@ -47,4 +47,5 @@ interface LazyClassContext {
val wrappedTypeFactory: WrappedTypeFactory
val kotlinTypeChecker: NewKotlinTypeChecker
val samConversionResolver: SamConversionResolver
val additionalClassPartsProvider: AdditionalClassPartsProvider
}
@@ -86,6 +86,8 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
private PlatformDiagnosticSuppressor platformDiagnosticSuppressor;
private SamConversionResolver samConversionResolver;
private AdditionalClassPartsProvider additionalClassPartsProvider;
private final SyntheticResolveExtension syntheticResolveExtension;
private final NewKotlinTypeChecker kotlinTypeChecker;
@@ -157,6 +159,11 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
this.samConversionResolver = samConversionResolver;
}
@Inject
public void setAdditionalClassPartsProvider(@NotNull AdditionalClassPartsProvider additionalClassPartsProvider) {
this.additionalClassPartsProvider = additionalClassPartsProvider;
}
// Only calls from injectors expected
@Deprecated
public ResolveSession(
@@ -500,4 +507,10 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
public SamConversionResolver getSamConversionResolver() {
return samConversionResolver;
}
@NotNull
@Override
public AdditionalClassPartsProvider getAdditionalClassPartsProvider() {
return additionalClassPartsProvider;
}
}
@@ -250,6 +250,9 @@ open class LazyClassMemberScope(
generateDataClassMethods(result, name, location, fromSupertypes)
generateFunctionsFromAnyForInlineClass(result, name, fromSupertypes)
c.syntheticResolveExtension.generateSyntheticMethods(thisDescriptor, name, trace.bindingContext, fromSupertypes, result)
c.additionalClassPartsProvider.generateAdditionalMethods(thisDescriptor, result, name, location, fromSupertypes)
generateFakeOverrides(name, fromSupertypes, result, SimpleFunctionDescriptor::class.java)
}
@@ -259,7 +262,7 @@ open class LazyClassMemberScope(
fromSupertypes: List<SimpleFunctionDescriptor>
) {
if (!thisDescriptor.isInlineClass()) return
addFunctionFromAnyIfNeeded(result, name, fromSupertypes)
FunctionsFromAny.addFunctionFromAnyIfNeeded(thisDescriptor, result, name, fromSupertypes)
}
private fun generateDataClassMethods(
@@ -309,25 +312,7 @@ open class LazyClassMemberScope(
}
if (c.languageVersionSettings.supportsFeature(LanguageFeature.DataClassInheritance)) {
addFunctionFromAnyIfNeeded(result, name, fromSupertypes)
}
}
private fun addFunctionFromAnyIfNeeded(
result: MutableCollection<SimpleFunctionDescriptor>,
name: Name,
fromSupertypes: List<SimpleFunctionDescriptor>
) {
if (FunctionsFromAny.shouldAddEquals(name, result, fromSupertypes)) {
result.add(FunctionsFromAny.createEqualsFunctionDescriptor(thisDescriptor))
}
if (FunctionsFromAny.shouldAddHashCode(name, result, fromSupertypes)) {
result.add(FunctionsFromAny.createHashCodeFunctionDescriptor(thisDescriptor))
}
if (FunctionsFromAny.shouldAddToString(name, result, fromSupertypes)) {
result.add(FunctionsFromAny.createToStringFunctionDescriptor(thisDescriptor))
FunctionsFromAny.addFunctionFromAnyIfNeeded(thisDescriptor, result, name, fromSupertypes)
}
}
@@ -69,7 +69,8 @@ class LocalClassifierAnalyzer(
private val delegationFilter: DelegationFilter,
private val wrappedTypeFactory: WrappedTypeFactory,
private val kotlinTypeChecker: NewKotlinTypeChecker,
private val samConversionResolver: SamConversionResolver
private val samConversionResolver: SamConversionResolver,
private val additionalClassPartsProvider: AdditionalClassPartsProvider,
) {
fun processClassOrObject(
scope: LexicalWritableScope?,
@@ -104,7 +105,8 @@ class LocalClassifierAnalyzer(
delegationFilter,
wrappedTypeFactory,
kotlinTypeChecker,
samConversionResolver
samConversionResolver,
additionalClassPartsProvider,
),
analyzerServices
)
@@ -134,7 +136,8 @@ class LocalClassDescriptorHolder(
val delegationFilter: DelegationFilter,
val wrappedTypeFactory: WrappedTypeFactory,
val kotlinTypeChecker: NewKotlinTypeChecker,
val samConversionResolver: SamConversionResolver
val samConversionResolver: SamConversionResolver,
val additionalClassPartsProvider: AdditionalClassPartsProvider,
) {
// We do not need to synchronize here, because this code is used strictly from one thread
private var classDescriptor: ClassDescriptor? = null
@@ -176,6 +179,8 @@ class LocalClassDescriptorHolder(
override val wrappedTypeFactory: WrappedTypeFactory = this@LocalClassDescriptorHolder.wrappedTypeFactory
override val kotlinTypeChecker: NewKotlinTypeChecker = this@LocalClassDescriptorHolder.kotlinTypeChecker
override val samConversionResolver: SamConversionResolver = this@LocalClassDescriptorHolder.samConversionResolver
override val additionalClassPartsProvider: AdditionalClassPartsProvider =
this@LocalClassDescriptorHolder.additionalClassPartsProvider
},
containingDeclaration,
classOrObject.nameAsSafeName,