Synthesized 'copy' in data classes cannot override anything since 1.3

Synthesized 'copy' introduces default values for parameters, which is
prohibited for regular overrides.
Report warning in language version 1.2-, error in 1.3+.
This commit is contained in:
Dmitry Petrov
2017-09-12 15:10:03 +03:00
parent 9ae6feb2c5
commit 4c2cfd3ea9
17 changed files with 226 additions and 1 deletions
@@ -394,6 +394,10 @@ public interface Errors {
DiagnosticFactory2<PsiElement, CallableMemberDescriptor, DeclarationDescriptor> DATA_CLASS_OVERRIDE_CONFLICT =
DiagnosticFactory2.create(ERROR);
DiagnosticFactory2<PsiElement, CallableMemberDescriptor, DeclarationDescriptor> DATA_CLASS_OVERRIDE_DEFAULT_VALUES_WARNING =
DiagnosticFactory2.create(WARNING);
DiagnosticFactory2<PsiElement, CallableMemberDescriptor, DeclarationDescriptor> DATA_CLASS_OVERRIDE_DEFAULT_VALUES_ERROR =
DiagnosticFactory2.create(ERROR);
DiagnosticFactory1<KtDeclaration, CallableMemberDescriptor> CANNOT_INFER_VISIBILITY =
DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
@@ -290,6 +290,8 @@ public class DefaultErrorMessages {
MAP.put(VIRTUAL_MEMBER_HIDDEN, "''{0}'' hides member of supertype ''{2}'' and needs ''override'' modifier", NAME, NAME, NAME);
MAP.put(DATA_CLASS_OVERRIDE_CONFLICT, "Function ''{0}'' generated for the data class conflicts with member of supertype ''{1}''", NAME, NAME);
MAP.put(DATA_CLASS_OVERRIDE_DEFAULT_VALUES_WARNING, "Function ''{0}'' generated for the data class has default values for parameters, and conflicts with member of supertype ''{1}''", NAME, NAME);
MAP.put(DATA_CLASS_OVERRIDE_DEFAULT_VALUES_ERROR, "Function ''{0}'' generated for the data class has default values for parameters, and conflicts with member of supertype ''{1}''", NAME, NAME);
MAP.put(CANNOT_OVERRIDE_INVISIBLE_MEMBER, "''{0}'' has no access to ''{1}'', so it cannot override it", FQ_NAMES_IN_TYPES,
FQ_NAMES_IN_TYPES);
@@ -22,6 +22,8 @@ import com.intellij.psi.PsiElement
import com.intellij.util.SmartList
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.containers.SmartHashSet
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE
@@ -41,7 +43,8 @@ import java.util.*
class OverrideResolver(
private val trace: BindingTrace,
private val overridesBackwardCompatibilityHelper: OverridesBackwardCompatibilityHelper
private val overridesBackwardCompatibilityHelper: OverridesBackwardCompatibilityHelper,
private val languageVersionSettings: LanguageVersionSettings
) {
fun check(c: TopDownAnalysisContext) {
@@ -244,6 +247,9 @@ class OverrideResolver(
if (DataClassDescriptorResolver.isComponentLike(declared.name)) {
checkOverrideForComponentFunction(declared)
}
else if (declared.name == DataClassDescriptorResolver.COPY_METHOD_NAME) {
checkOverrideForCopyFunction(declared)
}
return
}
@@ -341,6 +347,20 @@ class OverrideResolver(
})
}
private fun checkOverrideForCopyFunction(copyFunction: CallableMemberDescriptor) {
val overridden = copyFunction.overriddenDescriptors.firstOrNull()
if (overridden != null) {
val baseClassifier = overridden.containingDeclaration
val dataModifier = findDataModifierForDataClass(copyFunction.containingDeclaration)
if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitDataClassesOverridingCopy)) {
trace.report(DATA_CLASS_OVERRIDE_DEFAULT_VALUES_ERROR.on(dataModifier, copyFunction, baseClassifier))
}
else {
trace.report(DATA_CLASS_OVERRIDE_DEFAULT_VALUES_WARNING.on(dataModifier, copyFunction, baseClassifier))
}
}
}
private fun checkParameterOverridesForAllClasses(c: TopDownAnalysisContext) {
for (classDescriptor in c.declaredClasses.values) {
for (member in DescriptorUtils.getAllDescriptors(classDescriptor.defaultType.memberScope)) {