or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdenvironment.mdindex.mdjs-wasm-compilation.mdjvm-compilation.mdmessage-handling.mdplugin-development.md

message-handling.mddocs/

0

# Message Handling and Diagnostics

1

2

Comprehensive diagnostic and message reporting system providing multiple output formats, severity levels, and source location tracking. The message handling system supports integration with IDEs, build tools, and command-line interfaces through customizable renderers and collectors.

3

4

## Capabilities

5

6

### MessageCollector

7

8

Core interface for collecting compilation messages and diagnostics with severity-based filtering.

9

10

```kotlin { .api }

11

/**

12

* Interface for collecting compilation messages and diagnostics

13

* Provides extensible message handling with severity levels

14

*/

15

interface MessageCollector {

16

/**

17

* Report a compilation message

18

*

19

* @param severity Message severity level

20

* @param message Message text content

21

* @param location Optional source location information

22

*/

23

fun report(

24

severity: CompilerMessageSeverity,

25

message: String,

26

location: CompilerMessageSourceLocation? = null

27

)

28

29

/**

30

* Check if message collector has reported errors

31

*

32

* @return true if any error messages have been reported

33

*/

34

fun hasErrors(): Boolean

35

36

/**

37

* Clear all collected messages

38

* Resets error state and clears message history

39

*/

40

fun clear()

41

42

companion object {

43

/** No-op message collector that discards all messages */

44

val NONE: MessageCollector

45

}

46

}

47

```

48

49

### Message Severity Levels

50

51

Hierarchical severity levels for categorizing compilation messages.

52

53

```kotlin { .api }

54

/**

55

* Compilation message severity levels

56

* Hierarchical system from logging to errors

57

*/

58

enum class CompilerMessageSeverity(val presentableName: String) {

59

/** Detailed logging information */

60

LOGGING("logging"),

61

62

/** General information messages */

63

INFO("info"),

64

65

/** General warnings */

66

WARNING("warning"),

67

68

/** Important warnings that should not be ignored */

69

STRONG_WARNING("strong warning"),

70

71

/** Compilation errors */

72

ERROR("error"),

73

74

/** Fatal compiler errors */

75

EXCEPTION("exception");

76

77

companion object {

78

/** Verbose output including all severity levels */

79

val VERBOSE: Set<CompilerMessageSeverity>

80

81

/**

82

* Check if severity level is error or higher

83

*

84

* @param severity Severity to check

85

* @return true if error level or higher

86

*/

87

fun isError(severity: CompilerMessageSeverity): Boolean

88

89

/**

90

* Check if severity level is warning or higher

91

*

92

* @param severity Severity to check

93

* @return true if warning level or higher

94

*/

95

fun isWarning(severity: CompilerMessageSeverity): Boolean

96

}

97

}

98

```

99

100

### Source Location Information

101

102

Source file location information for precise error reporting.

103

104

```kotlin { .api }

105

/**

106

* Source location information for diagnostic messages

107

* Provides file path and position information

108

*/

109

interface CompilerMessageSourceLocation {

110

/** Source file path */

111

val path: String

112

113

/** Line number (1-based) */

114

val line: Int

115

116

/** Column number (1-based) */

117

val column: Int

118

119

/** Line content for context */

120

val lineContent: String?

121

122

companion object {

123

/**

124

* Create source location

125

*

126

* @param path File path

127

* @param line Line number (1-based)

128

* @param column Column number (1-based)

129

* @param lineContent Optional line content

130

* @return Source location instance

131

*/

132

fun create(

133

path: String,

134

line: Int,

135

column: Int,

136

lineContent: String?

137

): CompilerMessageSourceLocation

138

}

139

}

140

```

141

142

### Message Renderers

143

144

Pluggable message rendering system for different output formats and tools.

145

146

