Thread
#arrow-meta
    Tim Abil

    Tim Abil

    6 months ago
    Does arrow-meta provide any utils to resolve a type of
    KtExpression
    raulraja

    raulraja

    6 months ago
    Hi @Tim Abil, The binding context is available as argument in most of the methods available in the Analysis extension. In meta those methods are
    doAnalysis
    analysisCompleted
    . It’s also available in the declaration and expression checker context and you can find it inside the BindingTrace. If you have some code i may be able to point you as to how to get it in the place you are on now.
    Tim Abil

    Tim Abil

    6 months ago
    So im grabbing the
    CompilerContext
    from here and passing it down to my
    KtVisitor
    Then when i visit a
    KtExpression
    i assume i need to do something like this
    raulraja

    raulraja

    6 months ago
    that api and everything in the quotes package is gone from Arrow meta since the compiler is moving away from PSI to FIR and that API was gonna disappear after 1.8 on when FIR is stable. If you are in a different place like a callchecker you can get it with
    context.trace.bindingContext
    . What does you plugin try to perform?
    Tim Abil

    Tim Abil

    6 months ago
    Yeah im still using 1.5.31 since you guys are still in process of writing the new docs for FIR. I'm writing a Ktor plugin to generate a swagger spec and need to resolve a return type of
    call.receive<T>()
    to determine the endpoint's request body type.
    the
    validateFunction
    basically looks for a fun with a specific annotation so i could
    .accept
    a visitor on it
    raulraja

    raulraja

    6 months ago
    instead of using quotes, I would write this in
    arrow.meta.dsl.config.ConfigSyntax#callChecker
    we are gonna relocate that function, it’s in the wrong package now, but that intercepts all calls.
    fun callChecker(
        check:
          CompilerContext.(
            resolvedCall: ResolvedCall<*>,
            reportOn: org.jetbrains.kotlin.com.intellij.psi.PsiElement,
            context: CallCheckerContext) -> Unit
      ): arrow.meta.phases.config.StorageComponentContainer
    or
    fun declarationChecker(
        check:
          CompilerContext.(
            declaration: KtDeclaration,
            descriptor: DeclarationDescriptor,
            context: DeclarationCheckerContext) -> Unit
      ): arrow.meta.phases.config.StorageComponentContainer
    Both of those context arguments have access to the binding trace
    interface CheckerContext {
        val trace: BindingTrace
    
        val languageVersionSettings: LanguageVersionSettings
    
        val deprecationResolver: DeprecationResolver
    
        val moduleDescriptor: ModuleDescriptor
    }
    you would use those instead of
    namedFunction
    if you intercept the right call you may not need the binding context at all. The reason being that the
    descriptor: DesclarationDescriptor
    is what you are probably trying to get out of the binding context.
    Tim Abil

    Tim Abil

    6 months ago
    right right - what would i pass as
    CompilerContext.(..)
    check extension
    ahh i got it
    do i visit KtDeclarations the same way?
    raulraja

    raulraja

    6 months ago
    try the callChecker first since you seem to be intercepting a call instead of analyzing the definition or member of a declaration
    the call checker should actually intercept the precise call you are looking for.
    Tim Abil

    Tim Abil

    6 months ago
    hmm but then i wouldnt need a
    KtVisitor
    at all right?
    raulraja

    raulraja

    6 months ago
    no, you would just check the call you are intercepting is pointing to an annotated owner
    that info will b inside the
    resolvedCall
    the call checker already traverses all calls so no need for a visitor unless you are back tracing or looking up or down a nested call.
    Tim Abil

    Tim Abil

    6 months ago
    gotcha, i just have a bunch of logic implemented in the visitor and would prefer if i could resolve type when visitingCallExpression
    raulraja

    raulraja

    6 months ago
    if you choose the declarationChecker path that will force you to implement the part where the call needs to be resolved, not a big deal but usually the most effitient for this case would be to use a call checker
    calls have descriptor functions they are resolved to where you can extract annotation info and all the analysis knows about that call, including types etc.
    FIR provides both call and declaration checkers, porting it later to FIR should be not too hard if you don’t depend much on the trace and binding context directly.
    Tim Abil

    Tim Abil

    6 months ago
    makes sense, so if do use the declarationChecker instead since that lets me invoke a custom Visitor. how would implement the call resolution in that case, perhaps there's an example can reference.
    raulraja

    raulraja

    6 months ago
    Once you reach a node that is a
    call
    you can get its
    resolvedCall
    with
    org.jetbrains.kotlin.resolve.calls.util.CallUtilKt#getResolvedCall(org.jetbrains.kotlin.psi.KtElement, org.jetbrains.kotlin.resolve.BindingContext)
    That is an ext fun available over
    KtElement
    and over
    Call
    Tim Abil

    Tim Abil

    6 months ago
    expression.getResolvedCall(context)
    is giving me null back perhaps my context reference is wrong
    raulraja

    raulraja

    6 months ago
    it may be that the call is not yet resolved at the point the declaration checker is running
    try with a callchecker too to see if the call is intercepted with a resolved call. Or alternatively try extracting the binding context from the
    ContextChecker
    argument in the declaration checker instead of the one in the compiler context
    Tim Abil

    Tim Abil

    6 months ago
    yep im taking bindingContext from the
    declarationCheckerContext
    but that context is for the top level annotated function that i accept my Visitor to. Then the visitor visits the block of the annotated fun, iterates through the statements and visits another expression that im trying to resolve a type for.
    so perhaps at that point its the wrong bindingContext
    BindingContextUtils.getTypeNotNull(context, expression)
    seems to be working. I figured the test code i was feeding couldnt actually compile because it was referencing external types that were missing imports in the test's input string