CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-kotlin--kotlin-compiler

The Kotlin compiler infrastructure providing JVM, JavaScript, and metadata compilation capabilities

Pending
Overview
Eval results
Files

message-handling.mddocs/

Message Handling and Diagnostics

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.

Capabilities

MessageCollector

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

/**
 * Interface for collecting compilation messages and diagnostics
 * Provides extensible message handling with severity levels
 */
interface MessageCollector {
    /**
     * Report a compilation message
     * 
     * @param severity Message severity level
     * @param message Message text content
     * @param location Optional source location information
     */
    fun report(
        severity: CompilerMessageSeverity,
        message: String,
        location: CompilerMessageSourceLocation? = null
    )
    
    /**
     * Check if message collector has reported errors
     * 
     * @return true if any error messages have been reported
     */
    fun hasErrors(): Boolean
    
    /**
     * Clear all collected messages
     * Resets error state and clears message history
     */
    fun clear()
    
    companion object {
        /** No-op message collector that discards all messages */
        val NONE: MessageCollector
    }
}

Message Severity Levels

Hierarchical severity levels for categorizing compilation messages.

/**
 * Compilation message severity levels
 * Hierarchical system from logging to errors
 */
enum class CompilerMessageSeverity(val presentableName: String) {
    /** Detailed logging information */
    LOGGING("logging"),
    
    /** General information messages */
    INFO("info"),
    
    /** General warnings */
    WARNING("warning"),
    
    /** Important warnings that should not be ignored */
    STRONG_WARNING("strong warning"),
    
    /** Compilation errors */
    ERROR("error"),
    
    /** Fatal compiler errors */
    EXCEPTION("exception");
    
    companion object {
        /** Verbose output including all severity levels */
        val VERBOSE: Set<CompilerMessageSeverity>
        
        /**
         * Check if severity level is error or higher
         * 
         * @param severity Severity to check
         * @return true if error level or higher
         */
        fun isError(severity: CompilerMessageSeverity): Boolean
        
        /**
         * Check if severity level is warning or higher
         * 
         * @param severity Severity to check
         * @return true if warning level or higher
         */
        fun isWarning(severity: CompilerMessageSeverity): Boolean
    }
}

Source Location Information

Source file location information for precise error reporting.

/**
 * Source location information for diagnostic messages
 * Provides file path and position information
 */
interface CompilerMessageSourceLocation {
    /** Source file path */
    val path: String
    
    /** Line number (1-based) */
    val line: Int
    
    /** Column number (1-based) */
    val column: Int
    
    /** Line content for context */
    val lineContent: String?
    
    companion object {
        /**
         * Create source location
         * 
         * @param path File path
         * @param line Line number (1-based)
         * @param column Column number (1-based)
         * @param lineContent Optional line content
         * @return Source location instance
         */
        fun create(
            path: String,
            line: Int,
            column: Int,
            lineContent: String?
        ): CompilerMessageSourceLocation
    }
}

Message Renderers

Pluggable message rendering system for different output formats and tools.

/**
 * Interface for rendering diagnostic messages
 * Supports different output formats for various tools
 */
interface MessageRenderer {
    /**
     * Render diagnostic message to string
     * 
     * @param severity Message severity level
     * @param message Message content
     * @param location Source location information
     * @return Formatted message string
     */
    fun render(
        severity: CompilerMessageSeverity,
        message: String,
        location: CompilerMessageSourceLocation?
    ): String
    
    /**
     * Get path representation
     * Controls how file paths are displayed
     * 
     * @param location Source location
     * @return Formatted path string
     */
    fun getPath(location: CompilerMessageSourceLocation): String
    
    companion object {
        /** Plain text renderer with full file paths */
        val PLAIN_FULL_PATHS: MessageRenderer
        
        /** Plain text renderer with relative file paths */
        val PLAIN_RELATIVE_PATHS: MessageRenderer
        
        /** Plain text renderer without file paths */
        val PLAIN_WITHOUT_PATHS: MessageRenderer
    }
}

Specialized Message Renderers

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

/**
 * Plain text message renderer
 * Standard text output for command-line tools
 */
class PlainTextMessageRenderer(
    private val withPaths: Boolean = true
) : MessageRenderer {
    override fun render(
        severity: CompilerMessageSeverity,
        message: String,
        location: CompilerMessageSourceLocation?
    ): String
}

/**
 * Xcode-compatible message renderer
 * Formats messages for Xcode IDE integration
 */
