or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

compiler-entry-points.mdconfiguration-system.mdhigh-level-api.mdincremental-compilation.mdindex.mdmessage-collection.mdplugin-system.md

incremental-compilation.mddocs/

0

# Incremental Compilation Support

1

2

Advanced incremental compilation capabilities with change tracking, dependency analysis, and compilation optimization. The incremental compilation system minimizes compilation time by only recompiling changed sources and their dependencies.

3

4

## Capabilities

5

6

### IncrementalCompilationComponents

7

8

Main interface providing incremental compilation services and tracking components.

9

10

```kotlin { .api }

11

/**

12

* Main interface for incremental compilation functionality

13

* Provides tracking components for optimization and change detection

14

*/

15

interface IncrementalCompilationComponents {

16

/** Symbol lookup tracker for dependency analysis */

17

val lookupTracker: LookupTracker

18

19

/** Multiplatform expect/actual tracker */

20

val expectActualTracker: ExpectActualTracker

21

22

/** Inline constant usage tracker */

23

val inlineConstTracker: InlineConstTracker

24

25

/** Enum when exhaustiveness tracker */

26

val enumWhenTracker: EnumWhenTracker

27

28

/** Import statement tracker */

29

val importTracker: ImportTracker

30

31

companion object {

32

/** Create default incremental compilation components */

33

fun create(): IncrementalCompilationComponents

34

35

/** Create with custom configuration */

36

fun create(configuration: IncrementalCompilationConfiguration): IncrementalCompilationComponents

37

}

38

}

39

```

40

41

**Usage Examples:**

42

43

```kotlin

44

// Setup incremental compilation

45

val incrementalComponents = IncrementalCompilationComponents.create()

46

47

val configuration = CompilerConfiguration().apply {

48

put(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS, incrementalComponents)

49

}

50

51

val compiler = K2JVMCompiler()

52

val arguments = K2JVMCompilerArguments().apply {

53

destination = "build/classes"

54

// Other configuration...

55

}

56

57

// Compile with incremental support

58

val exitCode = compiler.exec(messageCollector, Services.EMPTY, arguments)

59

60

// Access tracking information

61

val lookupTracker = incrementalComponents.lookupTracker

62

val usedSymbols = lookupTracker.getUsedSymbols()

63

println("Used ${usedSymbols.size} symbols during compilation")

64

```

65

66

### LookupTracker

67

68

Tracks symbol lookups during compilation for dependency analysis and change impact assessment.

69

70

```kotlin { .api }

71

/**

72

* Tracks symbol lookups during compilation

73

* Essential for determining compilation dependencies and change impact

74

*/

75

interface LookupTracker {

76

/** Record a symbol lookup at specific location */

77

fun record(

78

filePath: String,

79

position: Int,

80

scopeFqName: String,

81

name: String

82

): Unit

83

84

/** Record lookup with additional context */

85

fun record(

86

filePath: String,

87

position: Int,

88

scopeFqName: String,

89

scopeKind: ScopeKind,

90

name: String

91

): Unit

92

93

/** Get all recorded lookups */

94

fun getUsedSymbols(): Set<LookupSymbol>

95

96

/** Get lookups for specific file */

97

fun getLookups(filePath: String): Collection<LookupSymbol>

98

99

/** Clear all recorded lookups */

100

fun clear(): Unit

101

102

/** Check if lookup tracking is enabled */

103

val requiresPosition: Boolean

104

}

105

106

/**

107

* Represents a symbol lookup for incremental compilation

108

*/

109

data class LookupSymbol(

110

/** Fully qualified name of the scope */

111

val scope: String,

112

113

/** Name of the looked up symbol */

114

val name: String,

115

116

/** Kind of scope (package, class, etc.) */

117

val scopeKind: ScopeKind

118

)

119

120

/**

121

* Types of scopes for symbol lookups

122

*/

123

enum class ScopeKind {

124

PACKAGE, CLASSIFIER, OBJECT

125

}

126

```

127

128

**LookupTracker Examples:**

129

130

