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

utilities.mddocs/

Utilities

Various utility classes for filtering, type handling, and descriptor management in IDE contexts. These utilities support advanced completion scenarios and provide essential functionality for the scripting IDE services.

Capabilities

ShadowedDeclarationsFilter

Filters out shadowed declarations in completion to provide cleaner, more relevant results.

/**
 * Filters out shadowed declarations in completion contexts
 * Removes declarations that are hidden by more specific declarations in the same scope
 */
class ShadowedDeclarationsFilter(
    private val bindingContext: BindingContext,
    private val resolutionFacade: ResolutionFacade,
    private val context: PsiElement,
    private val explicitReceiverValue: ReceiverValue?
) {
    /**
     * Filters a collection of declarations, removing shadowed ones
     * @param declarations - Collection of declaration descriptors to filter
     * @returns Filtered collection with shadowed declarations removed
     */
    fun <TDescriptor : DeclarationDescriptor> filter(
        declarations: Collection<TDescriptor>
    ): Collection<TDescriptor>
    
    companion object {
        /**
         * Creates a ShadowedDeclarationsFilter for the given context
         * @param bindingContext - Binding context from analysis
         * @param resolutionFacade - Resolution facade for type resolution
         * @param context - PSI element providing context
         * @param callTypeAndReceiver - Call type and receiver information
         * @returns ShadowedDeclarationsFilter instance or null if not applicable
         */
        fun create(
            bindingContext: BindingContext,
            resolutionFacade: ResolutionFacade,
            context: PsiElement,
            callTypeAndReceiver: CallTypeAndReceiver<*, *>
        ): ShadowedDeclarationsFilter?
    }
}

Usage Examples:

// Create filter for completion context
val filter = ShadowedDeclarationsFilter.create(
    bindingContext = bindingContext,
    resolutionFacade = resolutionFacade,
    context = expression,
    callTypeAndReceiver = callTypeAndReceiver
)

// Apply filtering to completion candidates
val allDescriptors: Collection<DeclarationDescriptor> = // from reference variants
val filteredDescriptors = filter?.filter(allDescriptors) ?: allDescriptors

// Example of shadowing:
// class Parent { fun method() {} }
// class Child : Parent() { fun method() {} } // shadows parent method
// In completion, only Child.method() would be shown

FuzzyType

Represents types with free parameters for advanced completion scenarios, particularly useful for generic type inference.

/**
 * Represents a type with free parameters for completion and type inference
 * Useful for handling generic types and type parameters in completion
 */
class FuzzyType(
    /** The underlying Kotlin type */
    val type: KotlinType,  
    /** Collection of free type parameters */
    val freeParameters: Collection<TypeParameterDescriptor>
) {
    /**
     * Checks if this fuzzy type represents a function type
     */
    fun isFunctionType(): Boolean
    
    /**
     * Gets the nullability of the fuzzy type
     */
    fun nullability(): TypeNullability
}

FuzzyType Extension Functions

Extension functions for working with fuzzy types:

/**
 * Gets the fuzzy extension receiver type for a callable descriptor
 * @returns FuzzyType representing the extension receiver or null
 */
fun CallableDescriptor.fuzzyExtensionReceiverType(): FuzzyType?

/**
 * Converts a Kotlin type to a fuzzy type with specified free parameters
 * @param freeParameters - Collection of type parameters to treat as free
 * @returns FuzzyType instance
 */
fun KotlinType.toFuzzyType(freeParameters: Collection<TypeParameterDescriptor>): FuzzyType

/**
 * Approximates flexible types for better IDE integration
 * @param builtIns - Built-in types for the module
 * @param languageVersionSettings - Language version settings
 * @returns Approximated Kotlin type
 */
fun KotlinType.approximateFlexibleTypes(
    builtIns: KotlinBuiltIns,
    languageVersionSettings: LanguageVersionSettings
): KotlinType

Usage Examples:

// Convert type to fuzzy type for generic inference
val genericFunction: FunctionDescriptor = // function with type parameters
val freeParams = genericFunction.typeParameters
val returnType = genericFunction.returnType

val fuzzyReturnType = returnType?.toFuzzyType(freeParams)
if (fuzzyReturnType?.isFunctionType() == true) {
    // Handle function type completion
    println("Return type is a function with free parameters: ${freeParams.map { it.name }}")
}

