Do not create synthesized equals/hashCode/toString in data classes in compatibility mode

To simplify migration from 1.0 to 1.1, do not allow data classes to
automatically implement abstract equals/hashCode/toString declared in
super-interfaces (KT-11306) if "-language-version 1.0" is specified
This commit is contained in:
Alexander Udalov
2016-10-03 11:46:48 +03:00
parent 597912824b
commit 73652f309f
10 changed files with 122 additions and 36 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.resolve.lazy
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker
import org.jetbrains.kotlin.incremental.components.LookupTracker
@@ -36,4 +37,5 @@ interface LazyClassContext {
val annotationResolver: AnnotationResolver
val lookupTracker: LookupTracker
val supertypeLoopChecker: SupertypeLoopChecker
val languageVersionSettings: LanguageVersionSettings
}
@@ -24,6 +24,7 @@ import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.ReadOnly;
import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.context.GlobalContext;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
@@ -48,7 +49,6 @@ import org.jetbrains.kotlin.storage.*;
import org.jetbrains.kotlin.utils.SmartList;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -79,6 +79,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
private LookupTracker lookupTracker;
private LocalDescriptorResolver localDescriptorResolver;
private SupertypeLoopChecker supertypeLoopsResolver;
private LanguageVersionSettings languageVersionSettings;
@Inject
public void setJetImportFactory(KtImportsFactory jetImportFactory) {
@@ -125,6 +126,11 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
this.lookupTracker = lookupTracker;
}
@Inject
public void setLanguageVersionSettings(@NotNull LanguageVersionSettings languageVersionSettings) {
this.languageVersionSettings = languageVersionSettings;
}
// Only calls from injectors expected
@Deprecated
public ResolveSession(
@@ -427,4 +433,10 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
public void setLocalDescriptorResolver(@NotNull LocalDescriptorResolver localDescriptorResolver) {
this.localDescriptorResolver = localDescriptorResolver;
}
@NotNull
@Override
public LanguageVersionSettings getLanguageVersionSettings() {
return languageVersionSettings;
}
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.resolve.lazy.descriptors
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE
@@ -29,7 +30,10 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.incremental.record
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
@@ -182,25 +186,27 @@ open class LazyClassMemberScope(
result.add(DataClassDescriptorResolver.createCopyFunctionDescriptor(constructor.valueParameters, thisDescriptor, trace))
}
fun shouldAddFunctionFromAny(checkParameters: (FunctionDescriptor) -> Boolean): Boolean {
// Add 'equals', 'hashCode', 'toString' iff there is no such declared member AND there is no such final member in supertypes
return result.none(checkParameters) &&
fromSupertypes.none { checkParameters(it) && it.modality == Modality.FINAL }
}
if (c.languageVersionSettings.supportsFeature(LanguageFeature.DataClassInheritance)) {
fun shouldAddFunctionFromAny(checkParameters: (FunctionDescriptor) -> Boolean): Boolean {
// Add 'equals', 'hashCode', 'toString' iff there is no such declared member AND there is no such final member in supertypes
return result.none(checkParameters) &&
fromSupertypes.none { checkParameters(it) && it.modality == Modality.FINAL }
}
if (name == DataClassDescriptorResolver.EQUALS_METHOD_NAME && shouldAddFunctionFromAny { function ->
val parameters = function.valueParameters
parameters.size == 1 && KotlinBuiltIns.isNullableAny(parameters.first().type)
}) {
result.add(DataClassDescriptorResolver.createEqualsFunctionDescriptor(thisDescriptor))
}
if (name == DataClassDescriptorResolver.EQUALS_METHOD_NAME && shouldAddFunctionFromAny { function ->
val parameters = function.valueParameters
parameters.size == 1 && KotlinBuiltIns.isNullableAny(parameters.first().type)
}) {
result.add(DataClassDescriptorResolver.createEqualsFunctionDescriptor(thisDescriptor))
}
if (name == DataClassDescriptorResolver.HASH_CODE_METHOD_NAME && shouldAddFunctionFromAny { it.valueParameters.isEmpty() }) {
result.add(DataClassDescriptorResolver.createHashCodeFunctionDescriptor(thisDescriptor))
}
if (name == DataClassDescriptorResolver.HASH_CODE_METHOD_NAME && shouldAddFunctionFromAny { it.valueParameters.isEmpty() }) {
result.add(DataClassDescriptorResolver.createHashCodeFunctionDescriptor(thisDescriptor))
}
if (name == DataClassDescriptorResolver.TO_STRING_METHOD_NAME && shouldAddFunctionFromAny { it.valueParameters.isEmpty() }) {
result.add(DataClassDescriptorResolver.createToStringFunctionDescriptor(thisDescriptor))
if (name == DataClassDescriptorResolver.TO_STRING_METHOD_NAME && shouldAddFunctionFromAny { it.valueParameters.isEmpty() }) {
result.add(DataClassDescriptorResolver.createToStringFunctionDescriptor(thisDescriptor))
}
}
}
@@ -46,9 +46,7 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.PsiBasedClassMemberDeclara
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.DynamicTypesSettings
class LocalClassifierAnalyzer(
private val globalContext: GlobalContext,
@@ -87,7 +85,8 @@ class LocalClassifierAnalyzer(
funcionDescriptorResolver,
typeResolver,
annotationResolver,
supertypeLoopChecker
supertypeLoopChecker,
languageVersionSettings
)
)
@@ -110,7 +109,8 @@ class LocalClassDescriptorHolder(
val functionDescriptorResolver: FunctionDescriptorResolver,
val typeResolver: TypeResolver,
val annotationResolver: AnnotationResolver,
val supertypeLoopChecker: SupertypeLoopChecker
val supertypeLoopChecker: SupertypeLoopChecker,
val languageVersionSettings: LanguageVersionSettings
) {
// We do not need to synchronize here, because this code is used strictly from one thread
private var classDescriptor: ClassDescriptor? = null
@@ -146,6 +146,7 @@ class LocalClassDescriptorHolder(
override val annotationResolver = this@LocalClassDescriptorHolder.annotationResolver
override val lookupTracker: LookupTracker = LookupTracker.DO_NOTHING
override val supertypeLoopChecker = this@LocalClassDescriptorHolder.supertypeLoopChecker
override val languageVersionSettings = this@LocalClassDescriptorHolder.languageVersionSettings
}
,
containingDeclaration,