```kotlin { .api }

147

/**

148

* Interface for rendering diagnostic messages

149

* Supports different output formats for various tools

150

*/

151

interface MessageRenderer {

152

/**

153

* Render diagnostic message to string

154

*

155

* @param severity Message severity level

156

* @param message Message content

157

* @param location Source location information

158

* @return Formatted message string

159

*/

160

fun render(

161

severity: CompilerMessageSeverity,

162

message: String,

163

location: CompilerMessageSourceLocation?

164

): String

165

166

/**

167

* Get path representation

168

* Controls how file paths are displayed

169

*

170

* @param location Source location

171

* @return Formatted path string

172

*/

173

fun getPath(location: CompilerMessageSourceLocation): String

174

175

companion object {

176

/** Plain text renderer with full file paths */

177

val PLAIN_FULL_PATHS: MessageRenderer

178

179

/** Plain text renderer with relative file paths */

180

val PLAIN_RELATIVE_PATHS: MessageRenderer

181

182

/** Plain text renderer without file paths */

183

val PLAIN_WITHOUT_PATHS: MessageRenderer

184

}

185

}

186

```

187

188

### Specialized Message Renderers

189

190

Pre-built renderers for common IDE and build tool integration.

191

192

```kotlin { .api }

193

/**

194

* Plain text message renderer

195

* Standard text output for command-line tools

196

*/

197

class PlainTextMessageRenderer(

198

private val withPaths: Boolean = true

199

) : MessageRenderer {

200

override fun render(

201

severity: CompilerMessageSeverity,

202

message: String,

203

location: CompilerMessageSourceLocation?

204

): String

205

}

206

207

/**

208

* Xcode-compatible message renderer

209

* Formats messages for Xcode IDE integration

210

*/

211

class XcodeStyleMessageRenderer : MessageRenderer {

212

override fun render(

213

severity: CompilerMessageSeverity,

214

message: String,

215

location: CompilerMessageSourceLocation?

216

): String

217

}

218

219

/**

220

* Gradle-compatible message renderer

221

* Formats messages for Gradle build tool integration

222

*/

223

class GradleStyleMessageRenderer : MessageRenderer {

224

override fun render(

225

severity: CompilerMessageSeverity,

226

message: String,

227

location: CompilerMessageSourceLocation?

228

): String

229

}

230

```

231

232

### Printing Message Collector

233

234

Concrete message collector that prints messages to output streams.

235

236

```kotlin { .api }

237

/**

238

* Message collector that prints to output streams

239

* Supports custom renderers and severity filtering

240

*/

241

class PrintingMessageCollector(

242

private val stream: PrintStream,

243

private val messageRenderer: MessageRenderer,

244

private val verbose: Boolean

245

) : MessageCollector {

246

247

/**

248

* Create printing message collector

249

*

250

* @param stream Output stream for messages

251

* @param messageRenderer Message rendering strategy

252

* @param verbose Enable verbose output (all severity levels)

253

*/

254

constructor(

255

stream: PrintStream,

256

messageRenderer: MessageRenderer,

257

verbose: Boolean

258

)

259

260

override fun report(

261

severity: CompilerMessageSeverity,

262

message: String,

263

location: CompilerMessageSourceLocation?

264

) {

265

if (verbose || severity != CompilerMessageSeverity.LOGGING) {

266

val renderedMessage = messageRenderer.render(severity, message, location)

267

stream.println(renderedMessage)

268

}

269

}

270

271

override fun hasErrors(): Boolean

272

override fun clear()

273

}

274

```

275

276

### Grouping Message Collector

277

278

Message collector that groups related messages together.

279

280

```kotlin { .api }

281

/**

282

* Message collector that groups related messages

283

* Useful for organizing diagnostic output by file or module

284

*/

285

class GroupingMessageCollector(

286

private val delegate: MessageCollector

287

) : MessageCollector {

288

289

/**

290

* Start new message group

291

*

292

* @param groupName Name for the message group

293

*/

294

fun startGroup(groupName: String)

295

296

/**

297

* End current message group

298

*/

299

fun endGroup()

300

301

override fun report(

302

severity: CompilerMessageSeverity,

303

message: String,

304

location: CompilerMessageSourceLocation?

305

)

306

307

override fun hasErrors(): Boolean

308

override fun clear()

309

}

310

```

311

312

### Analysis and Diagnostic Reporting

313

314

Advanced diagnostic reporting with analysis integration.

315

316

