Hi. I am trying to write a compiler plugin. I woul...
# compiler
g
Hi. I am trying to write a compiler plugin. I would like to generate some properties for each class marked with specific annotation where each property is associated with the class's type parameter that is marked with another specific annotation. For example, in code
Copy code
@Suppliable
interface Foo<@Supply T>

@Suppliable
class Bar<@Supply U> : Foo<Map<out U, *>>
I would like to generate
val $supplied_type_property_for_Foo_T: SuppliedType
in
Foo
and
val $supplied_type_property_for_Bar_U: SuppliedType
in
Bar
. So I am writing `FirDeclarationGenerationExtension`'s inheritor. If I return only `Bar`'s own properties (i.e. only
"\$supplied_type_property_for_Bar_U"
) from
getCallableNamesForClass
, then compiler test fails with the following error:
Copy code
Actual data differs from file content: inheritance2.kt

@Suppliable
interface Foo<@Supply T>

@Suppliable
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class Bar<!><@Supply U> : Foo<Map<out U, *>>
So I conclude that I have to override `Foo`'s properties in
Bar
. But to find names of supertype properties I have to override, I have to get supertypes, so I use
FirClassSymbol<*>.resolvedSuperTypes
. And it worked until I added empty `FirSupertypeGenerationExtension`'s inheritor to my plugin. Then it failed to evaluate
resolvedSuperTypes
extension property. I think I understand that the problem is in "recursion":
FirSupertypeGenerationExtension
for some reason calls
getCallableNamesForClass
on
Bar
during
SUPER_TYPES
phase when
resolvedSuperTypes
cannot resolve super types because they are resolved during this phase (but a bit later I guess). What should I do? Is it even possible to generate properties with such "dynamic" names?
d
TBH I have no idea if your idea is implementable or not. Such a use-case was not considered during design of the API (it would be nice if it would work out eventually).
I think I understand that the problem is in "recursion":
FirSupertypeGenerationExtension
for some reason calls
getCallableNamesForClass
on Bar during SUPER_TYPES phase
Do you have a stacktrace of this
getCallableNamesForClass
call?
g
Sure, a full stacktrace of the test is placed below. But I can also prepare my library, so that you can look at the actual plugin code. Or I can try to prepare a MRE.
The stacktrace:
Copy code
Somewhere in file /inheritance2.kt: java.lang.ClassCastException: class org.jetbrains.kotlin.fir.types.impl.FirUserTypeRefImpl cannot be cast to class org.jetbrains.kotlin.fir.types.FirResolvedTypeRef (org.jetbrains.kotlin.fir.types.impl.FirUserTypeRefImpl and org.jetbrains.kotlin.fir.types.FirResolvedTypeRef are in unnamed module of loader 'app')
org.jetbrains.kotlin.util.FileAnalysisException: Somewhere in file /inheritance2.kt: java.lang.ClassCastException: class org.jetbrains.kotlin.fir.types.impl.FirUserTypeRefImpl cannot be cast to class org.jetbrains.kotlin.fir.types.FirResolvedTypeRef (org.jetbrains.kotlin.fir.types.impl.FirUserTypeRefImpl and org.jetbrains.kotlin.fir.types.FirResolvedTypeRef are in unnamed module of loader 'app')
	at org.jetbrains.kotlin.util.AnalysisExceptionsKt.wrapIntoFileAnalysisExceptionIfNeeded(AnalysisExceptions.kt:62)
	at org.jetbrains.kotlin.fir.FirCliExceptionHandler.handleExceptionOnFileAnalysis(Utils.kt:270)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverTransformer.transformFile(FirSupertypesResolution.kt:910)
	at org.jetbrains.kotlin.fir.declarations.FirFile.transform(FirFile.kt:47)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirTransformerBasedResolveProcessor.processFile(FirResolveProcessor.kt:53)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveProcessor.process(FirTotalResolveProcessor.kt:39)
	at org.jetbrains.kotlin.fir.pipeline.AnalyseKt.runResolution(analyse.kt:24)
	at org.jetbrains.kotlin.fir.FirAnalyzerFacade.runResolution(FirAnalyzerFacade.kt:49)
	at org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade.analyze(FirFrontendFacade.kt:313)
	at org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade.analyze(FirFrontendFacade.kt:116)
	at org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade.analyze(FirFrontendFacade.kt:65)
	at org.jetbrains.kotlin.test.model.FrontendFacade.transform(Facades.kt:47)
	at org.jetbrains.kotlin.test.model.FrontendFacade.transform(Facades.kt:31)
	at org.jetbrains.kotlin.test.TestStep$FacadeStep.processModule(TestStep.kt:47)
	at org.jetbrains.kotlin.test.TestRunner.processModule(TestRunner.kt:206)
	at org.jetbrains.kotlin.test.TestRunner.hackyProcessModule(TestRunner.kt:197)
	at org.jetbrains.kotlin.test.TestRunner.processModule(TestRunner.kt:141)
	at org.jetbrains.kotlin.test.TestRunner.runTestPipeline(TestRunner.kt:92)
	at org.jetbrains.kotlin.test.TestRunner.runTestImpl(TestRunner.kt:70)
	at org.jetbrains.kotlin.test.TestRunner.runTest(TestRunner.kt:30)
	at org.jetbrains.kotlin.test.TestRunner.runTest$default(TestRunner.kt:28)
	at org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest.runTest(AbstractKotlinCompilerTest.kt:115)
	at dev.lounres.kone.plugin.suppliedTypes.runners.FirCompleteTestGenerated.testInheritance2(FirCompleteTestGenerated.java:80)
