VSCode拡張開発メモ
はじめに
「VSCodeでSQLMesh」で、SQLMesh の VSCode 拡張を確認して、ソースコードもあるし、拡張を拡張しちゃうぞ。と思ったのですが、ソースコードの気持ちが全くわからず…。ということで、ネットにたくさんある VSCode 拡張の作り方の Yet Another なんとかですが、できるだけ最新の公式から。
概要
拡張機能でできること(の例)
- VS Code の外観を色やファイルアイコンのテーマで変更する - Theming
- UI にカスタム コンポーネントとビューを追加する - ワークベンチの拡張
- HTML/CSS/JS で構築されたカスタム Web ページを表示する Webview を作成する - Webview ガイド
- 新しいプログラミング言語のサポート - 言語拡張の概要
- 特定のランタイムのデバッグをサポートする - デバッガー拡張ガイド
拡張機能の概要
共通機能(の例)
- コマンド、構成、キーバインド、またはコンテキスト メニュー項目を登録します。
-
vscode.commands
APIを使用してコマンドを登録および実行します。 -
contributes.commands
コントリビューション ポイントを使用して、コマンド パレットでコマンドを使用できるようにします。 -
contributes.configuration
コントリビューション ポイント を使用して拡張機能固有の設定を提供します。 -
workspace.getConfiguration
API を使用してそれらを読み取ることができます。 - カスタムキーバインドを追加できます。詳しくは、
contributes.keybindings
とキーバインドのトピックをご覧ください。 - 右クリックすると表示されるカスタムコンテキストメニュー項目を登録できます。詳しくは、
contributes.menus
コントリビューション ポイント をご覧ください。
-
- ワークスペースまたはグローバル データの保存。
-
ExtensionContext.workspaceState
: キーと値のペアを書き込むことができるワークスペースストレージ。VS Code がこのストレージを管理し、同じワークスペースを再度開いたときに復元します。 -
ExtensionContext.globalState
: キー/値のペアを書き込めるグローバルストレージです。VS Code はこのストレージを管理し、拡張機能のアクティベーションごとに復元します。globalState
のsetKeysForSync
メソッド のを使って同期対象のキーを設定することで、グローバルストレージ内のキー/値のペアを選択的に同期できます。 -
ExtensionContext.storageUri
: 拡張機能が読み取り/書き込み権限を持つローカルディレクトリを指す、ワークスペース固有のストレージURI。現在のワークスペースからのみアクセス可能な大きなファイルを保存する必要がある場合に適しています。 -
ExtensionContext.globalStorageUri
: 拡張機能が読み取り/書き込み権限を持つローカルディレクトリを指すグローバルストレージURI。これは、すべてのワークスペースからアクセスできる大きなファイルを保存する必要がある場合に適したオプションです。 -
ExtensionContext.secrets
: シークレット(または機密情報)を暗号化して保存するグローバルストレージ。これらの情報はマシン間で同期されません。VS Codeデスクトップ版では、Electron の safeStorage API を活用します。VS Code for the Webでは、Double Key Encryption(DKE)実装を使用します。
-
- 通知メッセージを表示します。
- クイックピックを使用してユーザー入力を収集します。
-
vscode.QuickPick
APIを使用すると、ユーザー入力を簡単に収集したり、複数のオプションから選択させたりすることができます。
-
- システム ファイル ピッカーを開いて、ユーザーがファイルまたはフォルダーを選択できるようにします。
-
window.showOpenDialog
API を使用してシステム ファイル ピッカーを開き、ファイルまたはフォルダーを選択できます。
-
- 長時間実行される操作を示すには、Progress API を使用します。
-
vscode.Progress
APIを使用して、ユーザーに進捗状況の更新を報告できます。
-
テーマ設定(の例)
- ソースコードの色を変更します。
-
tokenColors
は、エディタ内でのハイライト表示の色とスタイルを定義します。このトピックに関する詳細は、構文ハイライトガイドをご覧ください。 -
semanticTokenColors
マッピングとsemanticHighlighting
設定により、エディターでのハイライト表示を強化できます。セマンティックハイライトガイドでは、関連するAPIについて説明しています。
-
- VS Code UI の色を変更します。
- UI コンポーネントの色を制御する
colors
マッピング。
- UI コンポーネントの色を制御する
- 既存の TextMate テーマを VS Code に移植します。
- カスタム ファイル アイコンを追加します。
- 一意のファイル アイコン識別子から画像またはフォント アイコンへのマッピングを作成します。
- ファイル名またはファイル言語の種類によって、ファイルをこれらの一意のファイル アイコン識別子に関連付けます。
宣言型言語機能(の例)
- 一般的な JavaScript スニペットを拡張機能にバンドルします。
- VS Code に新しいプログラミング言語について伝えます。
- プログラミング言語の文法を追加または置き換えます。
- 文法注入を使用して既存の文法を拡張します。
- 既存の TextMate 文法を VS Code に移植します。
プログラム言語機能(の例)
- API の使用例を表示するホバーを追加します。
- 診断を使用して、ソース コード内のスペルまたはリンター エラーを報告します。
- HTML 用の新しいコード フォーマッタを登録します。
- 豊富でコンテキストに応じた IntelliSense を提供します。
- 言語に折りたたみ、パンくずリスト、アウトラインのサポートを追加します。
ワークベンチ拡張機能(の例)
- ファイル エクスプローラーにカスタム コンテキスト メニュー アクションを追加します。
- サイド バーに新しいインタラクティブな TreeView を作成します。
-
contributes.views
コントリビューションポイントを使用すると、任意のビューコンテナに表示される新しいビューを追加できます。
-
- 新しいアクティビティ バー ビューを定義します。
- ステータス バーに新しい情報を表示します。
- StatusBarItem 拡張機能は、ステータスバーに表示されるカスタム項目を作成できます。
- WebView APIを使用してカスタム コンテンツをレンダリングします。
- Webview は、HTML/CSS/JavaScript で構築された高度にカスタマイズ可能なビューです。エディターグループ領域では、テキストエディターの横に表示されます。Webview の詳細については、Webview ガイドをご覧ください。
- ソース管理プロバイダーに貢献します。
デバッグ(の例)
-
デバッグ アダプターの実装を提供することで、VS Code のデバッグ UI をデバッガーまたはランタイムに接続します。
-
デバッガー拡張機能でサポートされる言語を指定します。
-
デバッガーによって使用されるデバッグ構成属性に関する豊富な IntelliSense とホバー情報を提供します。
-
デバッグ構成スニペットを提供します。
-
動的に作成されたデバッグ構成に基づいてデバッグ セッションを開始します。
-
デバッグ セッションのライフサイクルを追跡します。
-
プログラムでブレークポイントを作成および管理します。
制限
- 拡張機能はVS Code UIのDOMにアクセスできません。
- ユーザーまたは拡張機能によって提供されるカスタム スタイル シートは、DOM 構造とクラス名に対して機能します。
Get Started(もしくは Hello world)
Your First Extension
事前準備
git と node をインストールします。今回は Windows でやるので、git for Windows と nvm-windows を入れます。
nvm は、git bash で以下のようにして、node や npm や npx が使えるようにします。
$ nvm install lts
Downloading node.js version 22.20.0 (64-bit)...
Extracting node and npm...
Complete
Installation complete.
If you want to use this version, type:
nvm use 22.20.0
$ nvm use 22.20.0
Now using node v22.20.0 (64-bit)
VSCode拡張プロジェクト構築
サイトに書いてあるとおりですが、
$ npx --package yo --package generator-code -- yo code
_-----_ ╭──────────────────────────╮
| | │ Welcome to the Visual │
|--(o)--| │ Studio Code Extension │
`---------´ │ generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? What type of extension do you want to create? (Use arrow keys)
❯ New Extension (TypeScript)
New Extension (JavaScript)
New Color Theme
New Language Support
New Code Snippets
New Keymap
New Extension Pack
New Language Pack (Localization)
New Web Extension (TypeScript)
New Notebook Renderer (TypeScript)
こんな感じで止まるので、選択肢や入力候補の出てるやつは、以下のようになるように Enter
していきます。
? What type of extension do you want to create? New Extension (TypeScript)
? What's the name of your extension? HelloWorld
? What's the identifier of your extension? helloworld
? What's the description of your extension?
? Initialize a git repository? Yes
? Which bundler to use? unbundled
? Which package manager to use? npm
Writing in C:\Users\araki\workspace\vscode-ext\helloworld...
create helloworld\.vscode\extensions.json
create helloworld\.vscode\launch.json
create helloworld\.vscode\settings.json
create helloworld\.vscode\tasks.json
create helloworld\package.json
create helloworld\tsconfig.json
create helloworld\.vscodeignore
create helloworld\vsc-extension-quickstart.md
create helloworld\.gitignore
create helloworld\README.md
create helloworld\CHANGELOG.md
create helloworld\src\extension.ts
create helloworld\src\test\extension.test.ts
create helloworld\.vscode-test.mjs
create helloworld\eslint.config.mjs
Changes to package.json were detected.
Running npm install for you to install the required dependencies.
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
added 259 packages, and audited 260 packages in 35s
74 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Your extension helloworld has been created!
To start editing with Visual Studio Code, use the following commands:
code helloworld
Open vsc-extension-quickstart.md inside the new extension for further instructions
on how to modify, test and publish your extension.
For more information, also visit http://code.visualstudio.com and follow us @code.
? Do you want to open the new folder with Visual Studio Code? Open with `code`
最後で Open with code
と VSCode が helloworld フォルダを開いて起動します。起動した VSCode で src/extension.ts
を開いて、デバックパネルでデバック実行 Run Extension
します。そうすると、もう一つ VSCode が Hello World 拡張入りで起動しますので、Shift + Ctrl + P
から Hello World
を選びます。
サイトの記載は、そうすると、こうなりますよ。という意味です。
メッセージの変更はコピペすれば OK。Developer: Reload Window
は、現時点では、Developer: Reload Webview
(開発者:Webビューの再読み込み)になっていました。
Extension Anatomy
記述された対象のバージョンが古いと内容が変わるので、注意が必要です。以下を探しても見つかりません。
Registers the onCommand Activation Event: onCommand:helloworld.helloWorld, so the extension becomes activated when user runs the Hello World command.
で、今回生成されたものを添付します。
{
"name": "helloworld",
"displayName": "HelloWorld",
"description": "",
"version": "0.0.1",
"engines": {
"vscode": "^1.104.0"
},
"categories": [
"Other"
],
"activationEvents": [],
"main": "./out/extension.js",
"contributes": {
"commands": [
{
"command": "helloworld.helloWorld",
"title": "Hello World"
}
]
},
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"pretest": "npm run compile && npm run lint",
"lint": "eslint src",
"test": "vscode-test"
},
"devDependencies": {
"@types/vscode": "^1.104.0",
"@types/mocha": "^10.0.10",
"@types/node": "22.x",
"@typescript-eslint/eslint-plugin": "^8.42.0",
"@typescript-eslint/parser": "^8.42.0",
"eslint": "^9.34.0",
"typescript": "^5.9.2",
"@vscode/test-cli": "^0.0.11",
"@vscode/test-electron": "^2.5.2"
}
}
-
name
およびpublisher
: VS Code は<publisher>.<name>
を拡張機能の一意の ID として使用します。例えば、Hello World サンプルの ID はvscode-samples.helloworld-sample
です。VS Code はこの ID を使用して拡張機能を一意に識別します。 -
main
: 拡張機能のエントリーポイント。 -
activationEvents
およびcontributes
: アクティベーションイベント(拡張機能がアクティブになるイベント)と貢献ポイント(VSCode のどこを拡張するのか)。 -
engines.vscode
: これは、拡張機能が依存する VS Code API の最小バージョンを指定します。
Your First Extension の演習でメッセージを変更した後のものです。ポイントはコメントのとおりなので、翻訳しました。
// モジュール「vscode」には VS Code 拡張 API が含まれています
// モジュールをインポートし、以下のコードでエイリアス vscode を使用して参照します
import * as vscode from 'vscode';
// このメソッドは拡張機能がアクティブ化されたときに呼び出されます
// 拡張機能はコマンドが最初に実行されたときにアクティブ化されます
export function activate(context: vscode.ExtensionContext) {
// コンソールを使用して、診断情報 (console.log) とエラー (console.error) を出力します。
// このコード行は、拡張機能が有効化されたときに一度だけ実行されます。
console.log('Congratulations, your extension "helloworld" is now active!');
// コマンドはpackage.jsonファイルで定義されています
// 次に、registerCommandを使用してコマンドの実装を指定します
// commandIdパラメータは、package.jsonのcommandフィールドと一致する必要があります
const disposable = vscode.commands.registerCommand('helloworld.helloWorld', () => {
// ここに記述したコードは、コマンドが実行されるたびに実行されます。
// ユーザーにメッセージボックスを表示します
vscode.window.showInformationMessage('Hello VS Code');
});
context.subscriptions.push(disposable);
}
// このメソッドは拡張機能が非アクティブ化されたときに呼び出されます
export function deactivate() {}
Wrapping Up
ここは、Get Started 以外の各章の概要が書いてあります。
拡張ガイド
AI(いろいろ)、Notebook(Jupyterみたいな)、Web Extensions(VS Code を Web で使用する場合)、Telemetry (使用状況データを収集し、Microsoft に送信)が上の一覧にはありません。
UXガイドライン
コンテナ
コンテナはVS Codeインターフェースの中で、1つ以上のアイテムをレンダリングする大きなセクションと考えることができます。
アクティビティバー(一番左端)
拡張機能は、プライマリサイドバーにビューをレンダリングするビューコンテナとして機能するアイテムをアクティビティバーに追加できます。
プライマリサイドバー(左)
アクティビティバーのアイテム(ビューコンテナ)をクリックすると、プライマリサイドバーが開き、そのビューコンテナに関連付けられた1つ以上のビューが表示されます。
セカンダリサイドバー(右)
ユーザーは、ターミナルビューや問題ビューなどのビューをセカンダリサイドバーにドラッグして、レイアウトをカスタマイズできます。
エディタ(主役)
エディター領域には、1つ以上のエディターグループが含まれます。拡張機能は、エディター領域で開くカスタムエディターやWebビューを提供できます。また、エディターツールバーに追加のアイコンボタンを表示するエディターアクションを提供することもできます。
パネル(下)
拡張機能では、アクティビティバー/プライマリサイドバーではなく、パネルにビューコンテナを追加することもできます。
ステータスバー
ステータスバーには、2つのステータスバー項目のグループが表示されます。
アイテム
ビュー
ビューは、ツリー・ビュー、ウェルカム・ビュー、または Webview・ビューの形式で提供され、インターフェイスの他の領域にドラッグできます。
ビュー・ツールバー
拡張機能は、ビュー・ツールバーにボタンとして表示されるビュー固有のアクションを公開できます。
サイドバー・ツールバー
ビュー・コンテナー全体を対象とするアクションは、サイドバー・ツールバーにも公開できます。
エディター・ツールバー
拡張機能は、エディター・ツールバーで直接エディターにスコープされたエディター・アクションを提供できます。
パネル・ツールバー
パネル・ツールバーには、現在選択されているビューにスコープされたオプションが表示されます。
ステータスバー項目
左側のステータスバー項目はワークスペース全体にスコープが設定されています。右側の項目はアクティブなファイルにスコープが設定されています。
一般的なUI要素
Ctrl + Shift + P
)
コマンドパレット(拡張機能は、コマンド パレットに表示されるコマンドを提供して、一部の機能をすばやく実行できます。
クイックピック(タイトルバー中央の入力フィールド)
クイックピックは、ユーザーの入力を様々な方法で取得します。単一の選択、複数の選択、あるいは自由形式のテキスト入力を求めることもできます。
通知(右下ポップアップ)
通知は、情報、警告、エラーメッセージをユーザーに伝えるために使用されます。また、進行状況を示すためにも使用できます。
Webviews
Webviews を使用すると、VS Code の「ネイティブ」 API を超えるユースケース向けにカスタム コンテンツと機能を表示できます。
コンテキストメニュー(右クリック)
コマンドパレットの一貫した場所とは対照的に、コンテキスト メニューを使用すると、ユーザーは特定の場所からアクションを実行したり、何かを構成したりすることができます。
ウォークスルー(最初にでるやつ?)
ウォークスルーは、豊富なコンテンツを備えた複数ステップのチェックリストを通じて、拡張機能へのユーザーオンボーディングに一貫したエクスペリエンスを提供します。
設定
設定により、ユーザーは拡張機能に関連するオプションを構成できます。
言語拡張
言語拡張の概要
宣言型言語機能
宣言型言語機能は設定ファイルで定義されます。例えば、
- 構文の強調表示
- スニペット補完
- 括弧のマッチング
- ブラケット自動閉鎖
- 括弧の自動囲み
- コメントの切り替え
- 自動インデント
- 折り畳み(マーカーによる)
宣言型言語機能を提供する言語拡張機能を記述するためのガイドが 3 つあります。
- 構文ハイライトガイド: VS Code は構文ハイライトに TextMate 文法を使用します。このガイドでは、シンプルな TextMate 文法を記述し、それを VS Code 拡張機能に変換する手順を説明します。
- スニペット補完ガイド: このガイドでは、一連のスニペットを拡張機能にバンドルする方法について説明します。
- 言語設定ガイド: VS Code では、拡張機能を使ってあらゆるプログラミング言語の言語設定を定義できます。このファイルは、コメントの切り替え、括弧の一致/囲み、領域の折りたたみ(レガシー)といった基本的な編集機能を制御します。
プログラム言語の機能
これらの機能は、多くの場合、言語サーバーによって提供されます。言語サーバーは、プロジェクトを分析して動的な機能を提供するプログラムです。例えば、
- ホバー情報(
vscode.languages.registerHoverProvider
) - 自動補完(
vscode.languages.registerCompletionItemProvider
) - 定義へジャンプ (
vscode.languages.registerDefinitionProvider
) - エラーチェック
- 書式設定
- リファクタリング
- 折りたたみ
言語サーバープロトコル(LSP)
言語サーバー (静的コード分析ツール) と言語クライアント (通常はソース コード エディター) 間の通信を標準化することにより、言語サーバー プロトコルでは拡張機能の作成者が 1 つのコード分析プログラムを記述し、それを複数のエディターで再利用できるようになります。
VS Code で言語サーバー拡張機能を実装する方法を説明した詳細なガイドを提供しています。
特殊なケース
- マルチルートワークスペースのサポート
- 埋め込み言語
テストと公開
拡張のテスト
Visual Studio Code は、拡張機能のテスト実行とデバッグをサポートしています。これらのテストは、拡張機能開発ホストと呼ばれる VS Code の特別なインスタンス内で実行され、VS Code API へのフルアクセスが可能です。
生成された拡張機能では、npm run test
または yarn test
を使用して、次のように統合テストを実行できます。
- VS Code の最新バージョンをダウンロードして解凍します。
- 拡張テスト ランナー スクリプトによって指定された Mocha テストを実行します。
セットアップ
現時点では、初期化時のサンプルの導入でセットアップが完了しています。
テストの実施
import { defineConfig } from '@vscode/test-cli';
export default defineConfig({
files: 'out/test/**/*.test.js',
});
テストを実施すると、package.json
の scripts.pretest
scripts.test
に記載のコマンドが以下のように実行されます。
$ npm run test
> helloworld@0.0.1 pretest
> npm run compile && npm run lint
> helloworld@0.0.1 compile
> tsc -p ./
> helloworld@0.0.1 lint
> eslint src
> helloworld@0.0.1 test
> vscode-test
✔ Validated version: 1.104.2
✔ Found at https://update.code.visualstudio.com/1.104.2/win32-x64-archive/stable?released=true
✔ Downloaded VS Code into C:\Users\araki\workspace\vscode-ext\helloworld\.vscode-test\vscode-win32-x64-archive-1.104.2
[main 2025-09-28T07:32:43.903Z] update#setState disabled
[main 2025-09-28T07:32:43.906Z] update#ctor - updates are disabled by the environment
[main 2025-09-28T07:32:44.104Z] Error: Error mutex already exists
at Nu.S (file:///C:/Users/araki/workspace/vscode-ext/helloworld/.vscode-test/vscode-win32-x64-archive-1.104.2/resources/app/out/main.js:128:18399)
ChatSessionStore: Migrating 0 chat sessions from storage service to file system
Started local extension host with pid 9012.
Started initializing default profile extensions in extensions installation folder. file:///c%3A/Users/araki/workspace/vscode-ext/helloworld/.vscode-test/extensions
Completed initializing default profile extensions in extensions installation folder. file:///c%3A/Users/araki/workspace/vscode-ext/helloworld/.vscode-test/extensions
Loading development extension at c:\Users\araki\workspace\vscode-ext\helloworld
Settings Sync: Account status changed from uninitialized to unavailable
Extension Test Suite
✔ Sample test
1 passing (106ms)
[main 2025-09-28T07:32:50.829Z] Extension host with pid 9012 exited with code: 0, signal: unknown.
Exit code: 0
拡張の公開
高品質な拡張機能を作成したら、VS Code 拡張機能マーケットプレイスに公開して、他のユーザーが拡張機能を見つけ、ダウンロードして使用できるようにすることができます。また、拡張機能をインストール可能な VSIX 形式にパッケージ化して、他のユーザーと共有することもできます。
vsce
のインストール(VS Code Extension Manager)
$ npm install -g @vscode/vsce
added 319 packages in 49s
パッケージを作る
$ vsce package
Executing prepublish script 'npm run vscode:prepublish'...
> helloworld@0.0.1 vscode:prepublish
> npm run compile
> helloworld@0.0.1 compile
> tsc -p ./
ERROR It seems the README.md still contains template text. Make sure to edit the README.md file before you package or publish your extension.
とエラーになります。README.md
を変更すると、動くようになります。
$ vsce package
Executing prepublish script 'npm run vscode:prepublish'...
> helloworld@0.0.1 vscode:prepublish
> npm run compile
> helloworld@0.0.1 compile
> tsc -p ./
WARNING A 'repository' field is missing from the 'package.json' manifest file.
Use --allow-missing-repository to bypass.
Do you want to continue? [y/N] y
WARNING LICENSE, LICENSE.md, or LICENSE.txt not found
Do you want to continue? [y/N] y
INFO Files included in the VSIX:
helloworld-0.0.1.vsix
├─ [Content_Types].xml
├─ extension.vsixmanifest
└─ extension/
├─ changelog.md [0.23 KB]
├─ package.json [0.96 KB]
├─ readme.md [2.87 KB]
└─ out/
├─ extension.js [3.02 KB]
└─ test/
└─ extension.test.js [1.94 KB]
DONE Packaged: C:\Users\araki\workspace\vscode-ext\helloworld\helloworld-0.0.1.vsix (7 files, 5.89 KB)
公開リポジトリや LICENSE
ファイルがないと警告がでますが、.vsix
ファイルはできました。この後、公開するには、組織やユーザーの登録が必要なので、今回はここまでにします。
拡張のバンドル
Visual Studio Code 拡張機能をバンドルする第一の理由は、あらゆるプラットフォームで VS Code を使用するすべてのユーザーが確実に動作できるようにするためです。github.dev や vscode.dev などの Web 環境向け VS Code では、バンドルされた拡張機能のみを使用できます。VS Codeがブラウザで実行されている場合、拡張機能用に読み込めるファイルは 1 つだけなので、拡張機能コードは 1 つの Web 対応 JavaScript ファイルにバンドルする必要があります。
継続的インテグレーション
拡張機能の統合テストはCIサービス上で実行できます。この @vscode/test-electron
ライブラリは、CIプロバイダー上で拡張機能のテストを設定するのに役立ち、 Azure Pipelines上の拡張機能のサンプル設定も含まれています。ビルドパイプラインを確認するか、azure-pipelines.yml
ファイルに直接ジャンプしてください。
自動公開
publish コマンドは、vsce
を使用したローカル環境からの公開に似ていますが、パーソナルアクセストークン(PAT)を安全な方法で提供する必要があります。PAT を VSCE_PAT
シークレット変数として保存することで、vsce
はそれを使用できるようになります。シークレット変数は決して公開されないため、CI パイプラインで安全に使用できます。ここも組織やユーザーの登録が必要なので、スキップします。
Azure パイプラインと GitHub アクションと GitLab CI の例が記載されています。
高度なトピック
初心者なので、以下のだけにします。
Python 拡張テンプレート
オリジナルのテンプレートを fork して、ローカルに clone して、README.md
に従って進めます。
uv init --bare
uv venv
uv add nox
uv run nox --session setup
uv add -r src/test/python_tests/requirements.txt
npm install
README.md
に従って、package.json
と bundled/tool/lsp_runner.py
中の以下のプレースホルダーを置換します。
<pytool-module>
<pytool-display-name>
<my-publisher>
<my-github>
<my-extension-project>
<server version>
テンプレートの内容
README.md
にも少し記載がありますが、こう読んだ方がいいかなという感じに整理します。
package.json
contributes.commands
で、コマンド <pytool-display-name>: Restart Server
(コマンドID:<pytool-module>.restart
)を登録します。
contributes.configuration.properties
で、以下の5つの設定項目を登録します。
-
<pytool-module>.args
: 引数の配列 -
<pytool-module>.path
: バイナリへのパス -
<pytool-module>.importStrategy
:<pytool-module>
のインポート元の決定方法 -
<pytool-module>.interpreter
: Python へのパス -
<pytool-module>.showNotifications
: 通知の表示方法
src/extension.ts
activate
と deactivate
のみ定義されていますが、deactivate
は簡単な後処理だけなので、activate
のみ見ていきます。
以下のものを context.subvscriptions.push
していきます。
- 自分用のログ出力チャネル : createOutputChannel ⇒ window.createOutputChannel
- そのチャネルに出力するロガー : registerLogger ⇒ new OutputChannelLogger
- ログレベル変更時ハンドラー(ランゲージサーバクライアントのログレベルを低い方にする)を登録する
- 最初に作ったチャネル用
- VSCode(グローバル)用
- ランゲージサーバーを起動するハンドラーを登録する
- Python インタープリタ変更時 : onDidChangePythonInterpreter(グローバルの独自イベント変数)
- 構成変更時 : onDidChangeConfiguration(グローバルの公式イベント変数)
- リスタートコマンド実行時 : registerCommand ⇒ commands.registerCommand
最後に、restartServer ⇒ createServer
でランゲージサーバーを起動して、そのクライアントオブジェクトをグローバル変数にセットします。
src/common/server.ts
restartServer
と createServer
が定義されていますが、restartServer
は、createServer
プラス前処理。後処理なので、createServer
を見ていきますが、公式の vscode-languageclient
パッケージの ServerOption
と LanguageClientOption
を設定して、LanguageClient
を呼ぶだけです。
ここで SERVER_SCRIPT_PATH
が bundled/tool/lsp_server.py
になっているので、Python のランゲージサーバーが起動され、それと対になるランゲージサーバークライアントが産み落とされます。
bundled/tool/lsp_server.py
pygls.server.LanguageServer
のインスタンスである LSP_SERVER
が実体です。LSP の feature を登録するデコレータで関数を紐づけるので、ここでは、@LSP_SERVER.feature()
デコレータが使われています。
このように入り口を追加できるので、どの機能を使って、何をやるのかを考えれば良いということになります。また、サーバーまわりの共通処理は同じディレクトリの Python コードがそのまま使えそうです。README.md
にもありますが、特殊なケースでは、lsp_runner.py
を更新する必要があるかもしれませんが、基本的には、lsp_server.py
とそこから呼び出される関数を実装していけば良さそうです。
さいごに
ほぼ、自分専用の備忘録になってしまいましたが、誰かのお役に立てば幸いです。
Discussion