Kotlin Scripting Compiler extension providing code completion and static analysis for IDE integration
—
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.
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()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(): DataFlowValueFactoryHelper 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}")
}
}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): LexicalScopeAdditional 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(): SyntheticScopesThe 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)
}Resolution operations may fail in various scenarios:
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