```kotlin { .api }

317

/**

318

* Analyzer with integrated compiler reporting

319

* Combines frontend analysis with diagnostic collection

320

*/

321

class AnalyzerWithCompilerReport(

322

private val messageCollector: MessageCollector,

323

private val languageVersionSettings: LanguageVersionSettings

324

) {

325

/**

326

* Check for compilation errors

327

*

328

* @return true if compilation should stop due to errors

329

*/

330

fun hasErrors(): Boolean

331

332

/**

333

* Report analysis result

334

*

335

* @param result Analysis result to report

336

* @param files Source files analyzed

337

*/

338

fun reportAnalysisResult(

339

result: AnalysisResult,

340

files: Collection<KtFile>

341

)

342

343

/**

344

* Render diagnostic with context

345

*

346

* @param diagnostic Diagnostic to render

347

* @return Formatted diagnostic message

348

*/

349

fun renderDiagnostic(diagnostic: Diagnostic): String

350

}

351

352

/**

353

* Default diagnostic reporter implementation

354

* Standard diagnostic message formatting and reporting

355

*/

356

class DefaultDiagnosticReporter(

357

private val messageCollector: MessageCollector

358

) : DiagnosticReporter {

359

360

override fun report(

361

diagnostic: Diagnostic,

362

bindingContext: BindingContext

363

) {

364

val severity = diagnostic.severity.toCompilerMessageSeverity()

365

val message = renderDiagnosticMessage(diagnostic)

366

val location = diagnostic.psiElement?.let {

367

getLocationFromPsiElement(it)

368

}

369

370

messageCollector.report(severity, message, location)

371

}

372

}

373

```

374

375

### Diagnostic Message Reporter

376

377

High-level diagnostic message reporting with rich formatting.

378

379

```kotlin { .api }

380

/**

381

* Rich diagnostic message reporter

382

* Provides detailed diagnostic information with context

383

*/

384

class DiagnosticMessageReporter(

385

private val messageCollector: MessageCollector,

386

private val messageRenderer: MessageRenderer = MessageRenderer.PLAIN_FULL_PATHS

387

) {

388

/**

389

* Report diagnostic with full context

390

*

391

* @param diagnostic Diagnostic information

392

* @param file Source file context

393

* @param context Binding context for resolution

394

*/

395

fun reportDiagnostic(

396

diagnostic: Diagnostic,

397

file: KtFile,

398

context: BindingContext

399

)

400

401

/**

402

* Report multiple diagnostics from analysis

403

*

404

* @param diagnostics Collection of diagnostics

405

* @param context Binding context

406

*/

407

fun reportDiagnostics(

408

diagnostics: Collection<Diagnostic>,

409

context: BindingContext

410

)

411

412

/**

413

* Report exception as diagnostic

414

*

415

* @param exception Exception to report

416

* @param location Optional source location

417

*/

418

fun reportException(

419

exception: Throwable,

420

location: CompilerMessageSourceLocation? = null

421

)

422

}

423

```

424

425

## Usage Examples

426

427

### Basic Message Collection

428

429

```kotlin

430

import org.jetbrains.kotlin.cli.common.messages.*

431

import java.io.PrintStream

432

433

// Create message collector with plain text renderer

434

val messageCollector = PrintingMessageCollector(

435

stream = System.err,

436

messageRenderer = MessageRenderer.PLAIN_FULL_PATHS,

437

verbose = true

438

)

439

440

// Report messages with different severity levels

441

messageCollector.report(

442

CompilerMessageSeverity.INFO,

443

"Starting compilation of module 'my-app'"

444

)

445

446

messageCollector.report(

447

CompilerMessageSeverity.WARNING,

448

"Unused import: kotlin.collections.List",

449

CompilerMessageSourceLocation.create(

450

path = "src/main/kotlin/Main.kt",

451

line = 3,

452

column = 1,

453

lineContent = "import kotlin.collections.List"

454

)

455

)

456

457

messageCollector.report(

458

CompilerMessageSeverity.ERROR,

459

"Unresolved reference: unknownFunction",

460

CompilerMessageSourceLocation.create(

461

path = "src/main/kotlin/Main.kt",

462

line = 10,

463

column = 5,

464

lineContent = " unknownFunction()"

465

)

466

)

467

468

// Check for errors

469

if (messageCollector.hasErrors()) {

470

println("Compilation failed due to errors")

471

}

472

```

473

474

### Custom Message Renderer

475

476

