or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

call-types.mdcompletion-config.mdindex.mdrepl-compiler.mdresolution.mdutilities.md

call-types.mddocs/

0

# Call Type Detection

1

2

Advanced call context analysis for determining the type of call being made and providing appropriate completion suggestions. This system analyzes the syntactic context around the cursor to provide context-aware completions.

3

4

## Capabilities

5

6

### CallType

7

8

Sealed class hierarchy representing different types of calls that can occur in Kotlin code.

9

10

```kotlin { .api }

11

/**

12

* Represents the type of call being made in Kotlin code

13

* Used for context-aware completion and analysis

14

*/

15

sealed class CallType<TReceiver : KtElement?>

16

17

/**

18

* Unknown or unrecognized call context

19

*/

20

object UNKNOWN : CallType<Nothing?>

21

22

/**

23

* Default call context (no specific receiver)

24

*/

25

object DEFAULT : CallType<Nothing?>

26

27

/**

28

* Dot call (receiver.member)

29

*/

30

object DOT : CallType<KtExpression>

31

32

/**

33

* Safe call (receiver?.member)

34

*/

35

object SAFE : CallType<KtExpression>

36

37

/**

38

* Super member access (super.member)

39

*/

40

object SUPER_MEMBERS : CallType<KtSuperExpression>

41

42

/**

43

* Infix function call (receiver infix function)

44

*/

45

object INFIX : CallType<KtExpression>

46

47

/**

48

* Operator call (receiver + other)

49

*/

50

object OPERATOR : CallType<KtExpression>

51

52

/**

53

* Callable reference (::member or receiver::member)

54

*/

55

object CALLABLE_REFERENCE : CallType<KtExpression?>

56

57

/**

58

* Import directive context (import package.member)

59

*/

60

object IMPORT_DIRECTIVE : CallType<Nothing?>

61

62

/**

63

* Package directive context (package name.subpackage)

64

*/

65

object PACKAGE_DIRECTIVE : CallType<Nothing?>

66

67

/**

68

* Type context (for type annotations, generic parameters)

69

*/

70

object TYPE : CallType<Nothing?>

71

72

/**

73

* Delegate context (by delegate)

74

*/

75

object DELEGATE : CallType<Nothing?>

76

77

/**

78

* Annotation context (@Annotation)

79

*/

80

object ANNOTATION : CallType<Nothing?>

81

```

82

83

### CallTypeAndReceiver

84

85

Combines call type information with receiver details for comprehensive context analysis.

86

87

```kotlin { .api }

88

/**

89

* Combines call type with receiver information for completion context

90

* Provides both the type of call and the receiver element

91

*/

92

sealed class CallTypeAndReceiver<TReceiver : KtElement?, out TCallType : CallType<TReceiver>> {

93

abstract val callType: TCallType

94

abstract val receiver: TReceiver

95

96

/**

97

* Detects the call type and receiver for a given expression

98

* @param expression - The simple name expression to analyze

99

* @returns CallTypeAndReceiver instance with detected context

100

*/

101

companion object {

102

fun detect(expression: KtSimpleNameExpression): CallTypeAndReceiver<*, *>

103

}

104

}

105

106

/**

107

* Dot call with receiver (receiver.member)

108

*/

109

data class DOT<TReceiver : KtExpression>(

110

override val receiver: TReceiver

111

) : CallTypeAndReceiver<TReceiver, CallType.DOT>() {

112

override val callType: CallType.DOT get() = CallType.DOT

113

}

114

115

/**

116

* Safe call with receiver (receiver?.member)

117

*/

118

data class SAFE<TReceiver : KtExpression>(

119

override val receiver: TReceiver

120

) : CallTypeAndReceiver<TReceiver, CallType.SAFE>() {

121

override val callType: CallType.SAFE get() = CallType.SAFE

122

}

123

124

/**

125

* Super member access (super.member)

126

*/

127

data class SUPER_MEMBERS<TReceiver : KtSuperExpression>(

128

override val receiver: TReceiver

129

) : CallTypeAndReceiver<TReceiver, CallType.SUPER_MEMBERS>() {

130

override val callType: CallType.SUPER_MEMBERS get() = CallType.SUPER_MEMBERS

131

}

132

133

/**

134

* Infix call with receiver (receiver infix function)

135

*/

136

data class INFIX<TReceiver : KtExpression>(

137

override val receiver: TReceiver

138

) : CallTypeAndReceiver<TReceiver, CallType.INFIX>() {

139

override val callType: CallType.INFIX get() = CallType.INFIX

140

}

141

142

/**

143

* Operator call with receiver (receiver + other)

144

*/

145

data class OPERATOR<TReceiver : KtExpression>(

146

override val receiver: TReceiver

147

) : CallTypeAndReceiver<TReceiver, CallType.OPERATOR>() {

148

override val callType: CallType.OPERATOR get() = CallType.OPERATOR

149

}

150

151

/**

152

* Callable reference (::member or receiver::member)

153

*/

154

data class CALLABLE_REFERENCE<TReceiver : KtExpression?>(

155

override val receiver: TReceiver

156

) : CallTypeAndReceiver<TReceiver, CallType.CALLABLE_REFERENCE>() {

157

override val callType: CallType.CALLABLE_REFERENCE get() = CallType.CALLABLE_REFERENCE

158

}

159

160

/**

161

* Default context (no specific receiver)

162

*/

163

object DEFAULT : CallTypeAndReceiver<Nothing?, CallType.DEFAULT>() {

164

override val callType: CallType.DEFAULT get() = CallType.DEFAULT

165

override val receiver: Nothing? get() = null

166

}

167

168

/**

169

* Unknown context

170

*/

171

object UNKNOWN : CallTypeAndReceiver<Nothing?, CallType.UNKNOWN>() {

172

override val callType: CallType.UNKNOWN get() = CallType.UNKNOWN

173

override val receiver: Nothing? get() = null

174

}

175

```

