こんにちは!日々のフロントエンド・バックエンド開発、本当にお疲れ様です。
TypeScriptやJavaScriptを書いていると、「こういう独自のコーディング規約や設計ルール、チーム全員に守ってほしいけれど、既存のESLintやPrettierのルールだけではどうしてもカバーしきれない……」と頭を悩ませた経験、ありませんか?
例えば、「特定のレガシーな関数を呼び出している箇所は、必ず新しいラッパー関数経由にさせたい」「ドメイン層のファイル内では、特定のインフラストラクチャ層のモジュールを直接インポートしてはならない」といった、ビジネスロジックやプロジェクト特有のアーキテクチャ制約です。
これらをコードレビューで人力チェックするのは、レビュアーにとってもレビューされる側にとってもコストが高すぎますよね。
そこで今回ご紹介するのが、WebStorm(IntelliJプラットフォーム)のカスタムインスペクション(静的解析)の開発です。
これをマスターすれば、開発者がコードを書いている「まさにその瞬間」にIDEがリアルタイムで規約違反を検知し、赤く波線を引いて警告してくれるだけでなく、ワンクリックで正しいコードに修正(クイックフィックス)できるようになります。これをチームに導入できれば、コードレビューの負荷は劇的に下がり、品質は一瞬で均一化されます。
今回は、IntelliJ Platform SDKの世界へ踏み込み、自分専用のカスタムインスペクションを作ってチームの規約を強制する術を、優しく丁寧に解説していきますね。これを読めば、あなたのWebStormが「世界で一番優秀な専属レビュアー」に生まれ変わりますよ!
—
なぜWebStormの「インスペクション」なのか?
世の中にはESLintやBiomeなど、素晴らしい静的解析ツールがたくさんあります。では、なぜあえてWebStormのインスペクション機能を作る必要があるのでしょうか?
その答えは、「IDEの圧倒的なコンテキスト理解と即時性」にあります。
- リアルタイム性: ファイルを保存するすら待たず、キーボードを叩いているその瞬間にAST(抽象構文木)を解析して警告を出せます。
- 強力なUI統合: WebStormのエディタ内に直接警告やヒントを表示し、Alt + Enter(macOSならOption + Enter)で自動修正(Quick Fix)のメニューをシームレスに呼び出せます。
- プロジェクト構造の把握: 単一のファイルだけでなく、プロジェクト全体のモジュール依存関係やシンボルを横断した高度な解析が可能です。
IntelliJプラットフォームの内部では、コードは常にPSI(Program Structure Interface)と呼ばれる高度なツリー構造としてメモリ上に保持されています。このPSIを操作するプラグインを書くことで、TypeScriptやJavaScriptのコードの構造を完全に把握し、自在にバリデーションできるというわけです。
—
開発環境のセットアップ:最強のプラグイン開発ベッドを作る
まずは、WebStormのプラグイン(カスタムインスペクション)を開発するための環境を整えましょう。
実は、IntelliJ系のプラグイン開発には、公式が提供している専用のIDE「IntelliJ IDEA Community Edition」を使うのが最もスムーズです。WebStormそのものを拡張するプラグインも、IntelliJ IDEAをベースに開発します。
1. 必要なツールの導入
- IntelliJ IDEA Community Edition(最新版)をインストールします。
- プラグイン開発用のテンプレート(Gradleベース)を使用するため、特別な追加インストールの必要はほとんどありません。
2. プロジェクトの初期化(Gradle Plugin Template)
JetBrains公式が提供している「IntelliJ Platform Plugin Template」を使うのが現代のデファクトスタンダードです。GitHubのテンプレートからリポジトリを作成し、お手元のマシンにクローンします。
プロジェクトルートにある `build.gradle.kts`(Kotlin DSL)を覗いてみましょう。ここにプラグインのビルド設定や依存関係が記述されています。
plugins {
// IntelliJ Platform Gradle Pluginの適用
id(“org.jetbrains.intellij”) version “1.17.3”
kotlin(“jvm”) version “1.9.22”
}
intellij {
// 開発対象とするIDEのバージョン(ここではWebStormを指定)
version.set(“2023.3.4”)
type.set(“WS”) // WebStormを表すコード
// 開発時に利用するプラグイン(JavaScriptやTypeScriptのサポートを含める)
plugins.set(listOf(“com.intellij.javascript”, “JavaScriptLanguage”))
}
tasks {
// JVMターゲットの指定
withType
kotlinOptions.jvmVersion = “17”
}
}
> 💡 先輩からのワンポイントアドバイス
> `intellij.type.set(“WS”)` と指定することで、WebStorm特有のJavaScript/TypeScript解析エンジンを開発環境(Sandbox)にロードしてテストできるようになります。ここがプラグイン開発の肝です!
—
実践:禁止された関数呼び出しを検知するインスペクションの実装
今回は、「プロジェクト内で `oldApiCall()` という非推奨の関数が使われていたら警告し、さらにそれを `newApiCall()` にワンクリックで書き換えるクイックフィックスを提供する」というカスタムインスペクションを作ってみましょう。
1. インスペクションのコアロジックを書く
Kotlinを使用して、PSIツリーを走査し、該当するコードパターンを検知するクラスを作成します。
package com.example.mycompany.inspection
import com.intellij.codeInspection.
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall
// 注意: 実際のJS/TS環境ではJSCallExpression等を使用しますが、概念説明としてシンプルに記述します
class DeprecatedApiInspection : LocalInspectionTool() {
// エディタ上に表示される警告文言(Bundle化するのが一般的ですが直書きで解説)
override fun getDisplayName(): String = “非推奨のAPI呼び出しが検出されました”
override fun getGroupDisplayName(): String = “社内コーディング規約”
override fun isEnabledByDefault(): Boolean = true
// 解析を行うビジターを返す
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : PsiElementVisitor() {
override function visitElement(element: PsiElement) {
super.visitElement(element)
// 要素が関数呼び出しであり、かつ関数名が “oldApiCall” であるか判定
if (isOldApiCall(element)) {
holder.registerProblem(
element,
“oldApiCallの使用は禁止されています。newApiCallを使用してください。”,
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
// クイックフィックス(自動修正)をアタッチする
ReplaceWithNewApiQuickFix()
)
}
}
}
}
private fun isOldApiCall(element: PsiElement): Boolean {
// 簡易的な判定ロジック(実際にはJavaScriptのASTノード構造に合わせた判定を行います)
return element.text.startsWith(“oldApiCall(“)
}
}
2. クイックフィックス(自動修正)の実装
警告を出すだけでなく、自動でコードを修正してくれる機能(Quick Fix)をつけることで、開発者の体験は劇的に向上します。
class ReplaceWithNewApiQuickFix : LocalQuickFix {
override fun getFamilyName(): String = “newApiCall() に置き換える”
override fun applyFix(project: com.intellij.openapi.project.Project, descriptor: ProblemDescriptor) {
val element = descriptor.psiElement ?: return
// 実際のコード要素を新しいAPI呼び出しのテキストで置換するファクトリ処理
// (簡易的にテキスト置換のイメージで記述しています)
val newText = element.text.replace(“oldApiCall”, “newApiCall”)
// PSIのエレメントを安全に置換
// element.replace(…) などのIntelliJ APIを使用します
}
}
3. `plugin.xml` への登録
作成したインスペクションをWebStormに認識させるため、`src/main/resources/META-INF/plugin.xml` に定義を追加します。
id = “DeprecatedApiInspection”
displayName = “非推奨APIの検知”
language = “JavaScript”
implementationClass = “com.example.mycompany.inspection.DeprecatedApiInspection”/>
—
動作確認:いざ、サンドボックス環境へ!
コードが書けたら、いよいよ動作確認です。IntelliJ IDEAのGradleツールウィンドウから、以下のタスクを実行します。
./gradlew runIde
このコマンドを実行すると、あなたが作ったプラグインが組み込まれた「専用のWebStormインスタンス(サンドボックス環境)」が新しく立ち上がります。
1. 立ち上がったWebStormで適当なプロジェクトを開き、JS/TSファイルを作成します。
2. ココード内に `oldApiCall();` と記述してみましょう。
3. ジャジャン! エディタ上にリアルタイムで赤波線が走り、「oldApiCallの使用は禁止されています」という警告がポップアップします。
4. さらに `Alt + Enter`(または `Option + Enter`)を押すと、「newApiCall() に置き換える」というクイックフィックスが提案され、選択するだけでコードが一瞬で書き換わります。
この瞬間、思わず「おぉ……!」と声が出てしまうはずです。自分が書いたコードが、世界最高峰のIDEの挙動を直接拡張したのですから。
—
チームへの配布と運用の自動化
せっかく作ったカスタムインスペクション。チームメンバー全員に使ってもらって初めて価値が生まれます。配布と運用のハードルも、非常に低く設計されています。
1. プラグインのビルド:
./gradlew buildPlugin
これで `build/distributions/` ディレクトリに `.zip` ファイル(プラグインの成果物)が生成されます。
2. チームへの共有:
- 生成されたzipファイルを、社内のプライベートなストレージやGitHub Releases、あるいは社内ニッチなプラグインリポジトリに配置します。
- メンバーはWebStormの「設定 (Preferences) -> プラグイン -> 歯車マーク -> ディスクからプラグインをインストール (Install Plugin from Disk)」からzipを選択するだけで、一瞬で導入完了です。
3. CI/CDでの活用(Headless Inspection):
実は、IntelliJプラットフォームのインスペクションは、GUIなし(ヘッドレスモード)でコマンドラインからCI/CD(GitHub Actions等)上でも実行可能です。これにより、「ローカルのIDE」と「リモートのCI」で完全に同一の静的解析ロジックを強制するという、極めて堅牢な開発基盤が完成します。
—
おわりに
今回は、WebStormのプラグイン開発を通じて、自分専用のカスタムインスペクションを作成し、チームの規約を強制するアプローチをご紹介しました。
「既存のツールでは縛りきれない独自のアーキテクチャルールがある」
「コードレビューで毎回同じ指摘をするのに疲れ果てた」
そんなチームの課題を、IDEの力で根本から解決できるのがこのカスタムインスペクション開発の醍醐味です。最初は少し難しく感じるかもしれませんが、PSIという強力な武器を手に入れたあなたなら、どんな複雑なルールでもコード化できるようになります。
これをマスターすれば、あなたのチームの毎日のコーディングとレビューは劇的に楽になり、より本質的な設計や機能開発に集中できるようになりますよ。ぜひ、次のスプリントの空き時間にでも、第一歩を踏み出してみてくださいね!応援しています!