みなさん、こんにちは!
株式会社コードリックの足立です。
コードリックでは様々な分野の課題をITで解決しています。
最近では、クルマエビの陸上養殖システムの開発や外壁塗装のための営業ツールなどを作成しています。
弊社では、VSCodeが開発用のテキストエディタとして採用されています。
開発やメンテが活発でサードパーティ製の拡張機能も豊富にあり、今もっともメジャーなエディタとしての地位を確立しているかと思います。
そんなVSCodeでVueの開発を行っているのですが、VueのstyleにSassを指定すると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"],
==== 以下略 ====
}
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()
)
)
}
provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.Location[]
/**
* 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)
)
)
)
}