いい感じに空行を入れて見せてくれるVSCodeの拡張機能を作ってみた

この記事は [Visual Studio Code Advent Calendar 2023](https://qiita.com/advent-calendar/2023/vscode) の8日目の記事です。

# ある嵐の日

某IT会社

先輩「後輩君ちょっといい？このコードのここだけどね、無駄な空行入れないで？」

後輩「・・・・・・無駄とは？」　カカッ(雷鳴)

# 空行入れる/入れない問題

そんなやり取りがプロジェクト崩壊の引き金になるとかならないとかいわれる殺伐とした今の日本社会。

空行を入れる入れないは、個人の経験や美的センスや視力の限界など様々な要素が複雑に絡み合い、しかも実害が無いことが多いために指摘もしづらいのに勝手に直すと角が立つという、非常にセンシティブな問題です。

今回利用するVSCodeの拡張機能の公式サンプルを見ても悩ましさにあふれています。

![空行の迷う例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/fd1064ca-c0c1-830a-f5dd-964499ff5772.png)
（矢印：空行を入れるか入れないか意見が分かれそうな箇所）

そんな社会の闇に光を差し込む（んなわけない）拡張機能を作ってみました。

※ジョークなのでストアでの公開はしません。

# 作り方

[コードレンズの公式サンプル](https://github.com/microsoft/vscode-extension-samples/tree/main/codelens-sample)をダウンロードし、npm install します。

次に、CodelensProvider.ts を次のように変更します。

```ts:CodelensProvider.ts
import * as vscode from 'vscode'
/**
 * CodelensProvider
 */
export class CodelensProvider implements vscode.CodeLensProvider {
	private codeLenses: vscode.CodeLens[] = []
	private _onDidChangeCodeLenses: vscode.EventEmitter<void> = new vscode.EventEmitter<void>()
	public readonly onDidChangeCodeLenses: vscode.Event<void> = this._onDidChangeCodeLenses.event
	constructor() {
		vscode.workspace.onDidChangeConfiguration((_) => {
			this._onDidChangeCodeLenses.fire()
		})
	}
	public provideCodeLenses(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.CodeLens[] | Thenable<vscode.CodeLens[]> {
		if (vscode.workspace.getConfiguration("codelens-sample").get("enableCodeLens", true)) {
			this.codeLenses = []
			let lastLine_isBlocBegin = false
			let lastLine_isBlockEnd = false
			let lastLine_isComment = false
			let lastLine_isOrLine = false
			for (let i = 0; i < document.lineCount; i++) {
				// 行のテキストから前後の空白を削除
				const line = document.lineAt(i)
				const trimedText = line.text.trimStart().trimEnd()
				// 行の状態に応じてCodeLensを追加（激しくいいかげんです）
				const isBlockBegin = trimedText.endsWith('{')
				const isBlockEnd = trimedText.endsWith('}')
				const isBlockCommentBegin = trimedText.startsWith('/*')
				const isBlockCommentEnd = trimedText.endsWith('*/')
				const isSingleLineComment = trimedText.startsWith('//')
				const isIfLine = trimedText.startsWith('if (')
				const isOrLine = trimedText.startsWith('||')
				const isCollectionElementLine = trimedText.endsWith(',')
				if (
					(isBlockBegin && !lastLine_isComment && !lastLine_isOrLine)
					|| (isSingleLineComment && !lastLine_isComment)
					|| (isIfLine && !lastLine_isComment)
					|| (isBlockCommentBegin)
					|| (lastLine_isBlocBegin && !isBlockBegin && !isBlockEnd && !isCollectionElementLine)
					|| (lastLine_isBlockEnd)
				) {
					this.codeLenses.push(new vscode.CodeLens(line.range))
				}
				lastLine_isBlocBegin = isBlockBegin
				lastLine_isBlockEnd = isBlockEnd
				lastLine_isComment = (isBlockCommentEnd || isSingleLineComment)
				lastLine_isOrLine = isOrLine
			}
			return this.codeLenses
		}
		return []
	}
	public resolveCodeLens(codeLens: vscode.CodeLens, token: vscode.CancellationToken) {
		if (vscode.workspace.getConfiguration("codelens-sample").get("enableCodeLens", true)) {
			codeLens.command = {
				title: "",
				tooltip: "Tooltip provided by sample extension",
				command: "codelens-sample.codelensAction",
				arguments: ["Argument 1", false]
			}
			return codeLens
		}
		return null
	}
}

```

空行が一行も無い、人間の温かみの感じられないコードですね。

最後に、NPMスクリプトの watch を実行します。これで準備完了です。

# 動かしてみる

F5等で拡張機能を実行します。

すると新しいVSCodeのウィンドウが開くので、先程の CodelensProvider.ts を開いてみましょう。

すると、こんな感じで表示されるはずです。

![スクリーンショット 2023-12-13 192824.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/75400386-9f48-695a-46ef-bf6a3d4afe36.png)

コード中の要所要所で行間に気持ちよく（人による）間隔がとられていますね！
微塵も思いやりの感じられなかった元のコードとは大違いです！

これで先輩に無駄な空行を入れないどころか一切空行の無いコードを叩きつけながら、自分は自分の好みの場所に空行（？）が入った状態で快適にコーディングできますね！絶対にしないでください！

# 何をしているのか

空行を入れたいところに空のコードレンズを入れて空行っぽくしています。

行ごとにマージンを設定する方法が見つからなくて…現状無いのかも。


  　

ちなみにコードレンズというのはコレです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/1421559d-437e-5776-93ed-d4ce7e8f98a0.png)
筆者は今回調べていて初めてコレの名称を知りました。

# おわりに

実際にこの拡張機能を使ってコーディングしてみると、手癖のせいで無駄な空行を入れまくってしまうので、めちゃくちゃ使いづらかったです。残念！