CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-kotlin--kotlin-scripting-ide-services

Kotlin Scripting Compiler extension providing code completion and static analysis for IDE integration

Pending
Overview
Eval results
Files

resolution.mddocs/

Resolution Services

Core resolution services providing symbol resolution, reference finding, and IDE-like analysis capabilities for Kotlin scripts. These services enable the compiler to understand code context and provide accurate completions and diagnostics.

Capabilities

ResolutionFacade

Central interface for Kotlin resolution services, providing access to analysis results and compiler services.

/**
 * Central interface for Kotlin resolution services in IDE contexts
 * Provides access to analysis results, compiler services, and resolution utilities
 */
interface ResolutionFacade {
    /** The IntelliJ project context */
    val project: Project
    
    /** The module descriptor for the current module */
    val moduleDescriptor: ModuleDescriptor
    
    /**
     * Performs comprehensive analysis with all compiler checks
     * @param elements - Collection of Kotlin elements to analyze
     * @param callback - Optional callback for handling diagnostics
     * @returns AnalysisResult containing binding context and diagnostics
     */
    fun analyzeWithAllCompilerChecks(
        elements: Collection<KtElement>,
        callback: DiagnosticSink.DiagnosticsCallback? = null
    ): AnalysisResult
    
    /**
     * Gets a frontend service instance for the specified service class
     * @param serviceClass - Class of the service to retrieve
     * @returns Service instance
     */
    @FrontendInternals
    fun <T : Any> getFrontendService(serviceClass: Class<T>): T
    
    /**
     * Gets an IDE service instance for the specified service class
     * @param serviceClass - Class of the service to retrieve
     * @returns Service instance
     */
    fun <T : Any> getIdeService(serviceClass: Class<T>): T
    
    /**
     * Gets a frontend service for a specific PSI element
     * @param element - PSI element context
     * @param serviceClass - Class of the service to retrieve
     * @returns Service instance
     */
    @FrontendInternals
    fun <T : Any> getFrontendService(element: PsiElement, serviceClass: Class<T>): T
    
    /**
     * Attempts to get a frontend service, returning null if unavailable
     * @param element - PSI element context
     * @param serviceClass - Class of the service to retrieve
     * @returns Service instance or null
     */
    @FrontendInternals
    fun <T : Any> tryGetFrontendService(element: PsiElement, serviceClass: Class<T>): T?
    
    /**
     * Gets a frontend service for a specific module descriptor
     * @param moduleDescriptor - Module descriptor context
     * @param serviceClass - Class of the service to retrieve
     * @returns Service instance
     */
    @FrontendInternals
    fun <T : Any> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T
    
    /**
     * Gets the resolver for the current project
     * @returns ResolverForProject instance
     */
    fun getResolverForProject(): ResolverForProject<out ModuleInfo>
}

Usage Examples:

// Using ResolutionFacade for analysis
val resolutionFacade: ResolutionFacade = // obtained from compiler
val elements: Collection<KtElement> = // elements to analyze

// Perform full analysis
val analysisResult = resolutionFacade.analyzeWithAllCompilerChecks(elements) { diagnostics ->
    // Handle diagnostics during analysis
    diagnostics.forEach { diagnostic ->
        println("${diagnostic.severity}: ${diagnostic.factoryName}")
    }
}

// Access binding context and diagnostics
val bindingContext = analysisResult.bindingContext
val diagnostics = analysisResult.diagnostics

// Get language version settings
val languageVersionSettings = resolutionFacade.getLanguageVersionSettings()

Extension Functions

Convenient extension functions for common resolution operations:

/**
 * Inline extension for getting frontend services with reified type parameters
 */
inline fun <reified T : Any> ResolutionFacade.frontendService(): T

/**
 * Gets the language version settings for the resolution facade
 */
fun ResolutionFacade.getLanguageVersionSettings(): LanguageVersionSettings

/**
 * Gets the data flow value factory for the resolution facade
 */
fun ResolutionFacade.getDataFlowValueFactory(): DataFlowValueFactory

ReferenceVariantsHelper

Helper class for finding reference variants and completion candidates in Kotlin code.

/**
 * Helper for finding reference variants and completions in Kotlin code
 * Provides methods for getting completion candidates based on context
 */
