Warning
Experimental project with limited functionality. Many features don't work as expected since Kotlin LSP only supports JVM targets.
- How to Use This Plugin
- Quick Start
- Configuration API
- Architecture
- Task Structure
- VS Code Integration
- Usage Examples
- Auto-Detection Features
- Generated Artifacts
- Workspace.json Technical Architecture
- Known Limitations
- Temporary Error Suppression
- Development
- References
This experimental plugin was created out of curiosity to explore if Android development is possible in IDEs other than Android Studio. After JetBrains released the official Kotlin Language Server Protocol (LSP), this opportunity became real.
Android Studio remains unmatched and always will be, but if you need a lightweight editor with auto-completion, auto-imports (crucial for Jetpack Compose), and type checking, this might work.
- JAVA_HOME environment variable set
- javac available on PATH
-
Clone this repository:
git clone git@github.com:desugar-64/kotlin-lsp-workspace-generator.git cd kotlin-lsp-workspace-generator -
Publish to Maven Local:
./gradlew :kotlin-lsp-workspace-gradle-plugin:publishToMavenLocal
-
Add to your Android project (in root
build.gradle.kts):// IMPORTANT: Add mavenLocal() to repositories pluginManagement { repositories { mavenLocal() // Required to pick up locally published plugin gradlePluginPortal() google() mavenCentral() } } plugins { id("cn.entertech.kotlin.lsp.workspace") version "1.0.0-SNAPSHOT" }
-
Generate workspace configuration:
./gradlew generateKotlinLspWorkspace # or sync Gradle project (auto-regeneration is enabled by default) -
Configure your Android app info:
kotlinLspWorkspace { applicationId.set("com.yourapp.package") launcherActivity.set("MainActivity") } -
Generate workspace configuration:
./gradlew generateKotlinLspWorkspace # or sync Gradle project (auto-regeneration is enabled by default) -
Open in VS Code:
- Install Kotlin LSP from GitHub releases
- Open your project folder in VS Code
- The generated
workspace.jsonprovides correct dependency paths - Android AARs transformed to JARs with proper source attachments! - Use Terminal → Run Task to access Android build commands like "Android: Build Debug & Run", "Android: Install Debug", etc.
The Kotlin LSP currently supports JVM modules only (Android/multiplatform support is on their roadmap). This plugin bridges that gap by solving the complex dependency setup problem for Android projects.
The Problem: Android projects have complex dependency structures with AARs, multiple source sets, SDK libraries, and Compose compiler transformations. Without proper configuration, LSP cannot find library JARs and source attachments, navigation to Android SDK sources fails, and code completion is limited to project sources only.
The Solution: This plugin automatically detects your project structure and generates the correct workspace configuration for Kotlin LSP, providing:
- Navigate to library sources - Jump to definitions in AndroidX, Compose, and other dependencies
- Code completion - Intelligent autocomplete for Kotlin and Android APIs
- Import resolution - Automatically resolve and suggest imports for Android libraries
- Syntax highlighting - Rich Kotlin syntax highlighting and error detection
- Cross-references - Find usages and references across the project
- Jetpack Compose: The plugin cannot fix Compose compiler issues. Compose uses compile-time transformations that LSP doesn't understand, so you'll see type errors (code still compiles correctly)
- Android-specific features: LSP doesn't understand Android manifest, resources, or build variants
- Full IDE features: For complete Android development, Android Studio remains the best choice
This plugin makes Kotlin LSP usable for Android projects but doesn't provide the full Android Studio experience.
A comprehensive Gradle plugin that generates workspace configuration files for the JetBrains Kotlin Language Server Protocol (LSP), enabling advanced Kotlin development support in VS Code and other LSP-compatible editors for Android projects.
Plugin ID: cn.entertech.kotlin.lsp.workspace
Extension: kotlinLspWorkspace { }
Architecture: Standalone Gradle plugin with composite build integration
// build.gradle.kts
plugins {
id("cn.entertech.kotlin.lsp.workspace") version "1.0.0-SNAPSHOT"
}
// Generate workspace
./gradlew generateKotlinLspWorkspaceThe plugin provides a clean DSL with smart defaults and minimal required configuration:
kotlinLspWorkspace {
// Core LSP Configuration
workspaceFile.set(file("workspace.json")) // Output location
includeTestDependencies.set(false) // Include test scopes
generateComposeStubs.set(true) // Compose support
copyJarsToTemp.set(true) // Path consistency
// Auto-regeneration
autoRegenerate.set(true) // Rebuild on dependency changes
// VS Code Integration
generateVSCodeConfig.set(true) // Create .vscode/ files
vsCodeDirectory.set(file(".vscode")) // VS Code config location
generateLaunchJson.set(true) // Android debugging setup
generateTasksJson.set(true) // Build task integration
// Android App Launch Configuration (REQUIRED for VS Code tasks)
applicationId.set("com.yourapp.package") // Your app's package name
launcherActivity.set("MainActivity") // Your launcher activity class name
}# Generate workspace only
./gradlew generateKotlinLspWorkspace
# Generate with VS Code config
./gradlew generateVSCodeConfig
# Clean and regenerate everything
./gradlew cleanLspTemp generateKotlinLspWorkspace
# See all available tasks
./gradlew tasks --group="kotlin lsp workspace"The plugin implements a 4-task pipeline that transforms a complex Android project into an LSP-compatible workspace:
./gradlew generateKotlinLspWorkspace
↓
┌─────────────────────┐
│ cleanLspTemp │ ← Clean build directory
└─────────────────────┘
↓
┌─────────────────────┐
│ processLspDependencies │ ← Extract & process all dependencies
└─────────────────────┘
↓
┌─────────────────────┐
│ generateKotlinLspWorkspace │ ← Generate workspace.json
└─────────────────────┘
↓
┌─────────────────────┐
│ generateVSCodeConfig │ ← Generate VS Code config (optional)
└─────────────────────┘
Purpose: Initialize clean working directory for LSP artifacts.
What it does:
- Removes existing
.lsp-tempdirectory frombuild/ - Creates fresh temp directory for processed dependencies
- Ensures consistent state for each workspace generation
Source: CleanLspTempTask.kt
// Simple but critical - ensures no stale artifacts
tempDir.deleteRecursively()
tempDir.mkdirs()Purpose: Transform Android project dependencies into LSP-compatible JAR files and metadata.
What it does:
- AAR Processing: Extracts
classes.jarfrom Android Archive files and creates properly named JARs - Source Attachment: Locates and copies corresponding
-sources.jarfiles - Android SDK Integration: Copies Android platform JARs and creates SDK sources
- Compose Stubs Generation: Creates
ComposableFunction0-22bytecode stubs for Compose compiler compatibility - Dependency Resolution: Maps Gradle configurations (
implementation,compileOnly) to LSP scopes - Path Normalization: Copies all JARs to
.lsp-tempfor consistent absolute paths
🔧 Recent Fixes:
- Fixed AAR processing bug: Now creates properly named JAR files (e.g.,
runtime-android-1.9.0.jar) instead of directory structures - Fixed library name consistency: All dependency names now match between modules and library definitions
- Improved error handling: Better cleanup of temporary extraction directories
Key Functions:
processAarFile(aarFile, tempDir, targetJarName)- Extracts JARs from AAR archives with proper namingaddAndroidSdkLibraries()- Integrates Android SDKaddComposeStubs()- Generates Compose compiler stubscollectLibrariesWithPaths()- Processes dependency graph
Source: ProcessDependenciesTask.kt (647 lines - extracted from original 600-line monolithic task)
// Fixed AAR to JAR extraction with proper naming
fun processAarFile(aarFile: File, tempDir: File, targetJarName: String): File? {
try {
val targetJar = File(tempDir, targetJarName)
// Extract AAR and create properly named JAR
extractedDir = extractAarToTemp(aarFile, tempDir)
val classesJar = File(extractedDir, "classes.jar")
if (classesJar.exists()) {
classesJar.copyTo(targetJar, overwrite = true)
return targetJar
}
} finally {
extractedDir.deleteRecursively() // Proper cleanup
}
return null
}Purpose: Create the final workspace.json file from processed dependency metadata.
What it does:
- Module Definition: Creates module entries with source roots and dependencies
- Library Registry: Defines all external JARs with paths and source attachments
- SDK Configuration: Integrates Android SDK information
- Kotlin Settings: Configures Kotlin-specific LSP parameters
- JSON Assembly: Combines all components into proper workspace structure
Source: GenerateWorkspaceTask.kt
{
"modules": [ /* Project modules with dependencies */ ],
"libraries": [ /* All JARs with sources */ ],
"sdks": [ /* Android SDK info */ ],
"kotlinSettings": [ /* [Kotlin LSP](https://github.com/Kotlin/kotlin-lsp) config */ ]
}Purpose: Generate VS Code-specific configuration files for seamless development experience.
What it does:
- Launch Configuration: Creates
.vscode/launch.jsonfor Android app debugging - Build Tasks: Creates
.vscode/tasks.jsonfor Gradle build integration - Template Processing: Uses configurable templates for custom setups
Source: GenerateVSCodeConfigTask.kt
The plugin automatically generates comprehensive VS Code task configurations for seamless Android development workflow.
Access via Command Palette (Ctrl+Shift+P) → type "Tasks: Run Task":
-
Android: Build Debug⭐ (Default)- Command:
./gradlew assembleDebug - Builds debug APK for development
- Default build task (Ctrl+Shift+B)
- Command:
-
Android: Build Debug & Run🚀 (Complete Workflow)- Sequence: Install Debug → Launch App
- Complete development cycle: build → install → launch
- One-click development - most commonly used
-
Android: Build Release- Command:
./gradlew assembleRelease - Builds optimized release APK
- Command:
-
Android: Install Debug- Command:
./gradlew installDebug - Builds and installs debug APK on device
- Depends on:
Android: Build Debug
- Command:
-
Android: Clean Project- Command:
./gradlew clean - Cleans all build artifacts
- Use when build cache issues occur
- Command:
-
Android: Uninstall Debug- Command:
./gradlew uninstallDebug - Removes debug app from device
- Command:
-
Android: List Devices- Command:
adb devices -l - Shows connected devices and emulators
- Useful for troubleshooting connections
- Command:
-
Android: Launch App- Command:
adb shell am start -n com.example.vscodetest/.MainActivity - Starts app on device (if installed)
- Quick app restart without rebuild
- Command:
-
Android: Clear App Data- Command:
adb shell pm clear com.example.vscodetest - Clears app data and preferences
- Useful for testing first-run scenarios
- Command:
Android: View Logs- Command:
adb logcat -v color - Opens live device logs in dedicated terminal
- Background task - runs continuously
- Essential for debugging runtime issues
- Command:
| Method | Shortcut | Use Case |
|---|---|---|
| Default Build | Ctrl+Shift+B |
Quick debug build (Android: Build Debug) |
| Run Specific Task | Ctrl+Shift+P → "Tasks: Run Task" |
Access any Android task |
| Terminal | Ctrl+`` |
Direct gradle/adb commands |
The plugin automatically detects and configures:
| Component | Detection Method | Fallback |
|---|---|---|
| Android SDK | local.properties → ANDROID_HOME → common paths |
Skip SDK integration |
| Compile SDK Version | Android Gradle Plugin extension | Default to API 36 |
| Kotlin Version | Applied plugins and dependencies | Use 2.0.21 |
| Compose Usage | Compose compiler plugin detection | Generate stubs anyway |
| Project Structure | Gradle project model | Standard Android layout |
| Dependencies | All Gradle configurations | implementation + compileOnly |
build/
├── .lsp-temp/ # Processed dependencies
│ ├── android-36.jar # Android SDK
│ ├── android-36-sources.jar # SDK sources
│ ├── compose-function-stubs.jar # Compose compatibility stubs
│ ├── runtime-android-1.9.0.jar # Fixed: Properly named AAR-extracted JARs
│ ├── runtime-android-1.9.0-sources.jar # AAR source attachments
│ ├── material3-android-1.3.2.jar # AndroidX libraries
│ ├── activity-compose-1.10.1.jar # Activity libraries
│ └── ... # All project dependencies (33+ JARs)
├── lsp-metadata.json # Intermediate processing data
└── reports/
└── problems/ # Gradle build reports
The plugin processes 4 distinct types of dependencies, each requiring different handling strategies:
- Source: Android libraries (AndroidX, Material, Compose)
- Processing: Extract
classes.jarfrom AAR structure, resolve separate-sources.jar - Examples:
androidx.compose.material3:material3-android:1.3.2 - Challenge: AAR contains multiple artifacts, need to extract bytecode and locate sources
- Count: 33 AAR files in typical Compose project
{
"name": "Gradle: androidx.compose.material3:material3-android:1.3.2",
"type": "java-imported",
"roots": [
{
"path": "/build/.lsp-temp/material3-android-1.3.2.jar"
},
{
"path": "/build/.lsp-temp/material3-android-1.3.2-sources.jar",
"type": "SOURCES"
}
]
}- Source: Standard JVM libraries (Kotlin stdlib, coroutines, etc.)
- Processing: Direct copy with source attachment resolution
- Examples:
org.jetbrains.kotlin:kotlin-stdlib:2.2.10 - Count: 15+ JAR files in typical project
{
"name": "Gradle: org.jetbrains.kotlin:kotlin-stdlib:2.2.10",
"type": "java-imported",
"roots": [
{
"path": "/build/.lsp-temp/kotlin-stdlib-2.2.10.jar"
},
{
"path": "/build/.lsp-temp/kotlin-stdlib-2.2.10-sources.jar",
"type": "SOURCES"
}
]
}- Source: Android platform (
android.jarfrom SDK) - Processing: Copy platform JAR, generate sources from SDK sources directory
- Examples:
android:android:36 - Special: Custom group ID, synthetic version, platform-specific handling
{
"name": "Gradle: android:android:36",
"type": "java-imported",
"roots": [
{
"path": "/build/.lsp-temp/android-36.jar"
},
{
"path": "/build/.lsp-temp/android-36-sources.jar",
"type": "SOURCES"
}
]
}- Source: Plugin-generated compatibility libraries
- Processing: Create synthetic JARs for LSP compatibility
- Examples:
androidx.compose.runtime:compose-function-stubs:1.0.0 - Purpose: Provide ComposableFunction0-22 types for Compose compiler
{
"name": "Gradle: androidx.compose.runtime:compose-function-stubs:1.0.0",
"type": "java-imported",
"roots": [
{
"path": "/build/.lsp-temp/compose-function-stubs.jar"
}
]
}Critical Discovery: The plugin uses a 2-tier fallback system for source resolution:
-
Primary:
findSourcesForDependency(groupId, artifactId, version)- Creates detached Gradle configuration
- Resolves
${groupId}:${artifactId}:${version}:sources@jar - Fixed: Now uses actual dependency IDs instead of filename extraction
-
Fallback:
findSourcesJar(originalFile)- Searches Gradle cache directory structure
- Looks for
-sources.jarvariants in same directory - Handles Maven local repository patterns
Each module declares dependencies using these types:
"dependencies": [
{
"type": "library",
"name": "Gradle: androidx.compose.material3:material3-android:1.3.2",
"scope": "compile"
},
{
"type": "moduleSource"
},
{
"type": "inheritedSdk"
}
]Scope Mapping:
"compile"←implementation,apiGradle configurations"provided"←compileOnly, Android SDK, compiler plugins"test"←testImplementation(whenincludeTestDependencies = true)
workspace.json # Main LSP workspace configuration
.vscode/ # VS Code integration (optional)
├── launch.json # Android debugging config
└── tasks.json # Gradle build tasks
@Composable fun MyComposable() { /* LSP shows type errors */ }- Issue: LSP analyzes source code before Compose compiler transformations
- Status: ❌ Cannot fix - fundamental LSP limitation
- Workaround: Errors are cosmetic, code compiles correctly
- Issue: Cannot navigate to Java source files in Android SDK
- Status: ❌ Cannot fix - use IntelliJ IDEA for full Java support
// These errors will appear but code compiles fine:
@Composable fun MyContent() { /* LSP shows errors */ }
// Error: Argument type mismatch: actual type is 'Function0<Unit>', but 'ComposableFunction0<Unit>' was expected
// Error: Cannot access class 'ComposableFunction1'. Check your module classpath for missing or conflicting dependencies- Root Cause:
ComposableFunction0-Ntypes are phantom types that only exist during Compose compiler transformation. They are not real classes that can be placed on classpath. - Technical Details:
- Status: ❌ Cannot fix - fundamental LSP architecture limitation
- Impact: Cosmetic errors only - code compiles and runs correctly
- Workaround: See Temporary Error Suppression
- Issue: Cannot navigate between different library source files
- Status: Cannot fix - tracked by JetBrains
Since Compose type errors are cosmetic and unavoidable, here are code-level suppressions:
Add at the top of Compose files:
@file:Suppress(
"ARGUMENT_TYPE_MISMATCH",
"MISSING_DEPENDENCY_CLASS",
"UNRESOLVED_REFERENCE",
"COMPOSABLE_FUNCTION_REFERENCE"
)
package com.example.yourapp
import androidx.compose.runtime.ComposableFor specific functions:
@Suppress("ARGUMENT_TYPE_MISMATCH", "MISSING_DEPENDENCY_CLASS")
@Composable
fun MyComposableFunction() {
// Your Compose code here
}# Build and test the plugin
./gradlew :kotlin-lsp-workspace-gradle-plugin:build
./gradlew :kotlin-lsp-workspace-gradle-plugin:test
# Use in project (via composite build)
./gradlew generateKotlinLspWorkspace
# Publish to Maven Local (optional)
./gradlew :kotlin-lsp-workspace-gradle-plugin:publishToMavenLocalkotlin-lsp-workspace-gradle-plugin/
├── settings.gradle.kts # Plugin project config
├── build.gradle.kts # Plugin build setup
└── src/main/kotlin/dev/serhiiyaremych/kotlin/lsp/
├── KotlinLspWorkspacePlugin.kt # Main plugin class
├── KotlinLspWorkspaceExtension.kt # Configuration DSL
├── CleanLspTempTask.kt # Cleanup task
├── ProcessDependenciesTask.kt # Core processing logic
├── GenerateWorkspaceTask.kt # Workspace generation
├── GenerateVSCodeConfigTask.kt # VS Code integration
└── LibraryInfo.kt # Data model
- Auto-detection over configuration - Minimize required setup
- Incremental builds - Tasks skip when inputs unchanged
- Path consistency - All JARs use absolute paths
- Error resilience - Graceful handling of missing dependencies
- Gradle best practices - Proper input/output annotations
Generated by: Kotlin LSP Workspace Generator Plugin
Plugin ID: cn.entertech.kotlin.lsp.workspace
Version: 1.0.0-SNAPSHOT
Last Updated: August 2025
Status: In Development
