この記事は、はじめてのアドベントカレンダー Advent Calendar 2025 の 17 日目の記事です。今まで読むばかりだったアドカレに初参加です😊 最近 VSCode で Java の開発環境を構築することがあったので、それについてまとめてみました!
はじめに
Java の開発には、IntelliJ IDEA や Eclipse などの統合開発環境 (IDE) が用いられることが多いと思いますが、VSCodeでも Extension Pack for Java などの拡張機能を利用することで、同様の開発環境を構築することができます。
コードの品質を高めるうえで Linter, Formatter の設定は欠かせませんが、IntelliJ IDEA や Eclipse での設定手順の説明は多くあるものの、VSCode での導入手順や CI への組み込みまで詳しく説明するものは多くないため、本記事では後者の導入手順について説明したいと思います。
Linter, Formatter について
Linter とは、ソースコードの構文エラーや潜在的なバグ、プロジェクトで定めたコーディング規約の違反などを検出してくれる静的解析ツールです。ソースコードの実行やコンパイルを行うことなく、命名規則違反や例外の握りつぶし、空ブロックや未使用変数などをチェックしてくれるため、コンパイルエラーにはならないものの品質面で問題となるコードを実行前に検出することができます。Javaで用いられる Linter には SpotBugs や後述する Checkstyle などがあります。
対して Formatter は、プロジェクトのコーディングスタイルに沿うようにソースコードを整形するツールです。ファイルの保存時に Formatter が実行されるように設定することで、改行の挿入や行の折り返し、import文の並び順などが自動的に整形され、開発者間で一貫したコーディングスタイルを保つことができます。Java では今回説明する google-java-format や、複数言語対応でエディタに依存しない Spotless などを用いることができます。
一般的に、Linter は例外の握りつぶしなど潜在的な問題まで検出するものを指しますが、Checkstyle プラグインの Lint 対象は基本的にコーディング規約違反のチェックに限るので注意が必要です。コーディングスタイル以外の静的解析には、SonarLint や SpotBugs などを別途利用します。
実行環境
-
VSCode : ver 1.100.3
$ java --version openjdk 21.0.8 $ gradle --version Gradle 8.13 -
JDK や VSCode の拡張機能
Extention Pack for Javaがインストールされていることを前提としています。
Checkstyle を導入する
1. build.gradle に以下の内容を追記し、プラグインを追加します。
plugins {
id 'checkstyle'
}
checkstyle {
toolVersion = '12.1.2'
configFile = file('config/checkstyle/checkstyle.xml') // 配置するディレクトリやファイル名は任意
}
2. 上記で指定した configFile のパスに、コーディングスタイルを定義した xml ファイルを配置します。今回は Google Java Style Guide に準拠したコーディング規約を用います。
このとき checkstyle.xml の記述は、checkstyleの最新バージョンに沿ったものとなっているため、先ほど記述した build.gradle の toolVersion もそれに合うように設定する必要があります (バージョンが不整合だと Lint 実行時にエラーとなります)。Checkstyle リポジトリの Code ページから最新のリリースバージョンを確認できます。
3. 必要に応じてプロジェクトで採用したいコーディング規約に沿うように checkstyle.xml を書き換えます。
- インデントレベルを 2 → 4 に変更する
<module name="Indentation"> - <property name="basicOffset" value="2"/> - <property name="braceAdjustment" value="2"/> - <property name="caseIndent" value="2"/> + <property name="basicOffset" value="4"/> + <property name="braceAdjustment" value="0"/> + <property name="caseIndent" value="4"/> <property name="throwsIndent" value="4"/> <property name="lineWrappingIndentation" value="4"/> - <property name="arrayInitIndent" value="2"/> + <property name="arrayInitIndent" value="4"/> </module> - import順の変更
Java標準パッケージと自作クラスのimport順についてのルールを追加します。<module name="CustomImportOrder"> <property name="sortImportsInGroupAlphabetically" value="true"/> <property name="separateLineBetweenGroups" value="true"/> - <property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/> + <property name="customImportOrderRules" value="STATIC###STANDARD_JAVA_PACKAGE###THIRD_PARTY_PACKAGE###SPECIAL_IMPORTS"/> + <property name="specialImportsRegExp" value="my\.unique\.domain\.projectname\..*"/> <property name="tokens" value="IMPORT, STATIC_IMPORT, PACKAGE_DEF"/> </module> - Javadoc の存在checkの無効化
Javadocが書かれていないメソッドがあっても pass するように該当部分をコメントアウトしておきます。<!-- <module name="MissingJavadocMethod"> <property name="scope" value="protected"/> <property name="allowMissingPropertyJavadoc" value="true"/> <property name="allowedAnnotations" value="Override, Test"/> <property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF, COMPACT_CTOR_DEF"/> </module> <module name="MissingJavadocType"> <property name="scope" value="protected"/> <property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, RECORD_DEF, ANNOTATION_DEF"/> <property name="excludeScope" value="nothing"/> </module> -->
4. checkstyle違反があったら build が失敗するように変更します。
- <property name="severity" value="${org.checkstyle.google.severity}" default="warning"/>
+ <property name="severity" value="${org.checkstyle.google.severity}" default="error"/>
5. Lint を実行する
以下のコマンドで checkstyle による Lint が正常に実行されるか確認します。
$ ./gradlew check
checkstyleMain と checkstyleTest の 2つの Task が実行されます。checkstyle.xml に構文エラーがあったり、先述したバージョンの不整合があると以下のようなエラーが表示されるので、適宜修正して再実行してください。
$ ./gradlew check
> Task :checkstyleMain FAILED
> Task :checkstyleTest FAILED
FAILURE: Build completed with 2 failures.
1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':checkstyleMain'.
> A failure occurred while executing org.gradle.api.plugins.quality.internal.CheckstyleAction
> An unexpected error occurred configuring and executing Checkstyle.
> Unable to create Root Module: config {/config/checkstyle/checkstyle.xml}.
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
Test コードを Lint 対象としたくない場合は、以下のコマンドで Main のプロダクトコードのみ Lint することができます。
$ ./gradlew checkstyleMain
試しに、以下のようなコーディング規約違反がある状態で Lint をかけてみます。
@Override
public List<Trade> findAll() {
try (var reader = Files.newBufferedReader(
this.csvResource.getFile().toPath(), this.charset
)) {
return reader.lines()
.skip(1)
.map(Line -> UserEntity.fromCsvLine(Line, this.csvConfig.getDelimiter())) // 変数名が大文字始まり
.map(UserEntity::toModel)
.toList();
} catch (IOException e) {
throw new RuntimeException("Failed to read csv file.", e); // インデントレベルが深すぎる
}
}
$ ./gradlew checkstyleMain
> Task :checkstyleMain
[ant:checkstyle] [ERROR] projectroot/src/main/java/my/unique/domain/myproject/infrastructure/repository/user/csv/CsvUserRepository.java:46:26: Lambda parameter name 'Line' must match pattern '^[a-z]([a-z0-9][a-zA-Z0-9]*)?$'. [LambdaParameterName]
[ant:checkstyle] [ERROR] projectroot/src/main/java/my/unique/domain/myproject/infrastructure/repository/user/csv/CsvUserRepository.java:52:17: 'catch' child has incorrect indentation level 16, expected level should be 12. [Indentation]
> Task :checkstyleMain FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':checkstyleMain'.
> A failure occurred while executing org.gradle.api.plugins.quality.internal.CheckstyleAction
> Checkstyle rule violations were found. See the report at: file://myproject/build/reports/checkstyle/main.html
Checkstyle files with violations: 1
Checkstyle violations by severity: [error:3]
* Try:
> Run with --scan to get full insights.
BUILD FAILED in 19s
3 actionable tasks: 2 executed, 1 up-to-date
このようにエラー箇所とその原因が表示されれば、正常に実行できています。修正して Lint が pass すると以下のようにビルドが成功します。
$ ./gradlew checkstyleMain
BUILD SUCCESSFUL in 35s
3 actionable tasks: 2 executed, 1 up-to-date
google-java-format を導入する
先ほど導入した Checkstyle のコーディングスタイルに沿うように、Formatter を導入し、ファイルの保存時に自動整形されるようにします。
1. eclipse-java-google-style からフォーマットルールが記述された xml ファイルをプロジェクト内の任意のディレクトリに配置します。今回は config/formatter/eclipse-java-google-style.xml に配置します。
2. .vscode/settings.json で Formatter が保存時に実行されるように設定します。
{
"java.format.settings.url": "config/formatter/eclipse-java-google-style.xml",
"java.format.settings.profile": "GoogleStyle",
"[java]": {
"editor.formatOnSave": true,
"editor.tabSize": 4
}
}
3. 必要に応じて Format ルールをカスタムします。
<!-- 不要な空行を削除する -->
- <setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="3"/>
+ <setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="0"/>
<!-- 改行を保持する -->
- <setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
+ <setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
<!-- importグループごとに改行を入れる -->
- <setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="0"/>
+ <setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
4. ソースコードを保存して整形されれば ok です。その他詳細な説明はこちら1の記事が詳しいので譲りたいと思います。
Github Actions で CI に組み込む
CI (継続的インテグレーション)2とは、ソフトウェア開発においてコードを頻繁に共有リポジトリに統合する手法のことを指しますが、統合のたびにビルドやテスト、静的解析といったタスクが自動実行される開発プロセスまでを含めて指すことが一般的です。Github では Github Actions を用いてワークフローを作成することで、ソースコードの push や Pull Request の作成などのイベントをトリガーに、Lint や build を自動的に実行する CI パイプラインを構築できます。これにより、開発ブランチのレビューに入る前の段階で問題のあるコードを自動的に検出することができるので、開発効率の向上や、開発者間で一定のコード品質を担保させることが可能になります。
今回は、Lint と Build の job をワークフローに定義し、push や Pull Requestの作成時に自動的に実行されるように設定したいと思います。
ワークフローを記述する
プロジェクトリポジトリの Actions のページにアクセスし、Java with Gradle のページにいくことで、ワークフローのテンプレートとなる YAML ファイルを作成することができます。作成される .github/workflows ディレクトリについては、Github Actions を利用するうえで決められているものになるので注意してください。また、YAML ファイル名は任意なので適当な名前をつけておきましょう。
テンプレートとなる YAML ファイルが作成できたら、具体的なワークフローを以下のように記述していきます。workflow の詳細な書き方はこちら3を参考にしてください。
name: Java CI with Gradle # workflow 名, github の Actionsタブに表示される
on:
# main ブランチに push または PR が出された場合に trigger
push:
branches: ["main"]
pull_request:
branches: ["main"]
jobs:
# lint job を定義
lint:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: 21 # 開発環境のバージョンと揃える
distribution: temurin
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Run Gradle check (lint)
run: ./gradlew check # lintコマンド
# build job を定義
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: "21"
distribution: "temurin"
# Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
# See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
- name: Setup Gradle
uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
- name: Build with Gradle Wrapper
run: ./gradlew build # buildコマンド
YAML ファイルが記述できたら、実際に開発ブランチから main ブランチへのPRを出して workflow が実行されるか確認しましょう。以下のように表示されていれば workflow が正常に実行されています。先ほど、checkstyle 違反があった場合は build も失敗するように設定したので、不適切なコードが含まれている場合 lint, build ともに落ちているはずです。
Branch protection rules で CI の成功を強制する
ここまでの設定で、PR をトリガーに workflow が実行されるようになりましたが、今のままでは、workflow が失敗していてもそのまま開発ブランチをマージできてしまいます。Github では force push や 未レビューのブランチのマージなどを禁止する Branch protection rules を設定することができます。CI check が成功していない場合にはブランチをマージできないように ブランチ保護ルールを追加しましょう。
プロジェクトリポジトリの Settings タブ → Rules → Rulesets と進み、New branch ruleset をクリックします。