```kotlin

131

// Custom lookup tracker implementation

132

class DetailedLookupTracker : LookupTracker {

133

private val lookups = mutableMapOf<String, MutableSet<LookupSymbol>>()

134

135

override fun record(

136

filePath: String,

137

position: Int,

138

scopeFqName: String,

139

name: String

140

) {

141

val symbol = LookupSymbol(scopeFqName, name, ScopeKind.CLASSIFIER)

142

lookups.getOrPut(filePath) { mutableSetOf() }.add(symbol)

143

144

// Log for debugging

145

println("Lookup: $filePath:$position -> $scopeFqName.$name")

146

}

147

148

override fun record(

149

filePath: String,

150

position: Int,

151

scopeFqName: String,

152

scopeKind: ScopeKind,

153

name: String

154

) {

155

val symbol = LookupSymbol(scopeFqName, name, scopeKind)

156

lookups.getOrPut(filePath) { mutableSetOf() }.add(symbol)

157

}

158

159

override fun getUsedSymbols(): Set<LookupSymbol> {

160

return lookups.values.flatten().toSet()

161

}

162

163

override fun getLookups(filePath: String): Collection<LookupSymbol> {

164

return lookups[filePath] ?: emptySet()

165

}

166

167

override fun clear() {

168

lookups.clear()

169

}

170

171

override val requiresPosition: Boolean = true

172

173

// Additional functionality

174

fun getDependentFiles(changedSymbol: LookupSymbol): Set<String> {

175

return lookups.filterValues { symbols ->

176

changedSymbol in symbols

177

}.keys

178

}

179

}

180

```

181

182

### ExpectActualTracker

183

184

Tracks expect/actual declarations in multiplatform projects for incremental compilation.

185

186

```kotlin { .api }

187

/**

188

* Tracks expect/actual declarations in multiplatform projects

189

* Ensures proper incremental compilation across platforms

190

*/

191

interface ExpectActualTracker {

192

/** Report expect declaration */

193

fun reportExpectDeclaration(

194

filePath: String,

195

fqName: String,

196

position: Int

197

): Unit

198

199

/** Report actual declaration */

200

fun reportActualDeclaration(

201

filePath: String,

202

fqName: String,

203

position: Int

204

): Unit

205

206

/** Get all expect declarations */

207

fun getExpectDeclarations(): Collection<ExpectActualDeclaration>

208

209

/** Get all actual declarations */

210

fun getActualDeclarations(): Collection<ExpectActualDeclaration>

211

212

/** Find actual declarations for expect */

213

fun findActuals(expectFqName: String): Collection<ExpectActualDeclaration>

214

215

/** Find expect declaration for actual */

216

fun findExpect(actualFqName: String): ExpectActualDeclaration?

217

}

218

219

/**

220

* Represents an expect or actual declaration

221

*/

222

data class ExpectActualDeclaration(

223

val filePath: String,

224

val fqName: String,

225

val position: Int,

226

val isExpect: Boolean

227

)

228

```

229

230

### InlineConstTracker

231

232

Tracks usage of inline constants for proper incremental compilation when constants change.

233

234

```kotlin { .api }

235

/**

236

* Tracks usage of inline constants

237

* Critical for incremental compilation when constant values change

238

*/

239

interface InlineConstTracker {

240

/** Report usage of inline constant */

241

fun report(

242

filePath: String,

243

position: Int,

244

owner: String,

245

name: String,

246

constType: ConstType

247

): Unit

248

249

/** Get all tracked inline constant usages */

250

fun getUsedInlineConsts(): Collection<InlineConstUsage>

251

252

/** Get inline constant usages for specific file */

253

fun getUsages(filePath: String): Collection<InlineConstUsage>

254

255

/** Check if constant change affects file */

256

fun isAffectedBy(filePath: String, changedConst: InlineConstUsage): Boolean

257

}

258

259

/**

260

* Represents usage of an inline constant

261

*/

262

data class InlineConstUsage(

263

val filePath: String,

264

val position: Int,

265

val owner: String,

266

val name: String,

267

val constType: ConstType

268

)

269

270

/**

271

* Types of inline constants

272

*/

273

enum class ConstType {

274

PROPERTY, ENUM_ENTRY, COMPANION_OBJECT_PROPERTY

275

}

276

```

277

278

### EnumWhenTracker

279

280

Tracks enum when expressions for incremental compilation when enum entries are added or removed.

281

282