class XcodeStyleMessageRenderer : MessageRenderer {
    override fun render(
        severity: CompilerMessageSeverity,
        message: String,
        location: CompilerMessageSourceLocation?
    ): String
}

/**
 * Gradle-compatible message renderer
 * Formats messages for Gradle build tool integration
 */
class GradleStyleMessageRenderer : MessageRenderer {
    override fun render(
        severity: CompilerMessageSeverity,
        message: String,
        location: CompilerMessageSourceLocation?
    ): String
}

Printing Message Collector

Concrete message collector that prints messages to output streams.

/**
 * Message collector that prints to output streams
 * Supports custom renderers and severity filtering
 */
class PrintingMessageCollector(
    private val stream: PrintStream,
    private val messageRenderer: MessageRenderer,
    private val verbose: Boolean
) : MessageCollector {
    
    /**
     * Create printing message collector
     * 
     * @param stream Output stream for messages
     * @param messageRenderer Message rendering strategy
     * @param verbose Enable verbose output (all severity levels)
     */
    constructor(
        stream: PrintStream,
        messageRenderer: MessageRenderer,
        verbose: Boolean
    )
    
    override fun report(
        severity: CompilerMessageSeverity,
        message: String,
        location: CompilerMessageSourceLocation?
    ) {
        if (verbose || severity != CompilerMessageSeverity.LOGGING) {
            val renderedMessage = messageRenderer.render(severity, message, location)
            stream.println(renderedMessage)
        }
    }
    
    override fun hasErrors(): Boolean
    override fun clear()
}

Grouping Message Collector

Message collector that groups related messages together.

/**
 * Message collector that groups related messages
 * Useful for organizing diagnostic output by file or module
 */
class GroupingMessageCollector(
    private val delegate: MessageCollector
) : MessageCollector {
    
    /**
     * Start new message group
     * 
     * @param groupName Name for the message group
     */
    fun startGroup(groupName: String)
    
    /**
     * End current message group
     */
    fun endGroup()
    
    override fun report(
        severity: CompilerMessageSeverity,
        message: String,
        location: CompilerMessageSourceLocation?
    )
    
    override fun hasErrors(): Boolean
    override fun clear()
}

Analysis and Diagnostic Reporting

Advanced diagnostic reporting with analysis integration.

/**
 * Analyzer with integrated compiler reporting
 * Combines frontend analysis with diagnostic collection
 */
class AnalyzerWithCompilerReport(
    private val messageCollector: MessageCollector,
    private val languageVersionSettings: LanguageVersionSettings
) {
    /**
     * Check for compilation errors
     * 
     * @return true if compilation should stop due to errors
     */
    fun hasErrors(): Boolean
    
    /**
     * Report analysis result
     * 
     * @param result Analysis result to report
     * @param files Source files analyzed
     */
    fun reportAnalysisResult(
        result: AnalysisResult,
        files: Collection<KtFile>
    )
    
    /**
     * Render diagnostic with context
     * 
     * @param diagnostic Diagnostic to render
     * @return Formatted diagnostic message
     */
    fun renderDiagnostic(diagnostic: Diagnostic): String
}

/**
 * Default diagnostic reporter implementation
 * Standard diagnostic message formatting and reporting
 */
class DefaultDiagnosticReporter(
    private val messageCollector: MessageCollector
) : DiagnosticReporter {
    
    override fun report(
        diagnostic: Diagnostic,
        bindingContext: BindingContext
    ) {
        val severity = diagnostic.severity.toCompilerMessageSeverity()
        val message = renderDiagnosticMessage(diagnostic)
        val location = diagnostic.psiElement?.let { 
            getLocationFromPsiElement(it)
        }
        
        messageCollector.report(severity, message, location)
    }
}

Diagnostic Message Reporter

High-level diagnostic message reporting with rich formatting.

/**
 * Rich diagnostic message reporter
 * Provides detailed diagnostic information with context
 */
class DiagnosticMessageReporter(
    private val messageCollector: MessageCollector,
    private val messageRenderer: MessageRenderer = MessageRenderer.PLAIN_FULL_PATHS
) {
    /**
     * Report diagnostic with full context
     * 
     * @param diagnostic Diagnostic information
     * @param file Source file context
     * @param context Binding context for resolution
     */
    fun reportDiagnostic(
        diagnostic: Diagnostic,
        file: KtFile,
        context: BindingContext
    )
    
    /**
     * Report multiple diagnostics from analysis
     * 
     * @param diagnostics Collection of diagnostics
     * @param context Binding context
     */
    fun reportDiagnostics(
        diagnostics: Collection<Diagnostic>,
        context: BindingContext
    )
    
    /**
     * Report exception as diagnostic
     * 
     * @param exception Exception to report
     * @param location Optional source location
     */
    fun reportException(
        exception: Throwable,
        location: CompilerMessageSourceLocation? = null
    )
}