```kotlin

477

// Custom JSON message renderer

478

class JsonMessageRenderer : MessageRenderer {

479

override fun render(

480

severity: CompilerMessageSeverity,

481

message: String,

482

location: CompilerMessageSourceLocation?

483

): String {

484

val json = buildJsonObject {

485

put("severity", severity.presentableName)

486

put("message", message)

487

put("timestamp", System.currentTimeMillis())

488

489

location?.let { loc ->

490

putJsonObject("location") {

491

put("path", loc.path)

492

put("line", loc.line)

493

put("column", loc.column)

494

put("lineContent", loc.lineContent)

495

}

496

}

497

}

498

return json.toString()

499

}

500

501

override fun getPath(location: CompilerMessageSourceLocation): String {

502

return location.path

503

}

504

}

505

506

// Use custom renderer

507

val jsonCollector = PrintingMessageCollector(

508

stream = System.out,

509

messageRenderer = JsonMessageRenderer(),

510

verbose = false

511

)

512

```

513

514

### IDE Integration

515

516

```kotlin

517

// Xcode integration

518

val xcodeCollector = PrintingMessageCollector(

519

stream = System.err,

520

messageRenderer = XcodeStyleMessageRenderer(),

521

verbose = false

522

)

523

524

// Gradle integration

525

val gradleCollector = PrintingMessageCollector(

526

stream = System.err,

527

messageRenderer = GradleStyleMessageRenderer(),

528

verbose = true

529

)

530

531

// Configure in compiler configuration

532

val configuration = CompilerConfiguration().apply {

533

put(CommonConfigurationKeys.MESSAGE_COLLECTOR_KEY, gradleCollector)

534

}

535

```

536

537

### Grouped Message Collection

538

539

```kotlin

540

val baseCollector = PrintingMessageCollector(

541

System.err,

542

MessageRenderer.PLAIN_FULL_PATHS,

543

true

544

)

545

546

val groupingCollector = GroupingMessageCollector(baseCollector)

547

548

// Group messages by module

549

groupingCollector.startGroup("Module: core")

550

groupingCollector.report(

551

CompilerMessageSeverity.INFO,

552

"Compiling core module"

553

)

554

groupingCollector.report(

555

CompilerMessageSeverity.ERROR,

556

"Missing dependency in core module"

557

)

558

groupingCollector.endGroup()

559

560

groupingCollector.startGroup("Module: api")

561

groupingCollector.report(

562

CompilerMessageSeverity.INFO,

563

"Compiling api module"

564

)

565

groupingCollector.endGroup()

566

```

567

568

### Filtering Message Collector

569

570

```kotlin

571

// Custom filtering message collector

572

class FilteringMessageCollector(

573

private val delegate: MessageCollector,

574

private val minSeverity: CompilerMessageSeverity

575

) : MessageCollector {

576

577

override fun report(

578

severity: CompilerMessageSeverity,

579

message: String,

580

location: CompilerMessageSourceLocation?

581

) {

582

if (severity.ordinal >= minSeverity.ordinal) {

583

delegate.report(severity, message, location)

584

}

585

}

586

587

override fun hasErrors(): Boolean = delegate.hasErrors()

588

override fun clear() = delegate.clear()

589

}

590

591

// Only show warnings and errors

592

val filteringCollector = FilteringMessageCollector(

593

delegate = PrintingMessageCollector(

594

System.err,

595

MessageRenderer.PLAIN_FULL_PATHS,

596

true

597

),

598

minSeverity = CompilerMessageSeverity.WARNING

599

)

600

```

601

602

### Diagnostic Integration

603

604

```kotlin

605

import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport

606

import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl

607

608

// Create analyzer with reporting

609

val analyzerWithReport = AnalyzerWithCompilerReport(

610

messageCollector = messageCollector,

611

languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT

612

)

613

614

// Analyze and report

615

val analysisResult = analyzeFiles(sourceFiles, environment)

616

analyzerWithReport.reportAnalysisResult(analysisResult, sourceFiles)

617

618

if (analyzerWithReport.hasErrors()) {

619

return ExitCode.COMPILATION_ERROR

620

}

621

```

622

623

### Exception Reporting

624

625

