株式会社コードリック株式会社コードリック
トップ
TOP
会社情報
COMPANY
請負開発
ORDER
自社開発
PRODUCT
開発実績
RECORD
お知らせ
NEWS
ブログ
BLOG
お問い合わせ
CONTACT
TOPトップCOMPANY会社情報ORDER請負開発PRODUCT自社サービスRECORD開発実績NEWSお知らせBLOGブログCONTACTお問い合わせ
BLOG
ブログ
  1. TOP > 
  2. BLOG
  3.  > プログラミング
  4.  > VSCodeでVue + SassのPeekができる拡張機能を作ってみた
2023/1/5

VSCodeでVue + SassのPeekができる拡張機能を作ってみた

プログラミング

みなさん、こんにちは!
株式会社コードリックの足立です。
コードリックでは様々な分野の課題をITで解決しています。
最近では、クルマエビの陸上養殖システムの開発や外壁塗装のための営業ツールなどを作成しています。

弊社では、VSCodeが開発用のテキストエディタとして採用されています。
開発やメンテが活発でサードパーティ製の拡張機能も豊富にあり、今もっともメジャーなエディタとしての地位を確立しているかと思います。

そんなVSCodeでVueの開発を行っているのですが、VueのstyleにSassを指定するとPeek機能や定義元へのジャンプ機能が動かないという問題がありました。
下の画像のような機能です。
Peek機能例
今日はこの問題を解決するためにVSCodeの拡張機能を自作した話をしていきます。
ちなみにこの問題は version 1.67(2022年4月) 以降のバージョンで修正されています。ということで、現在は自作した拡張機能は不要になりました。めでたしめでたし。

・事前準備


VSCodeの拡張機能を作るための準備をしていきます。といってもすでに読みやすい記事がいくつもあるので、プロジェクトのひな形を生成する段階までは記事の紹介で割愛します。
以下の記事を参考にするとわかりやすいです。
かんたん!VS Code拡張機能開発
VSCode Extensions(拡張機能) 自作入門 〜VSCodeにおみくじ機能を追加する〜

この拡張機能はVueファイルを読み込んだ時に動作してほしかったので、activationEventsの設定をpackage.jsonに追加しました。
 


{
"name": "vue-sass-peek",
"displayName": "vue-sass-peek",
"description": "",
"version": "0.0.1",
==== 中略 =====
"activationEvents": ["onLanguage:vue"],
==== 以下略 ====
}

・機能を登録するまで


準備ができたので早速実装していきましょう!
Peek機能を作るために以下のファイル構成にすることにしました。
・extension.ts - 拡張機能が有効になったときに動く関数を定義
・SassClass.ts - Sassで定義された単一のブロックを表現するクラスを定義
・SassClassDefinitionProvider.ts - Peek機能を実行するためのdefinition providerを実装 Sassのパーサもここで定義

それではひとつひとつ詳細に中身を見ていき、どのような構造になっているのか見ていきましょう。

import * as vscode from 'vscode'
import { SassClassDefinitionProvider } from './SassClassDefinitionProvider'

export function activate (context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.languages.registerDefinitionProvider(
{ scheme: 'file', language: 'vue' },
new SassClassDefinitionProvider()
)
)
}

まず、extension.tsで拡張機能が有効になったときの動作を記述します。
activate関数の中に書いた動作が実行され、ここではsubscriptionsにPeek機能が呼ばれたとき動作する関数を新たに登録しています。
VSCode標準のPeek機能と同時に呼ばれることになります。(上書きはできないです。こことか参照)
Peek機能を登録するには、スキームと言語を選択し、自作したdefinition providerを渡すことになります。

それでは、次にdefinition providerの作り方を見ていきましょう。
vscode.DefinitionProviderを継承したSassClassDefinitionProviderを定義します。このクラスは以下のメソッドをオーバーライドして実装する必要があります。

provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.Location[]

このメソッドにPeekが実行されたときの振る舞いを定義します。

/**
* override provideDefinition
* @param {TextDocument} document - target document
* @param {Position} position - position
* @param {CancellationToken} token - token
* @returns {Location[]} array of locations of the definitions
*/
provideDefinition (
document: vscode.TextDocument,
position: vscode.Position,
token: vscode.CancellationToken
) {
const targetText = document.getText()
const editor = vscode.window.activeTextEditor

const selection = document.getWordRangeAtPosition(
editor?.selection.active ?? new vscode.Position(0, 0)
)
const selectedText = document.getText(selection)

return this.genSassClassDefinitionsFromText(targetText)
.filter(sassClass => sassClass.className === selectedText)
.map(
targetSassClass =>
new vscode.Location(
document.uri,
new vscode.Range(
document.positionAt(targetSassClass.start),
document.positionAt(targetSassClass.end)
)
)
)
}

definition providerでは、現在開いているドキュメントのオブジェクトと現在のカーソルの位置、動作をキャンセルしてほしいときに送られてくるトークンが渡されます。これらを上手く利用しながら、最終的にPeekする場所を示すLocationオブジェクトを返すのが目標です。
上のコードでは、まずselectionで選択されている範囲のテキストを抽出します。その後、現在開いているVueファイル全体からgenSassClassDefinitionsFromTextメソッドによりすべてのSassのブロックを抽出し、比較してマッチするものがないか探しています。
Locationオブジェクトはマッチしたブロックをまとめて全部返すようにしました。これでPeekしたときに全容がハイライトされるので見やすいです。
genSassClassDefinitionsFromTextをどうやって実装するかですが、記事が長くなったので後編に続きます!
ところで、開発当時にはLanguage ServerにSassがサポートされていた気がするので、LSを使えばパーサの実装は必要ありません。
パーサをあらかた書いた段階で見つけたので、自作パーサをそのまま使っています。Language Serverを使った拡張機能の開発例は以下の記事が読みやすいです。
Language Server Protocolを用いたVSCode拡張機能開発 (後編)

VSCodeの拡張機能を作る方法を、特にPeek機能に絞ってどのように実装を進めていくか確認しました。
機能によって実装するメソッドなどは変わってきますし、WebViewを使って画面にいろいろなコンテンツを表示したり、エディタのUIを改造できたりもするので、ドキュメントを見ながらいろいろ開発してみましょう!
それでは後編で。
back
トップ
TOP
会社情報
COMPANY
請負開発
ORDER
自社サービス
PRODUCT
開発実績
RECORD
お知らせ
NEWS
ブログ
BLOG
お問い合わせ
CONTACT
トップ
TOP
会社情報
COMPANY
請負開発
ORDER
自社サービス
PRODUCT
開発実績
RECORD
お知らせ
NEWS
ブログ
BLOG
お問い合わせ
CONTACT
株式会社コードリック
〒920-0362 石川県金沢市古府3丁目45-2
TEL 076-249-8388 / FAX 076-203-0044
SDGsのロゴ
株式会社コードリック
〒920-0362 石川県金沢市古府3丁目45-2
TEL 076-249-8388 / FAX 076-203-0044
プライバシーポリシー
SDGsのロゴ
©株式会社コードリック. All Rights Reserved.プライバシーポリシー
©株式会社コードリック. All Rights Reserved.