Usage Examples

Basic Message Collection

import org.jetbrains.kotlin.cli.common.messages.*
import java.io.PrintStream

// Create message collector with plain text renderer
val messageCollector = PrintingMessageCollector(
    stream = System.err,
    messageRenderer = MessageRenderer.PLAIN_FULL_PATHS,
    verbose = true
)

// Report messages with different severity levels
messageCollector.report(
    CompilerMessageSeverity.INFO,
    "Starting compilation of module 'my-app'"
)

messageCollector.report(
    CompilerMessageSeverity.WARNING,
    "Unused import: kotlin.collections.List",
    CompilerMessageSourceLocation.create(
        path = "src/main/kotlin/Main.kt",
        line = 3,
        column = 1,
        lineContent = "import kotlin.collections.List"
    )
)

messageCollector.report(
    CompilerMessageSeverity.ERROR,
    "Unresolved reference: unknownFunction",
    CompilerMessageSourceLocation.create(
        path = "src/main/kotlin/Main.kt", 
        line = 10,
        column = 5,
        lineContent = "    unknownFunction()"
    )
)

// Check for errors
if (messageCollector.hasErrors()) {
    println("Compilation failed due to errors")
}

Custom Message Renderer

// Custom JSON message renderer
class JsonMessageRenderer : MessageRenderer {
    override fun render(
        severity: CompilerMessageSeverity,
        message: String,
        location: CompilerMessageSourceLocation?
    ): String {
        val json = buildJsonObject {
            put("severity", severity.presentableName)
            put("message", message)
            put("timestamp", System.currentTimeMillis())
            
            location?.let { loc ->
                putJsonObject("location") {
                    put("path", loc.path)
                    put("line", loc.line)
                    put("column", loc.column)
                    put("lineContent", loc.lineContent)
                }
            }
        }
        return json.toString()
    }
    
    override fun getPath(location: CompilerMessageSourceLocation): String {
        return location.path
    }
}

// Use custom renderer
val jsonCollector = PrintingMessageCollector(
    stream = System.out,
    messageRenderer = JsonMessageRenderer(),
    verbose = false
)

IDE Integration

// Xcode integration
val xcodeCollector = PrintingMessageCollector(
    stream = System.err,
    messageRenderer = XcodeStyleMessageRenderer(),
    verbose = false
)

// Gradle integration  
val gradleCollector = PrintingMessageCollector(
    stream = System.err,
    messageRenderer = GradleStyleMessageRenderer(),
    verbose = true
)

// Configure in compiler configuration
val configuration = CompilerConfiguration().apply {
    put(CommonConfigurationKeys.MESSAGE_COLLECTOR_KEY, gradleCollector)
}

Grouped Message Collection

val baseCollector = PrintingMessageCollector(
    System.err,
    MessageRenderer.PLAIN_FULL_PATHS,
    true
)

val groupingCollector = GroupingMessageCollector(baseCollector)

// Group messages by module
groupingCollector.startGroup("Module: core")
groupingCollector.report(
    CompilerMessageSeverity.INFO,
    "Compiling core module"
)
groupingCollector.report(
    CompilerMessageSeverity.ERROR,
    "Missing dependency in core module"
)
groupingCollector.endGroup()

groupingCollector.startGroup("Module: api")
groupingCollector.report(
    CompilerMessageSeverity.INFO,
    "Compiling api module"
)
groupingCollector.endGroup()

Filtering Message Collector

// Custom filtering message collector
class FilteringMessageCollector(
    private val delegate: MessageCollector,
    private val minSeverity: CompilerMessageSeverity
) : MessageCollector {
    
    override fun report(
        severity: CompilerMessageSeverity,
        message: String,
        location: CompilerMessageSourceLocation?
    ) {
        if (severity.ordinal >= minSeverity.ordinal) {
            delegate.report(severity, message, location)
        }
    }
    
    override fun hasErrors(): Boolean = delegate.hasErrors()
    override fun clear() = delegate.clear()
}

// Only show warnings and errors
val filteringCollector = FilteringMessageCollector(
    delegate = PrintingMessageCollector(
        System.err,
        MessageRenderer.PLAIN_FULL_PATHS,
        true
    ),
    minSeverity = CompilerMessageSeverity.WARNING
)

