0
# Message Collection and Diagnostics
1
2
Comprehensive diagnostic collection system for compilation errors, warnings, and informational messages with customizable output formatting. The message collection system provides structured reporting of compilation diagnostics with precise source location information.
3
4
## Capabilities
5
6
### MessageCollector Interface
7
8
Core interface for collecting compilation diagnostics with severity levels and source location information.
9
10
```kotlin { .api }
11
/**
12
* Core interface for collecting compilation diagnostic messages
13
* Implementations handle display, storage, or processing of compiler messages
14
*/
15
interface MessageCollector {
16
/** Report a diagnostic message with severity and optional location */
17
fun report(
18
severity: CompilerMessageSeverity,
19
message: String,
20
location: CompilerMessageSourceLocation? = null
21
): Unit
22
23
/** Check if any error messages have been reported */
24
fun hasErrors(): Boolean
25
26
/** Clear all collected messages */
27
fun clear(): Unit
28
}
29
```
30
31
**Usage Examples:**
32
33
```kotlin
34
// Custom message collector implementation
35
class CustomMessageCollector : MessageCollector {
36
private val messages = mutableListOf<CompilerMessage>()
37
private var hasErrorsFlag = false
38
39
override fun report(
40
severity: CompilerMessageSeverity,
41
message: String,
42
location: CompilerMessageSourceLocation?
43
) {
44
messages.add(CompilerMessage(severity, message, location))
45
if (severity == CompilerMessageSeverity.ERROR) {
46
hasErrorsFlag = true
47
}
48
49
// Custom handling
50
when (severity) {
51
CompilerMessageSeverity.ERROR -> logger.error(message)
52
CompilerMessageSeverity.WARNING -> logger.warn(message)
53
else -> logger.info(message)
54
}
55
}
56
57
override fun hasErrors(): Boolean = hasErrorsFlag
58
override fun clear() {
59
messages.clear()
60
hasErrorsFlag = false
61
}
62
}
63
64
// Using with compiler
65
val messageCollector = CustomMessageCollector()
66
val compiler = K2JVMCompiler()
67
val exitCode = compiler.exec(messageCollector, Services.EMPTY, arguments)
68
69
if (messageCollector.hasErrors()) {
70
println("Compilation failed with errors")
71
}
72
```
73
74
### CompilerMessageSeverity
75
76
Enumeration of message severity levels for categorizing diagnostic messages.
77
78
```kotlin { .api }
79
/**
80
* Message severity levels for compilation diagnostics
81
* Ordered from most severe (ERROR) to least severe (OUTPUT)
82
*/
83
enum class CompilerMessageSeverity {
84
/** Fatal compilation error - prevents successful compilation */
85
ERROR,
86
87
/** Strong warning - significant issue but compilation can continue */
88
STRONG_WARNING,
89
90
/** Standard warning - potential issue worth noting */
91
WARNING,
92
93
/** Informational message */
94
INFO,
95
96
/** Verbose logging information */
97
LOGGING,
98
99
/** Compiler output information */
100
OUTPUT;
101
102
companion object {
103
/** Verbose logging level for detailed output */
104
val VERBOSE: CompilerMessageSeverity = LOGGING
105
}
106
}
107
```
108
109
### CompilerMessageSourceLocation
110
111
Source location information for precise error reporting and IDE integration.
112
113
```kotlin { .api }
114
/**
115
* Source location information for diagnostic messages
116
* Provides precise file, line, and column information
117
*/
118
data class CompilerMessageSourceLocation(
119
/** File path where the diagnostic occurred */
120
val path: String,
121
122
/** Line number (1-based) */
123
val line: Int,
124
125
/** Column number (1-based) */
126
val column: Int,
127
128
/** Source line content for context (optional) */
129
val lineContent: String? = null
130
) {
131
/** Create location with line content for better error reporting */
132
constructor(
133
path: String,
134
line: Int,
135
column: Int,
136
lineContent: String
137
) : this(path, line, column, lineContent)
138
139
override fun toString(): String = "$path:$line:$column"
140
}
141
```
142
143
### Built-in Message Collectors
144
145
Pre-built message collector implementations for common use cases.
146
147
```kotlin { .api }
148
/**
149
* Message collector that prints messages to a PrintStream
150
* Supports different output formats and verbosity levels
151
*/
152
class PrintingMessageCollector(
153
/** Stream to write messages to */
154
val stream: PrintStream,
155
156
/** Message renderer for formatting output */
157
val messageRenderer: MessageRenderer,
158
159
/** Whether to print verbose messages */
160
val verbose: Boolean
161
) : MessageCollector {
162
163
override fun report(
164
severity: CompilerMessageSeverity,
165
message: String,
166
location: CompilerMessageSourceLocation?
167
): Unit
168
169
override fun hasErrors(): Boolean
170
override fun clear(): Unit
171
}
172
173
/**
174
* Message collector that groups messages by severity
175
* Useful for batch processing of diagnostics
176
*/
177
class GroupingMessageCollector(
178
/** Delegate message collector */
179
private val delegate: MessageCollector,
180
181
/** Treat warnings as errors */
182
private val treatWarningsAsErrors: Boolean,
183
184
/** Report all warnings */
185
private val reportAllWarnings: Boolean
186
) : MessageCollector {
187
188
/** Get all messages grouped by severity */
189
fun getGroupedMessages(): Map<CompilerMessageSeverity, List<String>>
190
191
override fun report(
192
severity: CompilerMessageSeverity,
193
message: String,
194
location: CompilerMessageSourceLocation?
195
): Unit
196
197
override fun hasErrors(): Boolean
198
override fun clear(): Unit
199
}
200
201
/**
202
* Message collector that filters messages based on severity
203
* Useful for controlling output verbosity
204
*/
205
class FilteringMessageCollector(
206
/** Delegate message collector */
207
private val delegate: MessageCollector,
208
209
/** Minimum severity to report */
210
private val minSeverity: CompilerMessageSeverity
211
) : MessageCollector {
212
213
override fun report(
214
severity: CompilerMessageSeverity,
215
message: String,
216
location: CompilerMessageSourceLocation?
217
): Unit
218
219
override fun hasErrors(): Boolean
220
override fun clear(): Unit
221
}
222
```
223
224
### Message Rendering
225
226
Different output formats for diagnostic messages.
227
228
```kotlin { .api }
229
/**
230
* Message rendering formats for different output contexts
231
*/
232
enum class MessageRenderer {
233
/** Plain text format suitable for console output */
234
PLAIN,
235
236
/** Plain text with full file paths */
237
PLAIN_FULL_PATHS,
238
239
/** XML format suitable for IDE integration */
240
XML,
241
242
/** JSON format for structured processing */
243
JSON;
244
245
/** Render a diagnostic message with the specified format */
246
fun render(
247
severity: CompilerMessageSeverity,
248
message: String,
249
location: CompilerMessageSourceLocation?
250
): String
251
}
252
```
253
254
**Advanced Usage Examples:**
255
256
```kotlin
257
// Hierarchical message collection with filtering
258
val baseCollector = PrintingMessageCollector(
259
System.err,
260
MessageRenderer.PLAIN_FULL_PATHS,
261
verbose = false
262
)
263
264
val groupingCollector = GroupingMessageCollector(
265
baseCollector,
266
treatWarningsAsErrors = false,
267
reportAllWarnings = true
268
)
269
270
val filteringCollector = FilteringMessageCollector(
271
groupingCollector,
272
minSeverity = CompilerMessageSeverity.WARNING
273
)
274
275
// Use with compilation
276
val compiler = K2JVMCompiler()
277
val exitCode = compiler.exec(filteringCollector, Services.EMPTY, arguments)
278
279
// Analyze results
280
val groupedMessages = groupingCollector.getGroupedMessages()
281
val errors = groupedMessages[CompilerMessageSeverity.ERROR] ?: emptyList()
282
val warnings = groupedMessages[CompilerMessageSeverity.WARNING] ?: emptyList()
283
284
println("Compilation completed with ${errors.size} errors, ${warnings.size} warnings")
285
286
// XML output for IDE integration
287
val xmlCollector = PrintingMessageCollector(
288
System.out,
289
MessageRenderer.XML,
290
verbose = true
291
)
292
293
// JSON output for tooling
294
val jsonCollector = PrintingMessageCollector(
295
FileOutputStream("compilation-results.json"),
296
MessageRenderer.JSON,
297
verbose = true
298
)
299
```
300
301
### Message Utilities
302
303
Utility functions for working with compiler messages.
304
305
```kotlin { .api }
306
/**
307
* Utilities for message processing and formatting
308
*/
309
object MessageUtil {
310
/** Format a location for display */
311
fun formatLocation(location: CompilerMessageSourceLocation): String
312
313
/** Extract file path from location */
314
fun getPath(location: CompilerMessageSourceLocation): String
315
316
/** Create location from PSI element */
317
fun psiElementToMessageLocation(element: PsiElement): CompilerMessageSourceLocation?
318
319
/** Render exception as compiler message */
320
fun renderException(exception: Throwable): String
321
}
322
323
/**
324
* Output message utilities for structured output
325
*/
326
object OutputMessageUtil {
327
/** Format output message for display */
328
fun formatOutputMessage(message: String): String
329
330
/** Format compilation statistics */
331
fun formatCompilationStats(
332
duration: Long,
333
filesCompiled: Int,
334
errorsCount: Int,
335
warningsCount: Int
336
): String
337
}
338
```
339
340
## Integration Examples
341
342
```kotlin
343
// Complete message collection setup for build tools
344
class BuildToolMessageCollector(
345
private val buildLogger: Logger,
346
private val failOnWarnings: Boolean = false
347
) : MessageCollector {
348
349
private var errorCount = 0
350
private var warningCount = 0
351
352
override fun report(
353
severity: CompilerMessageSeverity,
354
message: String,
355
location: CompilerMessageSourceLocation?
356
) {
357
val locationStr = location?.let { " at $it" } ?: ""
358
val fullMessage = "$message$locationStr"
359
360
when (severity) {
361
CompilerMessageSeverity.ERROR -> {
362
errorCount++
363
buildLogger.error(fullMessage)
364
}
365
CompilerMessageSeverity.STRONG_WARNING,
366
CompilerMessageSeverity.WARNING -> {
367
warningCount++
368
if (failOnWarnings) {
369
buildLogger.error("Warning treated as error: $fullMessage")
370
errorCount++
371
} else {
372
buildLogger.warn(fullMessage)
373
}
374
}
375
CompilerMessageSeverity.INFO -> buildLogger.info(fullMessage)
376
CompilerMessageSeverity.LOGGING,
377
CompilerMessageSeverity.OUTPUT -> buildLogger.debug(fullMessage)
378
}
379
}
380
381
override fun hasErrors(): Boolean = errorCount > 0
382
383
fun getErrorCount(): Int = errorCount
384
fun getWarningCount(): Int = warningCount
385
386
override fun clear() {
387
errorCount = 0
388
warningCount = 0
389
}
390
}
391
392
// IDE integration with source navigation
393
class IDEMessageCollector(
394
private val project: Project,
395
private val problemsHolder: ProblemsHolder
396
) : MessageCollector {
397
398
override fun report(
399
severity: CompilerMessageSeverity,
400
message: String,
401
location: CompilerMessageSourceLocation?
402
) {
403
location?.let { loc ->
404
val virtualFile = VirtualFileManager.getInstance()
405
.findFileByUrl("file://${loc.path}")
406
407
if (virtualFile != null) {
408
val psiFile = PsiManager.getInstance(project).findFile(virtualFile)
409
psiFile?.let { file ->
410
val element = file.findElementAt(loc.line, loc.column)
411
element?.let {
412
when (severity) {
413
CompilerMessageSeverity.ERROR ->
414
problemsHolder.registerProblem(it, message, ProblemHighlightType.ERROR)
415
CompilerMessageSeverity.WARNING,
416
CompilerMessageSeverity.STRONG_WARNING ->
417
problemsHolder.registerProblem(it, message, ProblemHighlightType.WARNING)
418
else -> Unit
419
}
420
}
421
}
422
}
423
}
424
}
425
426
override fun hasErrors(): Boolean = problemsHolder.hasErrors()
427
override fun clear(): Unit = problemsHolder.clear()
428
}
429
```