// Get extension receiver as fuzzy type
val extensionFunction: FunctionDescriptor = // extension function
val fuzzyReceiver = extensionFunction.fuzzyExtensionReceiverType()
fuzzyReceiver?.let { receiver ->
    println("Extension receiver: ${receiver.type} with free params: ${receiver.freeParameters.size}")
}

IdeDescriptorRenderersScripting

Object providing descriptor renderers optimized for IDE scenarios in scripting contexts.

/**
 * Provides descriptor renderers for IDE scenarios in scripting contexts
 * Contains pre-configured renderers for different presentation needs
 */
object IdeDescriptorRenderersScripting {
    /** Renderer for source code presentation */
    val SOURCE_CODE: DescriptorRenderer
    
    /** Type normalizer for approximating flexible types */
    val APPROXIMATE_FLEXIBLE_TYPES: (KotlinType) -> KotlinType
    
    /** Renderer for short names in types */
    val SHORT_NAMES_IN_TYPES: DescriptorRenderer
    
    /** Renderer for function parameters */
    val FUNCTION_PARAMETERS: DescriptorRenderer
}

Usage Examples:

// Render descriptors for completion display
val function: FunctionDescriptor = // function to render
val sourceCodePresentation = IdeDescriptorRenderersScripting.SOURCE_CODE.render(function)

// Render function parameters
val parametersPresentation = IdeDescriptorRenderersScripting.FUNCTION_PARAMETERS
    .renderFunctionParameters(function)

// Render type with short names
val type: KotlinType = function.returnType!!
val shortTypePresentation = IdeDescriptorRenderersScripting.SHORT_NAMES_IN_TYPES.renderType(type)

println("Function: $sourceCodePresentation")
println("Parameters: $parametersPresentation") 
println("Return type: $shortTypePresentation")

Import and Reference Utilities

Extension functions for handling imports and references:

/**
 * Gets the importable FqName for a declaration descriptor
 */
val DeclarationDescriptor.importableFqName: FqName?

/**
 * Checks if a declaration can be referenced via import
 */
fun DeclarationDescriptor.canBeReferencedViaImport(): Boolean

/**
 * Checks if a declaration can be added to imports
 */
fun DeclarationDescriptor.canBeAddedToImport(): Boolean

/**
 * Checks if a type can be referenced via import
 */
fun KotlinType.canBeReferencedViaImport(): Boolean

/**
 * Gets importable targets for a reference expression
 * @param bindingContext - Binding context from analysis
 * @returns Collection of declaration descriptors that can be imported
 */
fun KtReferenceExpression.getImportableTargets(bindingContext: BindingContext): Collection<DeclarationDescriptor>

Usage Examples:

// Check if descriptor can be imported
val descriptor: DeclarationDescriptor = // some descriptor
if (descriptor.canBeReferencedViaImport()) {
    val fqName = descriptor.importableFqName
    println("Can import: $fqName")
}

// Get importable targets for unresolved reference
val unresolvedRef: KtReferenceExpression = // unresolved reference
val importableTargets = unresolvedRef.getImportableTargets(bindingContext)
importableTargets.forEach { target ->
    println("Possible import: ${target.importableFqName}")
}

Implicit Receiver Utilities

Functions for working with implicit receivers in completion contexts:

/**
 * Interface for creating receiver expressions
 */
interface ReceiverExpressionFactory {
    /** Checks if the factory creates immediate receivers for the scope */
    fun isImmediate(scope: LexicalScope): Boolean
    
    /** Creates a receiver expression for the scope */
    fun createReceiverExpression(scope: LexicalScope): KtExpression
}

/**
 * Gets implicit receivers with instance for a lexical scope
 * @param excludeShadowedByDslMarkers - Whether to exclude receivers shadowed by DSL markers
 * @returns Collection of receiver parameter descriptors
 */
fun LexicalScope.getImplicitReceiversWithInstance(
    excludeShadowedByDslMarkers: Boolean = false
): Collection<ReceiverParameterDescriptor>

/**
 * Gets a factory for implicit receivers with subtype of the specified type
 * @param receiverType - Required receiver type
 * @returns ReceiverExpressionFactory or null if no suitable receiver
 */
