I am trying to trigger generation of a companion o...
# compiler
c
I am trying to trigger generation of a companion object for classes implementing a specific interface in a compiler plugin by the following
SyntheticResolveExtension
:
Copy code
override fun getSyntheticCompanionObjectNameIfNeeded(descriptor: ClassDescriptor): Name? {
    return descriptor.getSuperInterfaces().firstOrNull { it.fqNameSafe == FqName("SOME_INTERFACE") }
        ?.let { DEFAULT_NAME_FOR_COMPANION_OBJECT }
}
It works for most cases but when having inner classes as generic type parameters, like:
Copy code
interface Generic<T>

interface Outer : Generic<Outer.Inner> {
        class Inner
}
The check fails due to recursion in resolving the super interfaces (stack trace is in thread). Any suggestions on how to trigger generation of companion classes (or not) that would also work for this case by other means (APIs, phases, etc)?
Full stack trace
Copy code
Caused by: java.lang.AssertionError: Recursion detected on input: Inner under LockBasedStorageManager@73bcc4f4 (TopDownAnalyzer for JVM)
	at org.jetbrains.kotlin.resolve.lazy.descriptors.AbstractLazyMemberScope.getContributedClassifier(AbstractLazyMemberScope.kt:75)
	at org.jetbrains.kotlin.resolve.scopes.InnerClassesScopeWrapper.getContributedClassifier(InnerClassesScopeWrapper.kt:29)
	at org.jetbrains.kotlin.resolve.QualifiedExpressionResolver.resolveQualifierPartListForType(QualifiedExpressionResolver.kt:151)
	at org.jetbrains.kotlin.resolve.QualifiedExpressionResolver.resolveDescriptorForType(QualifiedExpressionResolver.kt:129)
	at org.jetbrains.kotlin.resolve.TypeResolver.resolveDescriptorForType(TypeResolver.kt:930)
	at org.jetbrains.kotlin.resolve.TypeResolver$resolveTypeElement$1.visitUserType(TypeResolver.kt:247)
	at org.jetbrains.kotlin.psi.KtVisitorVoid.visitUserType(KtVisitorVoid.java:929)
	at org.jetbrains.kotlin.psi.KtVisitorVoid.visitUserType(KtVisitorVoid.java:21)
	at org.jetbrains.kotlin.psi.KtUserType.accept(KtUserType.java:42)
	at org.jetbrains.kotlin.psi.KtElementImplStub.accept(KtElementImplStub.java:60)
	at org.jetbrains.kotlin.resolve.TypeResolver.resolveTypeElement(TypeResolver.kt:245)
	at org.jetbrains.kotlin.resolve.TypeResolver.resolvePossiblyBareType(TypeResolver.kt:124)
	at org.jetbrains.kotlin.resolve.TypeResolver.resolveType(TypeResolver.kt:114)
	at org.jetbrains.kotlin.resolve.TypeResolver.resolveTypeProjections(TypeResolver.kt:883)
	at org.jetbrains.kotlin.resolve.TypeResolver.resolveTypeForClass(TypeResolver.kt:505)
	at org.jetbrains.kotlin.resolve.TypeResolver.resolveTypeForClassifier(TypeResolver.kt:472)
	at org.jetbrains.kotlin.resolve.TypeResolver$resolveTypeElement$1.visitUserType(TypeResolver.kt:263)
	at org.jetbrains.kotlin.psi.KtVisitorVoid.visitUserType(KtVisitorVoid.java:929)
	at org.jetbrains.kotlin.psi.KtVisitorVoid.visitUserType(KtVisitorVoid.java:21)
	at org.jetbrains.kotlin.psi.KtUserType.accept(KtUserType.java:42)
	at org.jetbrains.kotlin.psi.KtElementImplStub.accept(KtElementImplStub.java:60)
	at org.jetbrains.kotlin.resolve.TypeResolver.resolveTypeElement(TypeResolver.kt:245)
	at org.jetbrains.kotlin.resolve.TypeResolver.resolvePossiblyBareType(TypeResolver.kt:124)
	at org.jetbrains.kotlin.resolve.TypeResolver.resolveType(TypeResolver.kt:114)
	at org.jetbrains.kotlin.resolve.TypeResolver.resolveType(TypeResolver.kt:85)
	at org.jetbrains.kotlin.resolve.DescriptorResolver.resolveSuperTypeListEntries(DescriptorResolver.java:212)
	at org.jetbrains.kotlin.resolve.DescriptorResolver.resolveSupertypes(DescriptorResolver.java:148)
	at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor.computeSupertypes(LazyClassDescriptor.java:758)
	at org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor$LazyClassTypeConstructor.computeSupertypes(LazyClassDescriptor.java:655)
	at org.jetbrains.kotlin.types.AbstractTypeConstructor$supertypes$1.invoke(AbstractTypeConstructor.kt:83)
	at org.jetbrains.kotlin.types.AbstractTypeConstructor$supertypes$1.invoke(AbstractTypeConstructor.kt:83)
	at org.jetbrains.kotlin.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(LockBasedStorageManager.java:408)
	at org.jetbrains.kotlin.storage.LockBasedStorageManager$LockBasedLazyValueWithPostCompute.invoke(LockBasedStorageManager.java:481)
	at org.jetbrains.kotlin.storage.LockBasedStorageManager$LockBasedNotNullLazyValueWithPostCompute.invoke(LockBasedStorageManager.java:512)
	at org.jetbrains.kotlin.types.AbstractTypeConstructor.getSupertypes(AbstractTypeConstructor.kt:30)
	at org.jetbrains.kotlin.types.AbstractTypeConstructor.getSupertypes(AbstractTypeConstructor.kt:27)
	at org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getSuperInterfaces(DescriptorUtils.kt:158)
	at io.realm.compiler.RealmModelSyntheticCompanionExtension.getSyntheticCompanionObjectNameIfNeeded(RealmModelSyntheticCompanionExtension.kt:50)
n
Hi @dmitriy.novozhilov any official work around for this use case? currently we're using PSI to check for supertypes and avoid the recursion https://github.com/realm/realm-kotlin/pull/845/files#diff-167d24791003e06479e2cfe3d073361d94f0bcc8d09cc076e87b0171390e71b9L110-R119 but I feel this is suboptimal ...
d
This won't be an issue in K2 compiler
n
That's a good news! is the above hack acceptable in the meantime or do you see any risk?
d
It won't work with typealiases and
as
imports
n
Good point, that is a constraint we can accept until we migrate to K2