ブランチ保護ルール名として適当な名前をつけ、main ブランチに対して、保護ルールが適用されるようにしておきます。

Require status checks to pass にチェックを入れ、さらに Add checks から workflow で決めた job 名を検索し追加します。このとき直近で実行された job 名のみ検索欄に表示されるようになっているので、見つからない場合は一度 job を実行することで追加できるようになります。

このように設定しておくと、CI が成功するまで開発ブランチをマージすることができなくなり、不適切な品質状態のままのコードが main ブランチにマージされることを避けることができます。

CI による workflow が成功するとマージできるようになります。

おわりに
今回は VSCode で Java 開発をする際の Linter, Formatter の導入、Github Actions による CI 構築の手順を説明しました。これらのツールを適切に利用することで、チーム開発時に一定のコード品質を担保できたり、開発効率を向上させたりできると思うので、ぜひ導入して快適な開発体験を構築していただけるとよいと思います。
以上!!
参考
ブランチ保護による CI ステータスチェックの強制
GitHubのブランチ保護でステータスチェックを必須にする
-
Google-java-format の詳細な導入手順
VSCode の Java 開発環境にフォーマッターを設定する ↩ -
CI についての Github ドキュメント
継続的インテグレーション ↩ -
Github Actions の workflow の書き方
【入門】GitHub Actionsとは?概要やメリット、使用例まとめ ↩

