初めに
現在の職場では、Kotlin の開発を VSCode と Docker を使って行っています。
ただ、実際にこの構成で開発環境を整えようとすると、意外とすんなりいかない部分も多くありました。
特に困ったのが、Kotlin 標準ライブラリや Spring Boot のような外部ライブラリの定義ジャンプが VSCode 上でうまく動かず、「定義が読み込めません」といったエラーが頻繁に発生することでした。
この問題は、正直なところ1年以上ちゃんと解消されずに放置されていた部分でもあります。
この記事では、そういった経験を踏まえて、Kotlin × VSCode × Docker で
安定して補完・定義ジャンプ・開発ができる環境を構築する方法をまとめています。
同じような環境で悩んでいる方の参考になれば嬉しいです。
前提事項
この記事は、以下のような前提のもとで書かれています。
- IntelliJ IDEA の有料版(Ultimate)が使用できない
→ よって、Kotlin 開発には VSCode を使用しています - 開発環境は Docker 上で構築し、ホスト環境には極力依存させたくない
- プロジェクトは Kotlin DSLのGradle(
build.gradle.kts
)で構成されている
⚠️実はそれだけじゃ動かなかった
私は最初、VSCode + Docker の環境で Kotlin の開発を行う場合、
「Gradle と JDK が入った Docker 環境を用意して、Kotlin Language Server(fwcd)を入れれば動くだろう」
と思っていました。
ですが、実際にはそう簡単にはいきませんでした。
例えば、build.gradle.kts
で依存を追加しているのに、
VSCode 上ではそれらのクラスに対して「定義ジャンプ」が効かなかったり、
標準ライブラリでさえ補完が出ず、赤い波線が出続けることもありました。
🔍外部ライブラリに定義ジャンプできない問題とその背景
以下の Issue にあるように、**Kotlin Language Server(fwcd) は .jar
内にあるクラスを見つけたとしても、
その中身の .java
ソースコードを探し当てるのに失敗するケースがあります。
📎 Issue #410 - Go-to-definition not working for external java jar
実際に記録されたエラーログの一部は以下のとおりです:
async2 Found declaration descriptor Lazy Java class org.apache.arrow.flight.FlightServer
async2 Finished in 11 ms
The following file kls:file:///Users/aiguofer/.gradle/caches/modules-2/files-2.1/org.apache.arrow/flight-core/10.0.1/626dcd8fb0f467cb93ca17e8fcfee1bb383b96d3/flight-core-10.0.1.jar!/org/apache/arrow/flight/FlightServer.kt is missing, ignoring from the results.
このログから読み取れる Kotlin Language Server(fwcd) の挙動は以下の通りです:
- KLS は
FlightServer
クラスのシンボル情報(型や定義)までは正常に取得できている - しかし、ソースコードを参照しようとした際に
.kt
ファイルを探しにいってしまう - 実際には
FlightServer
は Java で書かれているため、存在するのは.java
ファイル -
.kt
ファイルが見つからず、KLS は「該当ソースなし」と判断して結果から除外してしまう
つまり、KLS は Java 実装クラスであっても Kotlin ソース(.kt)を前提に参照しようとするため、.java
のソースコードが正しく取得されないケースがあるということです。
💡現時点での回避策
この問題に対して、Kotlin Language Server(fwcd) 側では以下のような対処が検討されてきました。
📎 PR #439 - Use eclipse gradle plugin to get classpath with sources
この PR では、Gradle の Eclipse プラグインを利用して .classpath
を生成し、
その中に含まれる sources.jar 付きの依存情報を **Kotlin Language Server(fwcd) に渡すことで、
Kotlin Language Server(fwcd) が外部ライブラリのソースコードを正しく認識できるようにする提案がされています。
plugins {
// その他の設定
eclipse
}
eclipse {
classpath {
downloadSources = true
}
}
❗️ただし Kotlin DSL では eclipse プラグインが使えない
ここで問題になるのが、Kotlin DSL(build.gradle.kts
)では以下のようなエラーが発生してしまうことです。
Cannot access 'downloadSources': it is private in 'EclipseClasspath'
これは、eclipse.classpath.downloadSources = true
のような記述が Kotlin DSL では非公開(internal)扱いになっているためで、Kotlin DSL 環境ではこの設定を使えません。
✅ 代替手段:idea
プラグインで sources.jar を取得する
Kotlin DSL を使っている場合、eclipse
プラグインの downloadSources = true
はサポートされていないため使えません。
その代替手段として有効なのが、idea
プラグインを使う方法です。
これにより、Kotlin DSL 環境でも sources.jar
を自動で取得できるようになります。
plugins {
kotlin("jvm") version "2.1.10"
id("idea")
}
idea {
module {
isDownloadSources = true
isDownloadJavadoc = true
}
}
この設定を加えたうえで、以下のコマンドを実行します。
./gradlew idea --no-configuration-cache
❗️
--no-configuration-cache
を付ける理由:Gradle の設定キャッシュが有効になっていると、
idea
タスクが古い構成を使い回してしまい、
sources.jar
のダウンロード設定が正しく反映されないことがあります。
そのため、初回実行時や設定変更後は--no-configuration-cache
を付けておくのが確実です。
このコマンドを実行すると、IntelliJ IDEA 用の .iml
ファイルや依存ライブラリ情報と一緒に、dependencies
に含まれる各ライブラリの sources.jar
や javadoc.jar
もダウンロードされるようになります。
Kotlin Language Server(KLS)は、このキャッシュされた sources.jar
をもとに、外部ライブラリのソースコードへ補完や定義ジャンプが可能になります。
🔁 応急処置的な対応策
- Mavenなどから手動で
sources.jar
を取得し、libs/
ディレクトリに配置する
✅ まとめ
VSCode + Docker + Kotlin DSL の構成で Kotlin 開発を行う場合、**Kotlin Language Server(KLS)**で外部ライブラリのソースコードが参照できない問題が発生することがあります。
この問題に対して、次のような対応が有効です:
-
eclipse
プラグインで.classpath
を生成し、sources.jar
を含める- ただし、この方法は Kotlin DSL(
build.gradle.kts
)では設定が制限されており、利用できない
- ただし、この方法は Kotlin DSL(
-
idea
プラグインをbuild.gradle.kts
に追加し、sources.jar
とjavadoc.jar
の取得を有効にする -
./gradlew idea --no-configuration-cache
を実行して依存ライブラリのソースを取得する - 取得された
sources.jar
により、KLS で外部ライブラリの補完や定義ジャンプが可能になる
**IntelliJ(Ultimate)**が使えない環境でも、idea
プラグインを活用することで、
VSCode 上で快適な Kotlin 開発環境を構築することができます。
この記事が、同じような構成で開発を進めている方の助けになれば幸いです。
実際の開発環境は、下記を参考にしてください。