176

177

**Usage Examples:**

178

179

```kotlin

180

// Detect call type from expression

181

val expression: KtSimpleNameExpression = // PSI element at cursor

182

val callTypeAndReceiver = CallTypeAndReceiver.detect(expression)

183

184

when (callTypeAndReceiver) {

185

is CallTypeAndReceiver.DOT -> {

186

println("Dot call on receiver: ${callTypeAndReceiver.receiver.text}")

187

// Provide member completions for the receiver type

188

}

189

is CallTypeAndReceiver.SAFE -> {

190

println("Safe call on receiver: ${callTypeAndReceiver.receiver.text}")

191

// Provide nullable member completions

192

}

193

is CallTypeAndReceiver.DEFAULT -> {

194

println("Default context - no specific receiver")

195

// Provide local variables, functions, and imports

196

}

197

is CallTypeAndReceiver.SUPER_MEMBERS -> {

198

println("Super member access")

199

// Provide super class member completions

200

}

201

else -> {

202

println("Other call type: ${callTypeAndReceiver.callType}")

203

}

204

}

205

```

206

207

### ReceiverType

208

209

Data class representing receiver type information for completion context.

210

211

```kotlin { .api }

212

/**

213

* Represents receiver type information for completion

214

* Contains the Kotlin type and additional metadata about the receiver

215

*/

216

data class ReceiverType(

217

/** The Kotlin type of the receiver */

218

val type: KotlinType,

219

/** Index of the receiver in implicit receiver chain */

220

val receiverIndex: Int,

221

/** Optional implicit receiver value */

222

val implicitValue: ReceiverValue?

223

) {

224

/**

225

* Extracts DSL markers from the receiver type

226

* @returns Collection of annotation class IDs representing DSL markers

227

*/

228

fun extractDslMarkers(): Collection<ClassId>

229

}

230

```

231

232

### Receiver Type Resolution

233

234

Functions for resolving receiver types from call context:

235

236

```kotlin { .api }

237

/**

238

* Gets the receiver types for a call type and receiver

239

* @param bindingContext - Binding context from analysis

240

* @param contextElement - PSI element providing context

241

* @param moduleDescriptor - Module descriptor for resolution

242

* @param resolutionFacade - Resolution facade for type resolution

243

* @param stableSmartCastsOnly - Whether to only consider stable smart casts

244

* @param withImplicitReceiversWhenExplicitPresent - Include implicit receivers even with explicit receiver

245

* @returns List of Kotlin types for the receivers

246

*/

247

fun CallTypeAndReceiver<*, *>.receiverTypes(

248

bindingContext: BindingContext,

249

contextElement: PsiElement,

250

moduleDescriptor: ModuleDescriptor,

251

resolutionFacade: ResolutionFacade,

252

stableSmartCastsOnly: Boolean,

253

withImplicitReceiversWhenExplicitPresent: Boolean = false

254

): List<KotlinType>?

255

256

/**

257

* Gets receiver types with index information

258

* @param bindingContext - Binding context from analysis

259

* @param contextElement - PSI element providing context

260

* @param moduleDescriptor - Module descriptor for resolution

261

* @param resolutionFacade - Resolution facade for type resolution

262

* @param stableSmartCastsOnly - Whether to only consider stable smart casts

263

* @param withImplicitReceiversWhenExplicitPresent - Include implicit receivers even with explicit receiver

264

* @returns List of ReceiverType objects with detailed information

265

*/

266

fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(

267

bindingContext: BindingContext,

268

contextElement: PsiElement,

269

moduleDescriptor: ModuleDescriptor,

270

resolutionFacade: ResolutionFacade,

271

stableSmartCastsOnly: Boolean,

272

withImplicitReceiversWhenExplicitPresent: Boolean = false

273

): List<ReceiverType>?

274

```