```kotlin

626

// Enhanced message collector with exception handling

627

class ExceptionHandlingMessageCollector(

628

private val delegate: MessageCollector

629

) : MessageCollector by delegate {

630

631

fun reportException(

632

exception: Throwable,

633

context: String? = null,

634

location: CompilerMessageSourceLocation? = null

635

) {

636

val message = buildString {

637

context?.let { append("$it: ") }

638

append(exception.message ?: exception.javaClass.simpleName)

639

640

// Add stack trace for debugging

641

if (exception.stackTrace.isNotEmpty()) {

642

append("\n")

643

exception.stackTrace.take(5).forEach { frame ->

644

append(" at ${frame}\n")

645

}

646

}

647

}

648

649

delegate.report(

650

CompilerMessageSeverity.EXCEPTION,

651

message,

652

location

653

)

654

}

655

}

656

657

// Usage

658

val exceptionCollector = ExceptionHandlingMessageCollector(messageCollector)

659

660

try {

661

// Compilation code

662

} catch (e: Exception) {

663

exceptionCollector.reportException(

664

e,

665

"Compilation failed",

666

CompilerMessageSourceLocation.create("build.gradle.kts", 1, 1, null)

667

)

668

}

669

```

670

671

### Performance Monitoring Integration

672

673

```kotlin

674

// Message collector with performance monitoring

675

class PerformanceMonitoringCollector(

676

private val delegate: MessageCollector

677

) : MessageCollector by delegate {

678

679

private var messageCount = 0

680

private var errorCount = 0

681

private var warningCount = 0

682

private val startTime = System.currentTimeMillis()

683

684

override fun report(

685

severity: CompilerMessageSeverity,

686

message: String,

687

location: CompilerMessageSourceLocation?

688

) {

689

messageCount++

690

when (severity) {

691

CompilerMessageSeverity.ERROR,

692

CompilerMessageSeverity.EXCEPTION -> errorCount++

693

CompilerMessageSeverity.WARNING,

694

CompilerMessageSeverity.STRONG_WARNING -> warningCount++

695

else -> {}

696

}

697

698

delegate.report(severity, message, location)

699

}

700

701

fun printStatistics() {

702

val duration = System.currentTimeMillis() - startTime

703

delegate.report(

704

CompilerMessageSeverity.INFO,

705

"Compilation completed in ${duration}ms: " +

706

"$messageCount messages ($errorCount errors, $warningCount warnings)"

707

)

708

}

709

}

710

711

// Usage

712

val performanceCollector = PerformanceMonitoringCollector(baseCollector)

713

// ... perform compilation ...

714

performanceCollector.printStatistics()

715

```

716

717

### Multi-Output Message Collection

718

719

```kotlin

720

// Broadcast messages to multiple collectors

721

class BroadcastMessageCollector(

722

private val collectors: List<MessageCollector>

723

) : MessageCollector {

724

725

override fun report(

726

severity: CompilerMessageSeverity,

727

message: String,

728

location: CompilerMessageSourceLocation?

729

) {

730

collectors.forEach { collector ->

731

collector.report(severity, message, location)

732

}

733

}

734

735

override fun hasErrors(): Boolean {

736

return collectors.any { it.hasErrors() }

737

}

738

739

override fun clear() {

740

collectors.forEach { it.clear() }

741

}

742

}

743

744

// Send messages to both console and log file

745

val consoleCollector = PrintingMessageCollector(

746

System.err,

747

MessageRenderer.PLAIN_FULL_PATHS,

748

false

749

)

750

751

val fileCollector = PrintingMessageCollector(

752

PrintStream(File("compilation.log")),

753

JsonMessageRenderer(),

754

true

755

)

756

757

val broadcastCollector = BroadcastMessageCollector(

758

listOf(consoleCollector, fileCollector)

759

)

760

```

761

762

## Error Handling

763

764

```kotlin { .api }

765

class MessageCollectionException(message: String, cause: Throwable? = null) : Exception(message, cause)

766

767

class InvalidMessageRendererException(message: String) : MessageCollectionException(message)

768

769

class MessageRenderingException(message: String, cause: Throwable) : MessageCollectionException(message, cause)

770

```

771

772

Common message handling scenarios:

773

- **INVALID_SEVERITY_LEVEL**: Unknown or invalid severity level

774

- **RENDERING_ERROR**: Error during message formatting or rendering

775

- **OUTPUT_STREAM_ERROR**: Problems writing to output stream

776

- **SOURCE_LOCATION_ERROR**: Invalid or inaccessible source location information