I want to author a plugin that declares an `inline...
# compiler
m
I want to author a plugin that declares an
inline operator fun invoke
in the
companion object
of an annotated
class
Copy code
class MyFirExtensionRegistrar : FirExtensionRegistrar() {
    override fun ExtensionRegistrarContext.configurePlugin() {
        (::MyFirDeclarationGenerationExtension).unaryPlus()
    }
}

class MyFirDeclarationGenerationExtension(session: FirSession)
    : FirDeclarationGenerationExtension(session)
{
    object Key: GeneratedDeclarationKey()

    fun appliesTo(classSymbol: FirClassSymbol<*>): Boolean {
        return classSymbol.hasAnnotation(
            classId = ClassId.topLevel(
                FqName(MyAnnotation::class.qualifiedName!!)
            ),
            session = this.session,
        )
    }

    override fun getNestedClassifiersNames(
        classSymbol: FirClassSymbol<*>,
        context: NestedClassGenerationContext,
    ): Set<Name> {
        return when (this.appliesTo(classSymbol) && @OptIn(SymbolInternals::class) (
            null == (classSymbol as? FirRegularClassSymbol)?.companionObjectSymbol
        )) {
            true -> setOf(SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT)
            else -> emptySet()
        }
    }

    override fun generateNestedClassLikeDeclaration(
        owner: FirClassSymbol<*>,
        name: Name,
        context: NestedClassGenerationContext,
    ): FirClassLikeSymbol<*>? {
        return when (name.takeIf { this.appliesTo(owner) }) {
            SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT ->
                (FirRegularClass::symbol)(createCompanionObject(
                    owner = owner,
                    key = Key,
                ))
            else -> null
        }
    }

    override fun getCallableNamesForClass(
        classSymbol: FirClassSymbol<*>,
        context: MemberGenerationContext,
    ): Set<Name> {
        return when (classSymbol
            .takeIf { symbol -> symbol.classKind == ClassKind.OBJECT }
            ?.classId
            ?.outerClassId
            ?.let(this.session.symbolProvider::getClassLikeSymbolByClassId)
            ?.let { owner -> owner as? FirClassSymbol<*> }
            ?.takeIf(this::appliesTo)
            ?.let(::companionObject)
            ?.name
        ) {
            classSymbol.classId.shortClassName -> setOf(Name.identifier("invoke"))
            else -> emptySet()
        }
    }
}

fun companionObject(haystack: FirClassSymbol<*>): FirRegularClassSymbol? {
    @OptIn(SymbolInternals::class)
    return (haystack as? FirRegularClassSymbol)?.companionObjectSymbol
}
Is this the right setup?