Caused by: java.lang.ClassCastException: class org.jetbrains.kotlin.fir.types.impl.FirUserTypeRefImpl cannot be cast to class org.jetbrains.kotlin.fir.types.FirResolvedTypeRef (org.jetbrains.kotlin.fir.types.impl.FirUserTypeRefImpl and org.jetbrains.kotlin.fir.types.FirResolvedTypeRef are in unnamed module of loader 'app')
	at org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol.getResolvedSuperTypes(FirClassLikeSymbol.kt:150)
	at dev.lounres.kone.plugin.suppliedTypes.fir.SuppliedTypeParametersFunctionsAndPropertiesGenerationExtension.getAllNecessaryTypeParameterProperties(SuppliedTypeParametersFunctionsAndPropertiesGenerationExtension.kt:203)
	at dev.lounres.kone.plugin.suppliedTypes.fir.SuppliedTypeParametersFunctionsAndPropertiesGenerationExtension.getCallableNamesForClass(SuppliedTypeParametersFunctionsAndPropertiesGenerationExtension.kt:237)
	at org.jetbrains.kotlin.fir.scopes.impl.FirGeneratedMemberDeclarationsStorage.getCallableStorage$providers(FirGeneratedScopes.kt:159)
	at org.jetbrains.kotlin.fir.scopes.impl.FirGeneratedClassDeclaredMemberScope$Companion.create(FirGeneratedScopes.kt:50)
	at org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProvider.createDeclaredMemberScope(FirDeclaredMemberScopeProvider.kt:99)
	at org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProvider.declaredMemberCache$lambda$0(FirDeclaredMemberScopeProvider.kt:47)
	at org.jetbrains.kotlin.fir.caches.FirThreadUnsafeCache.getValue(FirThreadUnsafeCachesFactory.kt:53)
	at org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProvider.declaredMemberScope(FirDeclaredMemberScopeProvider.kt:68)
	at org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProviderKt.declaredMemberScope(FirDeclaredMemberScopeProvider.kt:146)
	at org.jetbrains.kotlin.fir.extensions.GeneratedDeclarationsUtilsKt.generatedNestedClassifiers(generatedDeclarationsUtils.kt:17)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.addSupertypesToGeneratedNestedClasses(FirSupertypesResolution.kt:497)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.resolveSpecificClassLikeSupertypes$lambda$0(FirSupertypesResolution.kt:467)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.resolveSpecificClassLikeSupertypes(FirSupertypesResolution.kt:381)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.resolveSpecificClassLikeSupertypes(FirSupertypesResolution.kt:433)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.visitRegularClass(FirSupertypesResolution.kt:403)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.visitRegularClass(FirSupertypesResolution.kt:193)
	at org.jetbrains.kotlin.fir.declarations.FirRegularClass.accept(FirRegularClass.kt:66)
	at org.jetbrains.kotlin.fir.declarations.impl.FirFileImpl.acceptChildren(FirFileImpl.kt:60)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.visitDeclarationContent(FirSupertypesResolution.kt:391)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.visitFile(FirSupertypesResolution.kt:583)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.visitFile(FirSupertypesResolution.kt:193)
	at org.jetbrains.kotlin.fir.declarations.FirFile.accept(FirFile.kt:43)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverTransformer.transformFile(FirSupertypesResolution.kt:68)
	... 20 more