```kotlin { .api }

283

/**

284

* Tracks enum when expressions

285

* Ensures recompilation when enum entries are added/removed

286

*/

287

interface EnumWhenTracker {

288

/** Report enum when expression */

289

fun report(

290

filePath: String,

291

position: Int,

292

enumClassFqName: String,

293

whenExpression: WhenExpressionInfo

294

): Unit

295

296

/** Get all tracked when expressions */

297

fun getWhenExpressions(): Collection<EnumWhenUsage>

298

299

/** Check if enum change affects when expressions */

300

fun isAffectedByEnumChange(

301

enumFqName: String,

302

addedEntries: Set<String>,

303

removedEntries: Set<String>

304

): Collection<EnumWhenUsage>

305

}

306

307

/**

308

* Information about when expression on enum

309

*/

310

data class WhenExpressionInfo(

311

val isExhaustive: Boolean,

312

val matchedEntries: Set<String>

313

)

314

315

/**

316

* Usage of enum in when expression

317

*/

318

data class EnumWhenUsage(

319

val filePath: String,

320

val position: Int,

321

val enumClassFqName: String,

322

val whenInfo: WhenExpressionInfo

323

)

324

```

325

326

### ImportTracker

327

328

Tracks import statements and their usage for optimizing incremental compilation.

329

330

```kotlin { .api }

331

/**

332

* Tracks import statements and their usage

333

* Helps optimize incremental compilation by tracking import dependencies

334

*/

335

interface ImportTracker {

336

/** Report import statement */

337

fun report(filePath: String, importedFqName: String): Unit

338

339

/** Report star import */

340

fun reportStarImport(filePath: String, packageFqName: String): Unit

341

342

/** Get all imports for file */

343

fun getImports(filePath: String): Collection<ImportInfo>

344

345

/** Get files that import from package */

346

fun getFilesImportingFrom(packageFqName: String): Collection<String>

347

348

/** Check if symbol change affects imports */

349

fun isAffectedBySymbolChange(symbolFqName: String): Collection<String>

350

}

351

352

/**

353

* Information about an import

354

*/

355

data class ImportInfo(

356

val importedFqName: String,

357

val isStarImport: Boolean

358

)

359

```

360

361

### Classpath Change Detection

362

363

Advanced classpath analysis for incremental compilation optimization.

364

365

```kotlin { .api }

366

/**

367

* Analyzes classpath changes for incremental compilation

368

*/

369

interface ClasspathChangesComputer {

370

/** Compute changes between classpaths */

371

fun compute(

372

previousClasspath: List<File>,

373

currentClasspath: List<File>

374

): ClasspathChanges

375

376

/** Create snapshot of current classpath */

377

fun createSnapshot(classpath: List<File>): ClasspathSnapshot

378

379

/** Compare snapshots for changes */

380

fun compareSnapshots(

381

previous: ClasspathSnapshot,

382

current: ClasspathSnapshot

383

): ClasspathChanges

384

}

385

386

/**

387

* Represents changes in classpath between compilations

388

*/

389

data class ClasspathChanges(

390

/** Files added to classpath */

391

val added: Set<File>,

392

393

/** Files removed from classpath */

394

val removed: Set<File>,

395

396

/** Files modified in classpath */

397

val modified: Set<File>,

398

399

/** Unchanged files */

400

val unchanged: Set<File>

401

) {

402

/** Check if any changes occurred */

403

val hasChanges: Boolean get() = added.isNotEmpty() || removed.isNotEmpty() || modified.isNotEmpty()

404

405

/** Get all changed files */

406

val changedFiles: Set<File> get() = added + removed + modified

407

}

408

409

/**

410

* Snapshot of classpath state

411

*/

412

interface ClasspathSnapshot {

413

/** Classpath entries in this snapshot */

414

val entries: List<ClasspathEntrySnapshot>

415

416

/** Timestamp when snapshot was created */

417

val timestamp: Long

418

419

/** Hash of the complete classpath */

420

val hash: String

421

}

422

423

/**

424

* Snapshot of individual classpath entry

425

*/

426

interface ClasspathEntrySnapshot {

427

/** File path */

428

val file: File

429

430

/** Content hash */

431

val hash: String

432

433

/** Last modified timestamp */

434

val lastModified: Long

435

436

/** File size */

437

val size: Long

438

439

/** ABI hash for incremental compilation */

440

val abiHash: String?

441

}

442

```

