0
# Utilities
1
2
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.
3
4
## Capabilities
5
6
### ShadowedDeclarationsFilter
7
8
Filters out shadowed declarations in completion to provide cleaner, more relevant results.
9
10
```kotlin { .api }
11
/**
12
* Filters out shadowed declarations in completion contexts
13
* Removes declarations that are hidden by more specific declarations in the same scope
14
*/
15
class ShadowedDeclarationsFilter(
16
private val bindingContext: BindingContext,
17
private val resolutionFacade: ResolutionFacade,
18
private val context: PsiElement,
19
private val explicitReceiverValue: ReceiverValue?
20
) {
21
/**
22
* Filters a collection of declarations, removing shadowed ones
23
* @param declarations - Collection of declaration descriptors to filter
24
* @returns Filtered collection with shadowed declarations removed
25
*/
26
fun <TDescriptor : DeclarationDescriptor> filter(
27
declarations: Collection<TDescriptor>
28
): Collection<TDescriptor>
29
30
companion object {
31
/**
32
* Creates a ShadowedDeclarationsFilter for the given context
33
* @param bindingContext - Binding context from analysis
34
* @param resolutionFacade - Resolution facade for type resolution
35
* @param context - PSI element providing context
36
* @param callTypeAndReceiver - Call type and receiver information
37
* @returns ShadowedDeclarationsFilter instance or null if not applicable
38
*/
39
fun create(
40
bindingContext: BindingContext,
41
resolutionFacade: ResolutionFacade,
42
context: PsiElement,
43
callTypeAndReceiver: CallTypeAndReceiver<*, *>
44
): ShadowedDeclarationsFilter?
45
}
46
}
47
```
48
49
**Usage Examples:**
50
51
```kotlin
52
// Create filter for completion context
53
val filter = ShadowedDeclarationsFilter.create(
54
bindingContext = bindingContext,
55
resolutionFacade = resolutionFacade,
56
context = expression,
57
callTypeAndReceiver = callTypeAndReceiver
58
)
59
60
// Apply filtering to completion candidates
61
val allDescriptors: Collection<DeclarationDescriptor> = // from reference variants
62
val filteredDescriptors = filter?.filter(allDescriptors) ?: allDescriptors
63
64
// Example of shadowing:
65
// class Parent { fun method() {} }
66
// class Child : Parent() { fun method() {} } // shadows parent method
67
// In completion, only Child.method() would be shown
68
```
69
70
### FuzzyType
71
72
Represents types with free parameters for advanced completion scenarios, particularly useful for generic type inference.
73
74
```kotlin { .api }
75
/**
76
* Represents a type with free parameters for completion and type inference
77
* Useful for handling generic types and type parameters in completion
78
*/
79
class FuzzyType(
80
/** The underlying Kotlin type */
81
val type: KotlinType,
82
/** Collection of free type parameters */
83
val freeParameters: Collection<TypeParameterDescriptor>
84
) {
85
/**
86
* Checks if this fuzzy type represents a function type
87
*/
88
fun isFunctionType(): Boolean
89
90
/**
91
* Gets the nullability of the fuzzy type
92
*/
93
fun nullability(): TypeNullability
94
}
95
```
96
97
### FuzzyType Extension Functions
98
99
Extension functions for working with fuzzy types:
100
101
```kotlin { .api }
102
/**
103
* Gets the fuzzy extension receiver type for a callable descriptor
104
* @returns FuzzyType representing the extension receiver or null
105
*/
106
fun CallableDescriptor.fuzzyExtensionReceiverType(): FuzzyType?
107
108
/**
109
* Converts a Kotlin type to a fuzzy type with specified free parameters
110
* @param freeParameters - Collection of type parameters to treat as free
111
* @returns FuzzyType instance
112
*/
113
fun KotlinType.toFuzzyType(freeParameters: Collection<TypeParameterDescriptor>): FuzzyType
114
115
/**
116
* Approximates flexible types for better IDE integration
117
* @param builtIns - Built-in types for the module
118
* @param languageVersionSettings - Language version settings
119
* @returns Approximated Kotlin type
120
*/
121
fun KotlinType.approximateFlexibleTypes(
122
builtIns: KotlinBuiltIns,
123
languageVersionSettings: LanguageVersionSettings
124
): KotlinType
125
```
126
127
**Usage Examples:**
128
129
```kotlin
130
// Convert type to fuzzy type for generic inference
131
val genericFunction: FunctionDescriptor = // function with type parameters
132
val freeParams = genericFunction.typeParameters
133
val returnType = genericFunction.returnType
134
135
val fuzzyReturnType = returnType?.toFuzzyType(freeParams)
136
if (fuzzyReturnType?.isFunctionType() == true) {
137
// Handle function type completion
138
println("Return type is a function with free parameters: ${freeParams.map { it.name }}")
139
}
140
141
// Get extension receiver as fuzzy type
142
val extensionFunction: FunctionDescriptor = // extension function
143
val fuzzyReceiver = extensionFunction.fuzzyExtensionReceiverType()
144
fuzzyReceiver?.let { receiver ->
145
println("Extension receiver: ${receiver.type} with free params: ${receiver.freeParameters.size}")
146
}
147
```
148
149
### IdeDescriptorRenderersScripting
150
151
Object providing descriptor renderers optimized for IDE scenarios in scripting contexts.
152
153
```kotlin { .api }
154
/**
155
* Provides descriptor renderers for IDE scenarios in scripting contexts
156
* Contains pre-configured renderers for different presentation needs
157
*/
158
object IdeDescriptorRenderersScripting {
159
/** Renderer for source code presentation */
160
val SOURCE_CODE: DescriptorRenderer
161
162
/** Type normalizer for approximating flexible types */
163
val APPROXIMATE_FLEXIBLE_TYPES: (KotlinType) -> KotlinType
164
165
/** Renderer for short names in types */
166
val SHORT_NAMES_IN_TYPES: DescriptorRenderer
167
168
/** Renderer for function parameters */
169
val FUNCTION_PARAMETERS: DescriptorRenderer
170
}
171
```
172
173
**Usage Examples:**
174
175
```kotlin
176
// Render descriptors for completion display
177
val function: FunctionDescriptor = // function to render
178
val sourceCodePresentation = IdeDescriptorRenderersScripting.SOURCE_CODE.render(function)
179
180
// Render function parameters
181
val parametersPresentation = IdeDescriptorRenderersScripting.FUNCTION_PARAMETERS
182
.renderFunctionParameters(function)
183
184
// Render type with short names
185
val type: KotlinType = function.returnType!!
186
val shortTypePresentation = IdeDescriptorRenderersScripting.SHORT_NAMES_IN_TYPES.renderType(type)
187
188
println("Function: $sourceCodePresentation")
189
println("Parameters: $parametersPresentation")
190
println("Return type: $shortTypePresentation")
191
```
192
193
### Import and Reference Utilities
194
195
Extension functions for handling imports and references:
196
197
```kotlin { .api }
198
/**
199
* Gets the importable FqName for a declaration descriptor
200
*/
201
val DeclarationDescriptor.importableFqName: FqName?
202
203
/**
204
* Checks if a declaration can be referenced via import
205
*/
206
fun DeclarationDescriptor.canBeReferencedViaImport(): Boolean
207
208
/**
209
* Checks if a declaration can be added to imports
210
*/
211
fun DeclarationDescriptor.canBeAddedToImport(): Boolean
212
213
/**
214
* Checks if a type can be referenced via import
215
*/
216
fun KotlinType.canBeReferencedViaImport(): Boolean
217
218
/**
219
* Gets importable targets for a reference expression
220
* @param bindingContext - Binding context from analysis
221
* @returns Collection of declaration descriptors that can be imported
222
*/
223
fun KtReferenceExpression.getImportableTargets(bindingContext: BindingContext): Collection<DeclarationDescriptor>
224
```
225
226
**Usage Examples:**
227
228
```kotlin
229
// Check if descriptor can be imported
230
val descriptor: DeclarationDescriptor = // some descriptor
231
if (descriptor.canBeReferencedViaImport()) {
232
val fqName = descriptor.importableFqName
233
println("Can import: $fqName")
234
}
235
236
// Get importable targets for unresolved reference
237
val unresolvedRef: KtReferenceExpression = // unresolved reference
238
val importableTargets = unresolvedRef.getImportableTargets(bindingContext)
239
importableTargets.forEach { target ->
240
println("Possible import: ${target.importableFqName}")
241
}
242
```
243
244
### Implicit Receiver Utilities
245
246
Functions for working with implicit receivers in completion contexts:
247
248
```kotlin { .api }
249
/**
250
* Interface for creating receiver expressions
251
*/
252
interface ReceiverExpressionFactory {
253
/** Checks if the factory creates immediate receivers for the scope */
254
fun isImmediate(scope: LexicalScope): Boolean
255
256
/** Creates a receiver expression for the scope */
257
fun createReceiverExpression(scope: LexicalScope): KtExpression
258
}
259
260
/**
261
* Gets implicit receivers with instance for a lexical scope
262
* @param excludeShadowedByDslMarkers - Whether to exclude receivers shadowed by DSL markers
263
* @returns Collection of receiver parameter descriptors
264
*/
265
fun LexicalScope.getImplicitReceiversWithInstance(
266
excludeShadowedByDslMarkers: Boolean = false
267
): Collection<ReceiverParameterDescriptor>
268
269
/**
270
* Gets a factory for implicit receivers with subtype of the specified type
271
* @param receiverType - Required receiver type
272
* @returns ReceiverExpressionFactory or null if no suitable receiver
273
*/
274
fun LexicalScope.getFactoryForImplicitReceiverWithSubtypeOf(
275
receiverType: KotlinType
276
): ReceiverExpressionFactory?
277
278
/**
279
* Gets implicit receivers mapped to their expressions
280
* @param excludeShadowedByDslMarkers - Whether to exclude shadowed receivers
281
* @returns Collection of Kotlin expressions representing implicit receivers
282
*/
283
fun LexicalScope.getImplicitReceiversWithInstanceToExpression(
284
excludeShadowedByDslMarkers: Boolean = false
285
): Collection<KtExpression>
286
```
287
288
### Descriptor Utility Functions
289
290
Utility functions for working with descriptors:
291
292
```kotlin { .api }
293
/**
294
* Checks if two descriptors are equal with substitution
295
* @param descriptor1 - First descriptor
296
* @param descriptor2 - Second descriptor
297
* @param allowDifferentTypeParameters - Whether to allow different type parameters
298
* @returns true if descriptors are equivalent
299
*/
300
fun descriptorsEqualWithSubstitution(
301
descriptor1: DeclarationDescriptor?,
302
descriptor2: DeclarationDescriptor?,
303
allowDifferentTypeParameters: Boolean = false
304
): Boolean
305
306
/**
307
* Gets supertypes including Any for a type constructor
308
* @returns Collection of supertypes with Any included
309
*/
310
fun TypeConstructor.supertypesWithAny(): Collection<KotlinType>
311
```
312
313
### Descriptor Extension Properties
314
315
Extension properties for descriptor information:
316
317
```kotlin { .api }
318
/**
319
* Gets constructors for a classifier descriptor with type parameters
320
*/
321
val ClassifierDescriptorWithTypeParameters.constructors: Collection<ConstructorDescriptor>
322
323
/**
324
* Gets the class kind for a classifier descriptor
325
*/
326
val ClassifierDescriptorWithTypeParameters.kind: ClassKind?
327
328
/**
329
* Checks if a declaration descriptor is from Java
330
*/
331
val DeclarationDescriptor.isJavaDescriptor: Boolean
332
```
333
334
### Function Utility Extensions
335
336
Extensions for function descriptor handling:
337
338
```kotlin { .api }
339
/**
340
* Checks if a function should not be converted to property
341
* @param notProperties - Set of FqNames that should not be treated as properties
342
* @returns true if function should remain a function
343
*/
344
fun FunctionDescriptor.shouldNotConvertToProperty(notProperties: Set<FqNameUnsafe>): Boolean
345
346
/**
347
* Checks if a synthetic Java property is suppressed by the not-property list
348
* @param set - Set of FqNames for suppressed properties
349
* @returns true if property is suppressed
350
*/
351
fun SyntheticJavaPropertyDescriptor.suppressedByNotPropertyList(set: Set<FqNameUnsafe>): Boolean
352
```
353
354
### Smart Cast Utilities
355
356
Utilities for working with smart casts:
357
358
```kotlin { .api }
359
/**
360
* Gets smart cast variants with less specific types excluded
361
* @param receiver - Receiver value for smart cast analysis
362
* @param bindingContext - Binding context from analysis
363
* @param containingDeclarationOrModule - Context declaration or module
364
* @param dataFlowInfo - Data flow information
365
* @param languageVersionSettings - Language version settings
366
* @param dataFlowValueFactory - Factory for data flow values
367
* @returns List of smart cast types
368
*/
369
fun SmartCastManager.getSmartCastVariantsWithLessSpecificExcluded(
370
receiver: ReceiverValue,
371
bindingContext: BindingContext,
372
containingDeclarationOrModule: DeclarationDescriptor,
373
dataFlowInfo: DataFlowInfo,
374
languageVersionSettings: LanguageVersionSettings,
375
dataFlowValueFactory: DataFlowValueFactory
376
): List<KotlinType>
377
```
378
379
## Integration Examples
380
381
These utilities are used throughout the completion system:
382
383
```kotlin
384
// Example integration in completion engine
385
class CompletionEngine {
386
private fun getFilteredCompletions(
387
rawCompletions: Collection<DeclarationDescriptor>,
388
context: CompletionContext
389
): Collection<DeclarationDescriptor> {
390
// Apply shadowed declaration filtering
391
val shadowedFilter = ShadowedDeclarationsFilter.create(
392
bindingContext = context.bindingContext,
393
resolutionFacade = context.resolutionFacade,
394
context = context.position,
395
callTypeAndReceiver = context.callTypeAndReceiver
396
)
397
398
var filtered = shadowedFilter?.filter(rawCompletions) ?: rawCompletions
399
400
// Filter out non-importable items for import contexts
401
if (context.callTypeAndReceiver.callType == CallType.IMPORT_DIRECTIVE) {
402
filtered = filtered.filter { it.canBeReferencedViaImport() }
403
}
404
405
return filtered
406
}
407
}