2019年8月12日月曜日

Visual Studio Code の LSP 拡張を作る

mikoto2000/lsp4snippet を Visual Studio Code で使いたい。

前提

  • OS: Windows 10 Pro
  • VSCode: 1.37.0
  • Node: v10.16.2
  • npm: 6.4.1

開発に必要なツールのインストール

npmyo, generator-code をインストール。

npm install -g yo generator-code

プロジェクトひな形の作成

yo code で対話的にプロジェクトの作成ができる。

PS C:\Users\mikoto> cd ~/project/
PS C:\Users\mikoto\project> yo code

     _-----_     ╭──────────────────────────╮
    |       |Welcome to the Visual  │
    |--(o)--|Studio Code Extension  │
   `---------´   │        generator!        │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

? What type of extension do you want to create? New Extension (TypeScript)
? What's the name of your extension? snippet
? What's the identifier of your extension? snippet
? What's the description of your extension? Language Support for Snippet.
? Initialize a git repository? Yes
? Which package manager to use? npm
   create snippet\.vscode\extensions.json
   create snippet\.vscode\launch.json
   create snippet\.vscode\settings.json
   create snippet\.vscode\tasks.json
   create snippet\src\test\runTest.ts
   create snippet\src\test\suite\extension.test.ts
   create snippet\src\test\suite\index.ts
   create snippet\.vscodeignore
   create snippet\.gitignore
   create snippet\README.md
   create snippet\CHANGELOG.md
   create snippet\vsc-extension-quickstart.md
   create snippet\tsconfig.json
   create snippet\src\extension.ts
   create snippet\package.json
   create snippet\tslint.json


I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.


npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN snippet@0.0.1 No repository field.
npm WARN snippet@0.0.1 No license field.

added 143 packages from 573 contributors and audited 325 packages in 3.974s
found 0 vulnerabilities


Your extension snippet has been created!

To start editing with Visual Studio Code, use the following commands:

     cd snippet
     code .

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.


PS C:\Users\mikoto\project> # プロジェクト管理の都合でディレクトリの名前変更
PS C:\Users\mikoto\project> mv .\snippet .\vscode-snippet

LSP に必要なパッケージを追加

vscode-languageclient を追加する。

cd vscode-snippet
npm install --save vscode-languageclient

プロジェクトのメタデータを編集

package.json を編集。

{
  "name": "snippet",
  "displayName": "snippet",
  "description": "Language Support for Snippet.",
  "version": "0.0.1",
  "publisher": "mikoto2000",
  "engines": {
    "vscode": "^1.37.0"
  },
  "categories": [
    "Other"
  ],
  "activationEvents": [
    "*"
  ],
  "main": "./out/extension.js",
  "contributes": {},
  "scripts": {
    "vscode:prepublish": "npm run compile",
    "compile": "tsc -p ./",
    "watch": "tsc -watch -p ./",
    "pretest": "npm run compile",
    "test": "node ./out/test/runTest.js"
  },
  "devDependencies": {
    "@types/glob": "^7.1.1",
    "@types/mocha": "^5.2.6",
    "@types/node": "^10.12.21",
    "@types/vscode": "^1.37.0",
    "glob": "^7.1.4",
    "mocha": "^6.1.4",
    "typescript": "^3.3.1",
    "tslint": "^5.12.1",
    "vscode-test": "^1.0.2"
  },
  "dependencies": {
    "vscode-languageclient": "^5.2.1"
  }
}
  1. 発行者(publisher) を追加
  2. スニペットサーバーは常時起動させておきたいので、 activationEvents* に修正
  3. コマンドは必要ないので contributes/commands を削除

LSP サーバー起動コードの実装

import * as vscode from 'vscode';
import { Executable, LanguageClient, LanguageClientOptions, StreamInfo } from 'vscode-languageclient';

export function activate(context: vscode.ExtensionContext) {

  const serverOptions: Executable = {
      // TODO: requirements に「java にパスを通しておくこと」を追加したうえで java に修正
      command: 'C:/Java/openjdk-12.0.1/bin/java',
      args: ['--add-modules=ALL-SYSTEM',
          '--add-opens',
          'java.base/java.util=ALL-UNNAMED',
          '--add-opens', 'java.base/java.lang=ALL-UNNAMED',
          '-Declipse.application=org.eclipse.jdt.ls.core.id1',
          '-Dosgi.bundles.defaultStartLevel=4',
          '-Declipse.product=org.eclipse.jdt.ls.core.product',
          '-Dlog.level=ALL',
          '-noverify',
          '-Dfile.encoding=UTF-8',
          '-Xmx1G',
          // TODO: jar を同梱する
          '-jar',
          'C:/Users/mikoto/project/lsp4snippet/build/libs/lsp4snippet-1.0.0.jar',
          // TODO: config 化
          '--snippet', 'C:/Users/mikoto/project/dotvim/.vim/snippets/java.yaml',
          '--snippet', 'C:/Users/mikoto/project/dotvim/.vim/snippets/markdown.yaml']
  };

  const clientOptions: LanguageClientOptions = {
      documentSelector: [{ scheme: 'file', language: '*' }]
  };

  const disposable = new LanguageClient('lsp4snippet', 'lsp4snippet', serverOptions, clientOptions).start();
  context.subscriptions.push(disposable);
}

// this method is called when your extension is deactivated
export function deactivate() {}
  1. serverOptions で、 LSP サーバー起動に必要な情報を組み立て
  2. LanguageClientOptions.documentSelector で、この拡張が有効になる条件を指定。今回は常時有効にしたいので以下のように設定
    • scheme: file
    • language: *
  3. 「1.」「2.」を使って LanguageClient を作成し、 context.subscriptions に push

動作確認

起動。

code .
vscode-snippet プロジェクト

プロジェクトが開くので、 F5 押下。

ビルドが走り、 vscode-snippet 拡張機能が組み込まれた VSCode が新しく立ち上がるので、 適当なマークダウンファイルを開いて追加した補完候補が表示されることを確認する。

追加した補完が機能している

ドキュメント系は置いておくとして、あとは、jar 組込みとスニペット定義ファイル指定のコンフィグ化ができると、とりあえず使える感じにはなるかな?

以上。

参考資料

0 件のコメント:

コメントを投稿