class org.jetbrains.kotlin.fir.types.impl.FirUserTypeRefImpl cannot be cast to class org.jetbrains.kotlin.fir.types.FirResolvedTypeRef (org.jetbrains.kotlin.fir.types.impl.FirUserTypeRefImpl and org.jetbrains.kotlin.fir.types.FirResolvedTypeRef are in unnamed module of loader 'app')
java.lang.ClassCastException: class org.jetbrains.kotlin.fir.types.impl.FirUserTypeRefImpl cannot be cast to class org.jetbrains.kotlin.fir.types.FirResolvedTypeRef (org.jetbrains.kotlin.fir.types.impl.FirUserTypeRefImpl and org.jetbrains.kotlin.fir.types.FirResolvedTypeRef are in unnamed module of loader 'app')
	at org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol.getResolvedSuperTypes(FirClassLikeSymbol.kt:150)
	at dev.lounres.kone.plugin.suppliedTypes.fir.SuppliedTypeParametersFunctionsAndPropertiesGenerationExtension.getAllNecessaryTypeParameterProperties(SuppliedTypeParametersFunctionsAndPropertiesGenerationExtension.kt:203)
	at dev.lounres.kone.plugin.suppliedTypes.fir.SuppliedTypeParametersFunctionsAndPropertiesGenerationExtension.getCallableNamesForClass(SuppliedTypeParametersFunctionsAndPropertiesGenerationExtension.kt:237)
	at org.jetbrains.kotlin.fir.scopes.impl.FirGeneratedMemberDeclarationsStorage.getCallableStorage$providers(FirGeneratedScopes.kt:159)
	at org.jetbrains.kotlin.fir.scopes.impl.FirGeneratedClassDeclaredMemberScope$Companion.create(FirGeneratedScopes.kt:50)
	at org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProvider.createDeclaredMemberScope(FirDeclaredMemberScopeProvider.kt:99)
	at org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProvider.declaredMemberCache$lambda$0(FirDeclaredMemberScopeProvider.kt:47)
	at org.jetbrains.kotlin.fir.caches.FirThreadUnsafeCache.getValue(FirThreadUnsafeCachesFactory.kt:53)
	at org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProvider.declaredMemberScope(FirDeclaredMemberScopeProvider.kt:68)
	at org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProviderKt.declaredMemberScope(FirDeclaredMemberScopeProvider.kt:146)
	at org.jetbrains.kotlin.fir.extensions.GeneratedDeclarationsUtilsKt.generatedNestedClassifiers(generatedDeclarationsUtils.kt:17)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.addSupertypesToGeneratedNestedClasses(FirSupertypesResolution.kt:497)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.resolveSpecificClassLikeSupertypes$lambda$0(FirSupertypesResolution.kt:467)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.resolveSpecificClassLikeSupertypes(FirSupertypesResolution.kt:381)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.resolveSpecificClassLikeSupertypes(FirSupertypesResolution.kt:433)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.visitRegularClass(FirSupertypesResolution.kt:403)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.visitRegularClass(FirSupertypesResolution.kt:193)
	at org.jetbrains.kotlin.fir.declarations.FirRegularClass.accept(FirRegularClass.kt:66)
	at org.jetbrains.kotlin.fir.declarations.impl.FirFileImpl.acceptChildren(FirFileImpl.kt:60)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.visitDeclarationContent(FirSupertypesResolution.kt:391)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.visitFile(FirSupertypesResolution.kt:583)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor.visitFile(FirSupertypesResolution.kt:193)
	at org.jetbrains.kotlin.fir.declarations.FirFile.accept(FirFile.kt:43)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverTransformer.transformFile(FirSupertypesResolution.kt:68)
	at org.jetbrains.kotlin.fir.declarations.FirFile.transform(FirFile.kt:47)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirTransformerBasedResolveProcessor.processFile(FirResolveProcessor.kt:53)
	at org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveProcessor.process(FirTotalResolveProcessor.kt:39)
	at org.jetbrains.kotlin.fir.pipeline.AnalyseKt.runResolution(analyse.kt:24)
	at org.jetbrains.kotlin.fir.FirAnalyzerFacade.runResolution(FirAnalyzerFacade.kt:49)
	at org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade.analyze(FirFrontendFacade.kt:313)
	at org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade.analyze(FirFrontendFacade.kt:116)
	at org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade.analyze(FirFrontendFacade.kt:65)
	at org.jetbrains.kotlin.test.model.FrontendFacade.transform(Facades.kt:47)
	at org.jetbrains.kotlin.test.model.FrontendFacade.transform(Facades.kt:31)
	at org.jetbrains.kotlin.test.TestStep$FacadeStep.processModule(TestStep.kt:47)
	at org.jetbrains.kotlin.test.TestRunner.processModule(TestRunner.kt:206)
	at org.jetbrains.kotlin.test.TestRunner.hackyProcessModule(TestRunner.kt:197)
	at org.jetbrains.kotlin.test.TestRunner.processModule(TestRunner.kt:141)
	at org.jetbrains.kotlin.test.TestRunner.runTestPipeline(TestRunner.kt:92)
	at org.jetbrains.kotlin.test.TestRunner.runTestImpl(TestRunner.kt:70)
	at org.jetbrains.kotlin.test.TestRunner.runTest(TestRunner.kt:30)
	at org.jetbrains.kotlin.test.TestRunner.runTest$default(TestRunner.kt:28)
	at org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest.runTest(AbstractKotlinCompilerTest.kt:115)
	at dev.lounres.kone.plugin.suppliedTypes.runners.FirCompleteTestGenerated.testInheritance2(FirCompleteTestGenerated.java:80)
d
The problem is the following: • supertype generation extensions could generate new supertypes even for classes which are generated by plugins • so if there at least one such extension, the compiler checks if there are any plugins which want to generate nested classes • but due to not the best implementation, checking for nested classes also triggers
getCallableNamesForClass
, which leads to the problem you're observing There is nothing you can do to workaround it from your side except not registering the supertype extension. But it definitely worth reporting a ticket to youtrack (link), so we'll fix it in the compiler.
g
Thanks for the answer! I'll file the ticket.
d
Please also insert the link to this thread in the ticket.
👍 1
g
Sorry for the delay. Here the ticket is: https://youtrack.jetbrains.com/issue/KT-84928
thank you color 1