443

444

**Advanced Incremental Compilation Example:**

445

446

```kotlin

447

// Complete incremental compilation setup

448

class IncrementalCompilationManager {

449

private val lookupTracker = DetailedLookupTracker()

450

private val classpathComputer = ClasspathChangesComputer.create()

451

private var previousSnapshot: ClasspathSnapshot? = null

452

453

fun compile(

454

sources: List<File>,

455

classpath: List<File>,

456

outputDir: File

457

): CompilationResult {

458

459

// Check classpath changes

460

val currentSnapshot = classpathComputer.createSnapshot(classpath)

461

val classpathChanges = previousSnapshot?.let {

462

classpathComputer.compareSnapshots(it, currentSnapshot)

463

}

464

465

// Determine which sources need recompilation

466

val sourcesToCompile = if (classpathChanges?.hasChanges == true) {

467

// Significant classpath changes - recompile all

468

sources

469

} else {

470

// Check individual source changes

471

determineChangedSources(sources)

472

}

473

474

// Setup incremental compilation components

475

val incrementalComponents = IncrementalCompilationComponents.create().apply {

476

// Use our custom lookup tracker

477

(this as MutableIncrementalCompilationComponents).lookupTracker = this@IncrementalCompilationManager.lookupTracker

478

}

479

480

val configuration = CompilerConfiguration().apply {

481

put(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS, incrementalComponents)

482

put(JVMConfigurationKeys.OUTPUT_DIRECTORY, outputDir)

483

}

484

485

// Perform compilation

486

val compiler = K2JVMCompiler()

487

val arguments = K2JVMCompilerArguments().apply {

488

destination = outputDir.absolutePath

489

classpath = classpath.joinToString(File.pathSeparator) { it.absolutePath }

490

freeArgs = sourcesToCompile.map { it.absolutePath }

491

}

492

493

val messageCollector = PrintingMessageCollector(System.err, MessageRenderer.PLAIN, false)

494

val exitCode = compiler.exec(messageCollector, Services.EMPTY, arguments)

495

496

// Update snapshot for next compilation

497

previousSnapshot = currentSnapshot

498

499

return CompilationResult(

500

exitCode = exitCode,

501

compiledFiles = sourcesToCompile.size,

502

incrementalInfo = IncrementalInfo(

503

classpathChanges = classpathChanges,

504

recompiledSources = sourcesToCompile,

505

symbolLookups = lookupTracker.getUsedSymbols()

506

)

507

)

508

}

509

510

private fun determineChangedSources(sources: List<File>): List<File> {

511

// Implementation would check source file modifications

512

// and use lookup tracker to determine dependent files

513

return sources.filter { it.lastModified() > getLastCompilationTime() }

514

}

515

516

fun getImpactAnalysis(changedSymbol: String): Set<String> {

517

return lookupTracker.getDependentFiles(

518

LookupSymbol(changedSymbol, "", ScopeKind.CLASSIFIER)

519

)

520

}

521

}

522

523

// Result with incremental compilation information

524

data class IncrementalInfo(

525

val classpathChanges: ClasspathChanges?,

526

val recompiledSources: List<File>,

527

val symbolLookups: Set<LookupSymbol>

528

)

529

```

530

531

## Performance Optimization

532

533

```kotlin

534

// Incremental compilation configuration

535

data class IncrementalCompilationConfiguration(

536

/** Enable lookup tracking */

537

val enableLookupTracking: Boolean = true,

538

539

/** Enable expect/actual tracking */

540

val enableExpectActualTracking: Boolean = true,

541

542

/** Enable inline constant tracking */

543

val enableInlineConstTracking: Boolean = true,

544

545

/** Enable enum when tracking */

546

val enableEnumWhenTracking: Boolean = true,

547

548

/** Enable import tracking */

549

val enableImportTracking: Boolean = true,

550

551

/** Maximum cache size for tracking data */

552

val maxCacheSize: Int = 10000,

553

554

/** Whether to persist tracking data between sessions */

555

val persistTrackingData: Boolean = true,

556

557

/** Directory for storing incremental data */

558

val incrementalDataDir: File? = null

559

)

560

```