fun LexicalScope.getFactoryForImplicitReceiverWithSubtypeOf(
    receiverType: KotlinType
): ReceiverExpressionFactory?

/**
 * Gets implicit receivers mapped to their expressions
 * @param excludeShadowedByDslMarkers - Whether to exclude shadowed receivers
 * @returns Collection of Kotlin expressions representing implicit receivers
 */
fun LexicalScope.getImplicitReceiversWithInstanceToExpression(
    excludeShadowedByDslMarkers: Boolean = false
): Collection<KtExpression>

Descriptor Utility Functions

Utility functions for working with descriptors:

/**
 * Checks if two descriptors are equal with substitution
 * @param descriptor1 - First descriptor
 * @param descriptor2 - Second descriptor  
 * @param allowDifferentTypeParameters - Whether to allow different type parameters
 * @returns true if descriptors are equivalent
 */
fun descriptorsEqualWithSubstitution(
    descriptor1: DeclarationDescriptor?,
    descriptor2: DeclarationDescriptor?,
    allowDifferentTypeParameters: Boolean = false
): Boolean

/**
 * Gets supertypes including Any for a type constructor
 * @returns Collection of supertypes with Any included
 */
fun TypeConstructor.supertypesWithAny(): Collection<KotlinType>

Descriptor Extension Properties

Extension properties for descriptor information:

/**
 * Gets constructors for a classifier descriptor with type parameters
 */
val ClassifierDescriptorWithTypeParameters.constructors: Collection<ConstructorDescriptor>

/**
 * Gets the class kind for a classifier descriptor
 */
val ClassifierDescriptorWithTypeParameters.kind: ClassKind?

/**
 * Checks if a declaration descriptor is from Java
 */
val DeclarationDescriptor.isJavaDescriptor: Boolean

Function Utility Extensions

Extensions for function descriptor handling:

/**
 * Checks if a function should not be converted to property
 * @param notProperties - Set of FqNames that should not be treated as properties
 * @returns true if function should remain a function
 */
fun FunctionDescriptor.shouldNotConvertToProperty(notProperties: Set<FqNameUnsafe>): Boolean

/**
 * Checks if a synthetic Java property is suppressed by the not-property list
 * @param set - Set of FqNames for suppressed properties
 * @returns true if property is suppressed
 */
fun SyntheticJavaPropertyDescriptor.suppressedByNotPropertyList(set: Set<FqNameUnsafe>): Boolean

Smart Cast Utilities

Utilities for working with smart casts:

/**
 * Gets smart cast variants with less specific types excluded
 * @param receiver - Receiver value for smart cast analysis
 * @param bindingContext - Binding context from analysis
 * @param containingDeclarationOrModule - Context declaration or module
 * @param dataFlowInfo - Data flow information
 * @param languageVersionSettings - Language version settings
 * @param dataFlowValueFactory - Factory for data flow values
 * @returns List of smart cast types
 */
fun SmartCastManager.getSmartCastVariantsWithLessSpecificExcluded(
    receiver: ReceiverValue,
    bindingContext: BindingContext,
    containingDeclarationOrModule: DeclarationDescriptor,
    dataFlowInfo: DataFlowInfo,
    languageVersionSettings: LanguageVersionSettings,
    dataFlowValueFactory: DataFlowValueFactory
): List<KotlinType>

Integration Examples

These utilities are used throughout the completion system:

// Example integration in completion engine
class CompletionEngine {
    private fun getFilteredCompletions(
        rawCompletions: Collection<DeclarationDescriptor>,
        context: CompletionContext
    ): Collection<DeclarationDescriptor> {
        // Apply shadowed declaration filtering
        val shadowedFilter = ShadowedDeclarationsFilter.create(
            bindingContext = context.bindingContext,
            resolutionFacade = context.resolutionFacade,
            context = context.position,
            callTypeAndReceiver = context.callTypeAndReceiver
        )
        
        var filtered = shadowedFilter?.filter(rawCompletions) ?: rawCompletions
        
        // Filter out non-importable items for import contexts
        if (context.callTypeAndReceiver.callType == CallType.IMPORT_DIRECTIVE) {
            filtered = filtered.filter { it.canBeReferencedViaImport() }
        }
        
        return filtered
    }
}

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