Refactor DelegationChecker and related code
- move getDelegates from CodegenUtil to DelegationResolver, reuse it in DelegationChecker - use getAllOverriddenDescriptors + filterOutOverridden instead of a manual DFS
This commit is contained in:
@@ -24,51 +24,10 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.MemberComparator
|
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.isDynamic
|
|
||||||
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
|
|
||||||
|
|
||||||
object CodegenUtil {
|
object CodegenUtil {
|
||||||
// class Foo : Bar by baz
|
|
||||||
// descriptor = Foo
|
|
||||||
// toInterface = Bar
|
|
||||||
// delegateExpressionType = typeof(baz)
|
|
||||||
// return Map<member of Foo, corresponding member of typeOf(baz)>
|
|
||||||
@JvmStatic
|
|
||||||
fun getDelegates(
|
|
||||||
descriptor: ClassDescriptor,
|
|
||||||
toInterface: ClassDescriptor,
|
|
||||||
delegateExpressionType: KotlinType? = null
|
|
||||||
): Map<CallableMemberDescriptor, CallableDescriptor> {
|
|
||||||
if (delegateExpressionType?.isDynamic() ?: false) return emptyMap()
|
|
||||||
|
|
||||||
return descriptor.defaultType.memberScope.getContributedDescriptors().asSequence()
|
|
||||||
.filterIsInstance<CallableMemberDescriptor>()
|
|
||||||
.filter { it.kind == CallableMemberDescriptor.Kind.DELEGATION }
|
|
||||||
.asIterable()
|
|
||||||
.sortedWith(MemberComparator.INSTANCE)
|
|
||||||
.keysToMapExceptNulls { delegatingMember ->
|
|
||||||
val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember)
|
|
||||||
.filter { it.containingDeclaration == toInterface }
|
|
||||||
.map { overriddenDescriptor ->
|
|
||||||
val scope = (delegateExpressionType ?: toInterface.defaultType).memberScope
|
|
||||||
val name = overriddenDescriptor.name
|
|
||||||
|
|
||||||
// this is the actual member of delegateExpressionType that we are delegating to
|
|
||||||
(scope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND) +
|
|
||||||
scope.getContributedVariables(name, NoLookupLocation.FROM_BACKEND))
|
|
||||||
.firstOrNull { it == overriddenDescriptor || OverridingUtil.overrides(it, overriddenDescriptor) }
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(actualDelegates.size <= 1) { "Many delegates found for $delegatingMember: $actualDelegates" }
|
|
||||||
|
|
||||||
actualDelegates.firstOrNull()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getDelegatePropertyIfAny(
|
fun getDelegatePropertyIfAny(
|
||||||
expression: KtExpression, classDescriptor: ClassDescriptor, bindingContext: BindingContext
|
expression: KtExpression, classDescriptor: ClassDescriptor, bindingContext: BindingContext
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.name.FqName;
|
|||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
|
import org.jetbrains.kotlin.resolve.DelegationResolver;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||||
@@ -1655,18 +1656,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
fieldInfo.name, fieldInfo.type.getDescriptor(), /*TODO*/null, null);
|
fieldInfo.name, fieldInfo.type.getDescriptor(), /*TODO*/null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateDelegates(ClassDescriptor toTrait, KotlinType delegateExpressionType, DelegationFieldsInfo.Field field) {
|
private void generateDelegates(
|
||||||
for (Map.Entry<CallableMemberDescriptor, CallableDescriptor> entry :
|
@NotNull ClassDescriptor toInterface,
|
||||||
CodegenUtil.getDelegates(descriptor, toTrait, delegateExpressionType).entrySet()) {
|
@Nullable KotlinType delegateExpressionType,
|
||||||
CallableMemberDescriptor callableMemberDescriptor = entry.getKey();
|
@NotNull DelegationFieldsInfo.Field field
|
||||||
CallableDescriptor delegateTo = entry.getValue();
|
) {
|
||||||
if (callableMemberDescriptor instanceof PropertyDescriptor) {
|
for (Map.Entry<CallableMemberDescriptor, CallableMemberDescriptor> entry : DelegationResolver.Companion.getDelegates(
|
||||||
propertyCodegen
|
descriptor, toInterface, delegateExpressionType).entrySet()
|
||||||
.genDelegate((PropertyDescriptor) callableMemberDescriptor, (PropertyDescriptor) delegateTo, field.getStackValue());
|
) {
|
||||||
|
CallableMemberDescriptor member = entry.getKey();
|
||||||
|
CallableMemberDescriptor delegateTo = entry.getValue();
|
||||||
|
if (member instanceof PropertyDescriptor) {
|
||||||
|
propertyCodegen.genDelegate((PropertyDescriptor) member, (PropertyDescriptor) delegateTo, field.getStackValue());
|
||||||
}
|
}
|
||||||
else if (callableMemberDescriptor instanceof FunctionDescriptor) {
|
else if (member instanceof FunctionDescriptor) {
|
||||||
functionCodegen
|
functionCodegen.genDelegate((FunctionDescriptor) member, (FunctionDescriptor) delegateTo, field.getStackValue());
|
||||||
.genDelegate((FunctionDescriptor) callableMemberDescriptor, (FunctionDescriptor) delegateTo, field.getStackValue());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED
|
import org.jetbrains.kotlin.diagnostics.Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED
|
||||||
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
||||||
import org.jetbrains.kotlin.psi.KtPureClassOrObject
|
import org.jetbrains.kotlin.psi.KtPureClassOrObject
|
||||||
@@ -27,6 +28,8 @@ import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Res
|
|||||||
import org.jetbrains.kotlin.resolve.lazy.DelegationFilter
|
import org.jetbrains.kotlin.resolve.lazy.DelegationFilter
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
import org.jetbrains.kotlin.types.isDynamic
|
||||||
|
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
|
||||||
|
|
||||||
class DelegationResolver<T : CallableMemberDescriptor> private constructor(
|
class DelegationResolver<T : CallableMemberDescriptor> private constructor(
|
||||||
private val classOrObject: KtPureClassOrObject,
|
private val classOrObject: KtPureClassOrObject,
|
||||||
@@ -124,5 +127,40 @@ class DelegationResolver<T : CallableMemberDescriptor> private constructor(
|
|||||||
private fun isOverridableBy(memberOne: CallableDescriptor, memberTwo: CallableDescriptor): Boolean =
|
private fun isOverridableBy(memberOne: CallableDescriptor, memberTwo: CallableDescriptor): Boolean =
|
||||||
OverridingUtil.DEFAULT.isOverridableBy(memberOne, memberTwo, null).result == OVERRIDABLE
|
OverridingUtil.DEFAULT.isOverridableBy(memberOne, memberTwo, null).result == OVERRIDABLE
|
||||||
|
|
||||||
|
// class Foo : Bar by baz
|
||||||
|
// descriptor = Foo
|
||||||
|
// toInterface = Bar
|
||||||
|
// delegateExpressionType = typeof(baz)
|
||||||
|
// return Map<member of Foo, corresponding member of typeOf(baz)>
|
||||||
|
fun getDelegates(
|
||||||
|
descriptor: ClassDescriptor,
|
||||||
|
toInterface: ClassDescriptor,
|
||||||
|
delegateExpressionType: KotlinType? = null
|
||||||
|
): Map<CallableMemberDescriptor, CallableMemberDescriptor> {
|
||||||
|
if (delegateExpressionType?.isDynamic() ?: false) return emptyMap()
|
||||||
|
|
||||||
|
val delegatedMembers = descriptor.defaultType.memberScope.getContributedDescriptors().asSequence()
|
||||||
|
.filterIsInstance<CallableMemberDescriptor>()
|
||||||
|
.filter { it.kind == CallableMemberDescriptor.Kind.DELEGATION }
|
||||||
|
.asIterable()
|
||||||
|
.sortedWith(MemberComparator.INSTANCE)
|
||||||
|
|
||||||
|
return delegatedMembers
|
||||||
|
.keysToMapExceptNulls { delegatingMember ->
|
||||||
|
val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember)
|
||||||
|
.filter { it.containingDeclaration == toInterface }
|
||||||
|
.map { overriddenDescriptor ->
|
||||||
|
val scope = (delegateExpressionType ?: toInterface.defaultType).memberScope
|
||||||
|
val name = overriddenDescriptor.name
|
||||||
|
|
||||||
|
// this is the actual member of delegateExpressionType that we are delegating to
|
||||||
|
(scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_OVERRIDES) +
|
||||||
|
scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_OVERRIDES))
|
||||||
|
.firstOrNull { it == overriddenDescriptor || OverridingUtil.overrides(it, overriddenDescriptor) }
|
||||||
|
}
|
||||||
|
|
||||||
|
actualDelegates.firstOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,16 +22,13 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors.DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE
|
import org.jetbrains.kotlin.diagnostics.Errors.DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.DelegationResolver
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.MemberComparator
|
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||||
import org.jetbrains.kotlin.utils.DFS
|
|
||||||
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
|
|
||||||
|
|
||||||
class DelegationChecker : SimpleDeclarationChecker {
|
class DelegationChecker : SimpleDeclarationChecker {
|
||||||
override fun check(
|
override fun check(
|
||||||
@@ -43,16 +40,12 @@ class DelegationChecker : SimpleDeclarationChecker {
|
|||||||
if (descriptor !is ClassDescriptor) return
|
if (descriptor !is ClassDescriptor) return
|
||||||
if (declaration !is KtClassOrObject) return
|
if (declaration !is KtClassOrObject) return
|
||||||
|
|
||||||
val delegationDescriptors = descriptor.defaultType.memberScope.getContributedDescriptors().
|
|
||||||
filterIsInstance<CallableMemberDescriptor>().filter { it.kind == CallableMemberDescriptor.Kind.DELEGATION }.sortedWith(MemberComparator.INSTANCE)
|
|
||||||
|
|
||||||
for (specifier in declaration.superTypeListEntries) {
|
for (specifier in declaration.superTypeListEntries) {
|
||||||
if (specifier is KtDelegatedSuperTypeEntry) {
|
if (specifier is KtDelegatedSuperTypeEntry) {
|
||||||
val superType = specifier.typeReference?.let { bindingContext.get(BindingContext.TYPE, it) } ?: continue
|
val superType = specifier.typeReference?.let { bindingContext.get(BindingContext.TYPE, it) } ?: continue
|
||||||
val superTypeDescriptor = superType.constructor.declarationDescriptor as? ClassDescriptor ?: continue
|
val superTypeDescriptor = superType.constructor.declarationDescriptor as? ClassDescriptor ?: continue
|
||||||
|
|
||||||
val delegates = getDelegates(delegationDescriptors, superTypeDescriptor)
|
for ((delegated, delegatedTo) in DelegationResolver.getDelegates(descriptor, superTypeDescriptor)) {
|
||||||
delegates.forEach { (delegated, delegatedTo) ->
|
|
||||||
checkDescriptor(declaration, delegated, delegatedTo, diagnosticHolder)
|
checkDescriptor(declaration, delegated, delegatedTo, diagnosticHolder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,57 +58,16 @@ class DelegationChecker : SimpleDeclarationChecker {
|
|||||||
delegatedToDescriptor: CallableMemberDescriptor,
|
delegatedToDescriptor: CallableMemberDescriptor,
|
||||||
diagnosticHolder: DiagnosticSink
|
diagnosticHolder: DiagnosticSink
|
||||||
) {
|
) {
|
||||||
val reachableFromDelegated = findAllReachableDeclarations(delegatedDescriptor)
|
val reachableFromDelegated =
|
||||||
reachableFromDelegated.remove(delegatedDescriptor.original)
|
OverridingUtil.filterOutOverridden(
|
||||||
val toRemove = linkedSetOf<CallableMemberDescriptor>()
|
DescriptorUtils.getAllOverriddenDescriptors(delegatedDescriptor).filter { it.kind.isReal }.toSet()
|
||||||
for (declaration in reachableFromDelegated) {
|
) - DescriptorUtils.unwrapFakeOverride(delegatedToDescriptor).original
|
||||||
val reachable = findAllReachableDeclarations(declaration.original)
|
|
||||||
reachable.remove(declaration)
|
|
||||||
toRemove.addAll(reachable)
|
|
||||||
}
|
|
||||||
reachableFromDelegated.removeAll(toRemove)
|
|
||||||
reachableFromDelegated.remove(DescriptorUtils.unwrapFakeOverride(delegatedToDescriptor).original)
|
|
||||||
|
|
||||||
val nonAbstractReachable = reachableFromDelegated.filter { it.modality != Modality.ABSTRACT }
|
val nonAbstractReachable = reachableFromDelegated.filter { it.modality != Modality.ABSTRACT }
|
||||||
|
|
||||||
if (nonAbstractReachable.isNotEmpty()) {
|
if (nonAbstractReachable.isNotEmpty()) {
|
||||||
/*In case of MANY_IMPL_MEMBER_NOT_IMPLEMENTED error there could be several elements otherwise only one*/
|
/*In case of MANY_IMPL_MEMBER_NOT_IMPLEMENTED error there could be several elements otherwise only one*/
|
||||||
diagnosticHolder.report(DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE.on(classDeclaration, delegatedDescriptor, nonAbstractReachable.toList()))
|
diagnosticHolder.report(DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE.on(classDeclaration, delegatedDescriptor, nonAbstractReachable))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDelegates(
|
|
||||||
delegatedMethods: Iterable<CallableMemberDescriptor>,
|
|
||||||
toInterface: ClassDescriptor
|
|
||||||
): Map<CallableMemberDescriptor, CallableMemberDescriptor> {
|
|
||||||
return delegatedMethods
|
|
||||||
.keysToMapExceptNulls { delegatingMember ->
|
|
||||||
val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember)
|
|
||||||
.filter { it.containingDeclaration == toInterface }
|
|
||||||
.map { overriddenDescriptor ->
|
|
||||||
val scope = toInterface.defaultType.memberScope
|
|
||||||
val name = overriddenDescriptor.name
|
|
||||||
|
|
||||||
// this is the actual member of delegateExpressionType that we are delegating to
|
|
||||||
(scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_OVERRIDES) +
|
|
||||||
scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_OVERRIDES))
|
|
||||||
.firstOrNull { it == overriddenDescriptor || OverridingUtil.overrides(it, overriddenDescriptor) }
|
|
||||||
}
|
|
||||||
|
|
||||||
actualDelegates.firstOrNull() as? CallableMemberDescriptor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findAllReachableDeclarations(memberDescriptor: CallableMemberDescriptor): MutableSet<CallableMemberDescriptor> {
|
|
||||||
val collector = object : DFS.NodeHandlerWithListResult<CallableMemberDescriptor, CallableMemberDescriptor>() {
|
|
||||||
override fun afterChildren(current: CallableMemberDescriptor) {
|
|
||||||
if (current.kind.isReal) {
|
|
||||||
result.add(current.original)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DFS.dfs(listOf(memberDescriptor), { it.overriddenDescriptors }, collector)
|
|
||||||
return java.util.HashSet(collector.result())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
interface Base {
|
||||||
|
fun test() = "Base"
|
||||||
|
}
|
||||||
|
|
||||||
|
class Delegate : Base
|
||||||
|
|
||||||
|
abstract class Middle : Base {
|
||||||
|
override fun test() = "MyClass"
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class MyClass : Middle()
|
||||||
|
|
||||||
|
<!DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE!>class A : MyClass(), Base by Delegate()<!>
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public final class A : MyClass, Base {
|
||||||
|
public constructor A()
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*2*/ /*delegation*/ fun test(): kotlin.String
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Base {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open fun test(): kotlin.String
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Delegate : Base {
|
||||||
|
public constructor Delegate()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun test(): kotlin.String
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class Middle : Base {
|
||||||
|
public constructor Middle()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ fun test(): kotlin.String
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class MyClass : Middle {
|
||||||
|
public constructor MyClass()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun test(): kotlin.String
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -6271,6 +6271,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("fakeOverrideInTheMiddle.kt")
|
||||||
|
public void testFakeOverrideInTheMiddle() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/delegationBy/fakeOverrideInTheMiddle.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("generic.kt")
|
@TestMetadata("generic.kt")
|
||||||
public void testGeneric() throws Exception {
|
public void testGeneric() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/delegationBy/generic.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/delegationBy/generic.kt");
|
||||||
|
|||||||
+3
-2
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateFunctio
|
|||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
||||||
import org.jetbrains.kotlin.psi.KtSuperTypeListEntry
|
import org.jetbrains.kotlin.psi.KtSuperTypeListEntry
|
||||||
|
import org.jetbrains.kotlin.resolve.DelegationResolver
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ class DelegationTranslator(
|
|||||||
BindingUtils.getClassDescriptor(context.bindingContext(), classDeclaration)
|
BindingUtils.getClassDescriptor(context.bindingContext(), classDeclaration)
|
||||||
|
|
||||||
private val delegationBySpecifiers =
|
private val delegationBySpecifiers =
|
||||||
classDeclaration.getSuperTypeListEntries().filterIsInstance<KtDelegatedSuperTypeEntry>()
|
classDeclaration.superTypeListEntries.filterIsInstance<KtDelegatedSuperTypeEntry>()
|
||||||
|
|
||||||
private class Field (val name: JsName, val generateField: Boolean)
|
private class Field (val name: JsName, val generateField: Boolean)
|
||||||
private val fields = mutableMapOf<KtDelegatedSuperTypeEntry, Field>()
|
private val fields = mutableMapOf<KtDelegatedSuperTypeEntry, Field>()
|
||||||
@@ -91,7 +92,7 @@ class DelegationTranslator(
|
|||||||
CodegenUtil.getSuperClassBySuperTypeListEntry(specifier, bindingContext())
|
CodegenUtil.getSuperClassBySuperTypeListEntry(specifier, bindingContext())
|
||||||
|
|
||||||
private fun generateDelegates(toClass: ClassDescriptor, field: Field) {
|
private fun generateDelegates(toClass: ClassDescriptor, field: Field) {
|
||||||
for ((descriptor, overriddenDescriptor) in CodegenUtil.getDelegates(classDescriptor, toClass)) {
|
for ((descriptor, overriddenDescriptor) in DelegationResolver.getDelegates(classDescriptor, toClass)) {
|
||||||
when (descriptor) {
|
when (descriptor) {
|
||||||
is PropertyDescriptor ->
|
is PropertyDescriptor ->
|
||||||
generateDelegateCallForPropertyMember(descriptor, field.name)
|
generateDelegateCallForPropertyMember(descriptor, field.name)
|
||||||
|
|||||||
Reference in New Issue
Block a user