Advanced Kotlin language server with intelligent completion, diagnostics, and seamless Java interoperability for Android development
Android Code Studio provides full-featured Kotlin language support through integration with the Kotlin Language Server (KLS), enabling modern Android development with Kotlin’s expressive syntax and safety features.
KotlinEventHandler: Responds to document change events
The Kotlin language server runs as a separate process, communicating via JSON-RPC protocol over standard input/output streams. This architecture ensures isolation and stability.
Compilation Errors: Syntax errors, type mismatches, and unresolved references
Semantic Warnings: Unused variables, redundant casts, and deprecated API usage
Import Analysis: Missing import detection with quick-fix suggestions
Quick Fixes: Automated import resolution and common error corrections
Type Errors
Import Issues
Warnings
// Type mismatch detectedval number: Int = "text" // Error: Type mismatch// Unresolved referenceval result = unknownFunction() // Error: Unresolved reference
// Missing import - quick fix availableval list = ArrayList<String>() // Quick fix: Import ArrayList// After quick fix applied:import java.util.ArrayListval list = ArrayList<String>() // Resolved
// Unused variable warningfun example() { val unused = 42 // Warning: Variable 'unused' is never used}// Redundant cast warningval text = "Hello" as String // Warning: Cast is redundant
The diagnostic system is powered by KotlinDiagnosticProvider and KotlinImportAnalyzer, which work together to provide actionable error messages and quick fixes.
// Concise data class with auto-generated equals, hashCode, toStringdata class User( val id: Int, val name: String, val email: String) { fun isValid(): Boolean = email.contains("@")}// Usage with copyval user = User(1, "Alice", "[email protected]")val updated = user.copy(name = "Alice Smith")
import kotlinx.coroutines.*class DataRepository { // Suspend function for async operations suspend fun fetchData(): String = withContext(Dispatchers.IO) { // Simulate network call delay(1000) "Data loaded" } // Launch coroutine from main fun loadDataAsync() = CoroutineScope(Dispatchers.Main).launch { val data = fetchData() println(data) }}
Result.kt
// Sealed class for type-safe state representationsealed class Result<out T> { data class Success<T>(val data: T) : Result<T>() data class Error(val exception: Exception) : Result<Nothing>() object Loading : Result<Nothing>()}// Exhaustive when expressionfun <T> handleResult(result: Result<T>) { when (result) { is Result.Success -> println("Data: ${result.data}") is Result.Error -> println("Error: ${result.exception}") Result.Loading -> println("Loading...") }}
Android Code Studio supports Kotlin 1.9+ with compatibility for modern language features including inline value classes, context receivers (experimental), and improved type inference.
The KotlinWorkspaceSetup class handles initialization:
class KotlinWorkspaceSetup(private val context: Context, private val workspace: IWorkspace) { fun setup(processManager: KotlinServerProcessManager) { // Initialize Kotlin compiler classpath // Configure language server process // Set up indexing for project sources }}
The KotlinIndexCache provides efficient symbol lookup:
class KotlinIndexCache { // Cache for class symbols private val classCache = ConcurrentHashMap<String, ClassInfo>() // Cache for function symbols private val functionCache = ConcurrentHashMap<String, List<FunctionInfo>>() // Clear cache on project sync fun clearCache() // Get cache statistics fun getCacheStats(): String}
// Kotlin file with @JvmStatic and @JvmNameobject Utils { @JvmStatic fun formatDate(date: Date): String = SimpleDateFormat().format(date) @JvmName("isValidEmail") fun String.isValid(): Boolean = contains("@")}
The KotlinJavaCompilerBridge enables cross-language navigation and completion:
class KotlinJavaCompilerBridge(private val workspace: IWorkspace) { // Find Java classes for Kotlin completion fun findClassesByPrefix(prefix: String): List<ClassInfo> // Resolve Java symbols from Kotlin code fun resolveJavaSymbol(fqn: String): JavaSymbolInfo?}
// Type 'fun' and press Tabfun functionName(param: Type): ReturnType { // Function body}// Type 'funr' for function with returnfun calculate(): Int { return 42}
// Type 'class' and press Tabclass ClassName { // Class body}// Type 'data' for data classdata class User(val name: String, val age: Int)// Type 'sealed' for sealed classsealed class Result { object Success : Result() object Error : Result()}
// Type 'if' and press Tabif (condition) { // If body}// Type 'when' and press Tabwhen (value) { condition1 -> result1 condition2 -> result2 else -> defaultResult}// Type 'for' and press Tabfor (item in collection) { // Loop body}
Snippets are stored in java/lsp/src/main/assets/data/editor/kotlin/ with scope-specific files:
class KotlinLanguageServer(private val context: Context) : ILanguageServer { override val serverId: String = "kotlin" // Register editor for diagnostic rendering fun registerEditor(file: Path, editor: CodeEditor) // Invalidate cache after project changes fun invalidateCacheAndReindex() // Get cache statistics fun getCacheInfo(): String}
class KotlinCompilerService(private val module: AndroidModule) { // Compile Kotlin sources fun compile(sources: List<Path>): CompilationResult // Get classpath for module fun getClasspath(): List<String>}