class ReferenceVariantsHelper(
    private val bindingContext: BindingContext,
    private val resolutionFacade: ResolutionFacade,
    private val moduleDescriptor: ModuleDescriptor,
    private val visibilityFilter: (DeclarationDescriptor) -> Boolean,
    private val notProperties: Set<FqNameUnsafe> = emptySet()
) {
    /**
     * Gets reference variants for a simple name expression
     * @param expression - The expression to find variants for
     * @param kindFilter - Filter for descriptor kinds (functions, properties, etc.)
     * @param nameFilter - Filter for names
     * @param filterOutJavaGettersAndSetters - Whether to filter Java getters/setters
     * @param filterOutShadowed - Whether to filter shadowed declarations
     * @param excludeNonInitializedVariable - Whether to exclude uninitialized variables
     * @param useReceiverType - Optional receiver type for member completion
     * @returns Collection of declaration descriptors
     */
    fun getReferenceVariants(
        expression: KtSimpleNameExpression,
        kindFilter: DescriptorKindFilter,
        nameFilter: (Name) -> Boolean,
        filterOutJavaGettersAndSetters: Boolean = false,
        filterOutShadowed: Boolean = true,
        excludeNonInitializedVariable: Boolean = false,
        useReceiverType: KotlinType? = null
    ): Collection<DeclarationDescriptor>
    
    /**
     * Gets reference variants for a context element with call type and receiver
     * @param contextElement - PSI element providing context
     * @param callTypeAndReceiver - Call type and receiver information
     * @param kindFilter - Filter for descriptor kinds
     * @param nameFilter - Filter for names
     * @param filterOutJavaGettersAndSetters - Whether to filter Java getters/setters
     * @param filterOutShadowed - Whether to filter shadowed declarations
     * @returns Collection of declaration descriptors
     */
    fun getReferenceVariants(
        contextElement: PsiElement,
        callTypeAndReceiver: CallTypeAndReceiver<*, *>,
        kindFilter: DescriptorKindFilter,
        nameFilter: (Name) -> Boolean,
        filterOutJavaGettersAndSetters: Boolean = false,
        filterOutShadowed: Boolean = true
    ): Collection<DeclarationDescriptor>
    
    /**
     * Filters out Java getter and setter methods from variants
     */
    fun <TDescriptor : DeclarationDescriptor> filterOutJavaGettersAndSetters(
        variants: Collection<TDescriptor>
    ): Collection<TDescriptor>
    
    /**
     * Excludes non-initialized variables from completion variants
     */
    fun excludeNonInitializedVariable(
        variants: Collection<DeclarationDescriptor>,
        contextElement: PsiElement
    ): Collection<DeclarationDescriptor>
}

Usage Examples:

// Create reference variants helper
val helper = ReferenceVariantsHelper(
    bindingContext = bindingContext,
    resolutionFacade = resolutionFacade, 
    moduleDescriptor = moduleDescriptor,
    visibilityFilter = { descriptor -> 
        // Custom visibility logic
        descriptor.visibility.isVisible(
            receiver = null,
            what = descriptor,
            from = currentDescriptor
        )
    }
)

// Get completion variants for a simple expression
val expression: KtSimpleNameExpression = // PSI element
val variants = helper.getReferenceVariants(
    expression = expression,
    kindFilter = DescriptorKindFilter.ALL,
    nameFilter = { name -> name.identifier.startsWith("get") },
    filterOutShadowed = true,
    excludeNonInitializedVariable = true
)

// Process variants
variants.forEach { descriptor ->
    when (descriptor) {
        is FunctionDescriptor -> println("Function: ${descriptor.name}")
        is PropertyDescriptor -> println("Property: ${descriptor.name}")
        is ClassDescriptor -> println("Class: ${descriptor.name}")
    }
}

Scope Resolution Extensions

Extension functions for working with resolution scopes and PSI elements:

/**
 * Gets the resolution scope for a PSI element
 * @param bindingContext - Binding context from analysis
 * @returns LexicalScope or null if not available
 */
fun PsiElement.getResolutionScope(bindingContext: BindingContext): LexicalScope?

/**
 * Gets the resolution scope for a PSI element with fallback resolution
 * @param bindingContext - Binding context from analysis  
 * @param resolutionFacade - Resolution facade for fallback resolution
 * @returns LexicalScope (never null)
 */
fun PsiElement.getResolutionScope(
    bindingContext: BindingContext, 
    resolutionFacade: ResolutionFacade
): LexicalScope

/**
 * Gets the file-level resolution scope
 * @param file - Kotlin file to get scope for
 * @returns LexicalScope for the file
 */
fun ResolutionFacade.getFileResolutionScope(file: KtFile): LexicalScope

Advanced Resolution Functions

Additional utility functions for complex resolution scenarios:

/**
 * Collects synthetic static members and constructors for a resolution scope
 */
fun ResolutionScope.collectSyntheticStaticMembersAndConstructors(
    kindFilter: DescriptorKindFilter,
    nameFilter: (Name) -> Boolean,
    location: LookupLocation
): List<FunctionDescriptor>

/**
 * Forces enabling of SAM adapters in synthetic scopes
 */
fun SyntheticScopes.forceEnableSamAdapters(): SyntheticScopes

Integration with REPL Compiler

The resolution services are automatically integrated with the REPL compiler:

// Internal usage within KJvmReplCompilerWithIdeServices
val analyzeResult = analyzeWithCursor(messageCollector, snippet, configuration, cursor)

with(analyzeResult.valueOr { return it }) {
    // Uses resolution facade for completion
    return getKJvmCompletion(
        ktScript,
        bindingContext,
        resolutionFacade, // ResolutionFacade instance
        moduleDescriptor,
        cursorAbs,
        configuration
    ).asSuccess(messageCollector.diagnostics)
}

Error Handling

Resolution operations may fail in various scenarios:

  • Missing dependencies: Required libraries not available in classpath
  • Compilation errors: Syntax or semantic errors preventing resolution
  • Context issues: Invalid PSI element or binding context
  • Service unavailability: Required compiler services not initialized

Always check for null returns and handle exceptions appropriately when using resolution services directly.

Install with Tessl CLI

npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-scripting-ide-services

docs

call-types.md

completion-config.md

index.md

repl-compiler.md

resolution.md

utilities.md

tile.json