Diagnostic Integration

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

// Create analyzer with reporting
val analyzerWithReport = AnalyzerWithCompilerReport(
    messageCollector = messageCollector,
    languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT
)

// Analyze and report
val analysisResult = analyzeFiles(sourceFiles, environment)
analyzerWithReport.reportAnalysisResult(analysisResult, sourceFiles)

if (analyzerWithReport.hasErrors()) {
    return ExitCode.COMPILATION_ERROR
}

Exception Reporting

// Enhanced message collector with exception handling
class ExceptionHandlingMessageCollector(
    private val delegate: MessageCollector
) : MessageCollector by delegate {
    
    fun reportException(
        exception: Throwable,
        context: String? = null,
        location: CompilerMessageSourceLocation? = null
    ) {
        val message = buildString {
            context?.let { append("$it: ") }
            append(exception.message ?: exception.javaClass.simpleName)
            
            // Add stack trace for debugging
            if (exception.stackTrace.isNotEmpty()) {
                append("\n")
                exception.stackTrace.take(5).forEach { frame ->
                    append("  at ${frame}\n")
                }
            }
        }
        
        delegate.report(
            CompilerMessageSeverity.EXCEPTION,
            message,
            location
        )
    }
}

// Usage
val exceptionCollector = ExceptionHandlingMessageCollector(messageCollector)

try {
    // Compilation code
} catch (e: Exception) {
    exceptionCollector.reportException(
        e,
        "Compilation failed",
        CompilerMessageSourceLocation.create("build.gradle.kts", 1, 1, null)
    )
}

Performance Monitoring Integration

// Message collector with performance monitoring
class PerformanceMonitoringCollector(
    private val delegate: MessageCollector
) : MessageCollector by delegate {
    
    private var messageCount = 0
    private var errorCount = 0
    private var warningCount = 0
    private val startTime = System.currentTimeMillis()
    
    override fun report(
        severity: CompilerMessageSeverity,
        message: String,
        location: CompilerMessageSourceLocation?
    ) {
        messageCount++
        when (severity) {
            CompilerMessageSeverity.ERROR, 
            CompilerMessageSeverity.EXCEPTION -> errorCount++
            CompilerMessageSeverity.WARNING,
            CompilerMessageSeverity.STRONG_WARNING -> warningCount++
            else -> {}
        }
        
        delegate.report(severity, message, location)
    }
    
    fun printStatistics() {
        val duration = System.currentTimeMillis() - startTime
        delegate.report(
            CompilerMessageSeverity.INFO,
            "Compilation completed in ${duration}ms: " +
            "$messageCount messages ($errorCount errors, $warningCount warnings)"
        )
    }
}

// Usage
val performanceCollector = PerformanceMonitoringCollector(baseCollector)
// ... perform compilation ...
performanceCollector.printStatistics()

Multi-Output Message Collection

// Broadcast messages to multiple collectors
class BroadcastMessageCollector(
    private val collectors: List<MessageCollector>
) : MessageCollector {
    
    override fun report(
        severity: CompilerMessageSeverity,
        message: String,
        location: CompilerMessageSourceLocation?
    ) {
        collectors.forEach { collector ->
            collector.report(severity, message, location)  
        }
    }
    
    override fun hasErrors(): Boolean {
        return collectors.any { it.hasErrors() }
    }
    
    override fun clear() {
        collectors.forEach { it.clear() }
    }
}

// Send messages to both console and log file
val consoleCollector = PrintingMessageCollector(
    System.err,
    MessageRenderer.PLAIN_FULL_PATHS,
    false
)

val fileCollector = PrintingMessageCollector(
    PrintStream(File("compilation.log")),
    JsonMessageRenderer(),
    true
)

val broadcastCollector = BroadcastMessageCollector(
    listOf(consoleCollector, fileCollector)
)

Error Handling

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

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

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

Common message handling scenarios:

  • INVALID_SEVERITY_LEVEL: Unknown or invalid severity level
  • RENDERING_ERROR: Error during message formatting or rendering
  • OUTPUT_STREAM_ERROR: Problems writing to output stream
  • SOURCE_LOCATION_ERROR: Invalid or inaccessible source location information

Install with Tessl CLI

npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-compiler

docs

configuration.md

environment.md

index.md

js-wasm-compilation.md

jvm-compilation.md

message-handling.md

plugin-development.md

tile.json