275

276

**Usage Examples:**

277

278

```kotlin

279

// Get receiver types for completion

280

val callTypeAndReceiver = CallTypeAndReceiver.detect(expression)

281

val receiverTypes = callTypeAndReceiver.receiverTypes(

282

bindingContext = bindingContext,

283

contextElement = expression,

284

moduleDescriptor = moduleDescriptor,

285

resolutionFacade = resolutionFacade,

286

stableSmartCastsOnly = true

287

)

288

289

receiverTypes?.forEach { receiverType ->

290

println("Receiver type: ${receiverType}")

291

// Get members for this receiver type

292

val members = receiverType.memberScope.getContributedDescriptors()

293

// Process members for completion

294

}

295

296

// Get detailed receiver information

297

val receiverTypesWithIndex = callTypeAndReceiver.receiverTypesWithIndex(

298

bindingContext = bindingContext,

299

contextElement = expression,

300

moduleDescriptor = moduleDescriptor,

301

resolutionFacade = resolutionFacade,

302

stableSmartCastsOnly = true

303

)

304

305

receiverTypesWithIndex?.forEach { receiverType ->

306

println("Receiver ${receiverType.receiverIndex}: ${receiverType.type}")

307

receiverType.implicitValue?.let { implicit ->

308

println(" Implicit value: $implicit")

309

}

310

311

// Extract DSL markers for context-aware completion

312

val dslMarkers = receiverType.extractDslMarkers()

313

if (dslMarkers.isNotEmpty()) {

314

println(" DSL markers: ${dslMarkers.joinToString()}")

315

}

316

}

317

```

318

319

## Integration with Completion System

320

321

The call type detection system is automatically used by the completion engine:

322

323

```kotlin

324

// Internal usage in completion system

325

private val getDescriptorsQualified = ResultGetter { element, options ->

326

val expression = element.thisOrParent<KtQualifiedExpression>() ?: return@ResultGetter null

327

328

val receiverExpression = expression.receiverExpression

329

val expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiverExpression)?.type

330

331

DescriptorsResult(targetElement = expression).apply {

332

if (expressionType != null) {

333

sortNeeded = false

334

descriptors.addAll(

335

getVariantsHelper { true }

336

.getReferenceVariants(

337

receiverExpression,

338

CallTypeAndReceiver.DOT(receiverExpression), // Using call type detection

339

DescriptorKindFilter.ALL,

340

ALL_NAME_FILTER,

341

filterOutShadowed = options.filterOutShadowedDescriptors,

342

)

343

)

344

}

345

}

346

}

347

```

348

349

## Context-Aware Completion Scenarios

350

351

Different call types enable different completion strategies:

352

353

### Dot Call Completion

354

```kotlin

355

val list = listOf(1, 2, 3)

356

list. // DOT call type

357

// Provides: map, filter, size, isEmpty, etc.

358

```

359

360

### Safe Call Completion

361

```kotlin

362

val nullable: String? = "hello"

363

nullable?. // SAFE call type

364

// Provides: length, uppercase, lowercase, etc. (nullable context)

365

```

366

367

### Super Member Completion

368

```kotlin

369

class Child : Parent() {

370

override fun method() {

371

super. // SUPER_MEMBERS call type

372

// Provides: parent class members only

373

}

374

}

375

```

376

377

### Import Completion

378

```kotlin

379

import kotlin.collections. // IMPORT_DIRECTIVE call type

380

// Provides: package members and subpackages

381

```

382

383

### Type Context Completion

384

```kotlin

385

fun method(): List< // TYPE call type

386

// Provides: type names, generic parameters

387

```