## 経緯
同一ファイルを複数表示したり、[[🦉Another Quick Switcher]]のpreviewをしてから開くとLintの表示がおかしくなってしまう問題を調査していたところ、表題の件に行き着いた。
## 調査方法
`src/services/lint-service.ts` に `console.log` を仕込んで確認した。
```ts
/**
* ファイルをアクティブにしたときにLint(検査)をするサービスです
*/
export class LintService implements Service {
name = "Lint";
unsetFileOpenHandler!: () => void;
unsetExWCommandHandler!: () => void;
constructor(public settings: PluginSettings["linter"]) {}
onLayoutReady(): void {
// 起動直後、既にファイルが開かれている場合はファイルの中身を保存する (setOnCreateFileEvent では取得できないため)
const activeFile = getActiveFile();
if (activeFile) {
lintFile(activeFile, this.settings, false);
}
}
onload(): void {
this.unsetFileOpenHandler = setOnFileOpenEvent(async (file) => {
// ★ここが呼ばれていなかった
console.log(`[LintService] File opened: ${file?.path}`);
if (!file) {
return;
}
await lintFile(file, this.settings, false);
});
this.unsetExWCommandHandler = setOnExWCommandEvent(
(file) => lintFile(file, this.settings, true),
this.name,
);
}
onunload(): void {
this.unsetFileOpenHandler();
this.unsetExWCommandHandler();
removeLinterInspectionElements();
}
}
```
イベントの登録は `app.workspace.on("file-open")` である。
`src/lib/helpers/events.ts`
```ts
/**
* ファイルを開いたときに実行する処理を設定します
* handlerのfile引数は、タブグループのファイルが存在しない場合はnullになります
*
* @returns 処理の解除処理
*/
export function setOnFileOpenEvent(
handler: (file: TFile | null) => any,
ctx?: any,
): () => void {
const ref = app.workspace.on("file-open", handler, ctx);
return () => {
app.workspace.offref(ref);
};
}
```
## 解決方法
`active-leaf-change` のイベントを使う。
```ts
/**
* アクティブなLeafが変更されたときに実行する処理を設定します
*
* @returns 処理の解除処理
*/
export function setOnActiveLeafChangeEvent(
handler: (leaf: UWorkspaceLeaf | null) => any,
ctx?: any,
): () => void {
const ref = app.workspace.on(
"active-leaf-change",
handler as (leaf: WorkspaceLeaf | null) => any,
ctx,
);
return () => {
app.workspace.offref(ref);
};
}
```
```ts
onload(): void {
// INFO: setOnFileOpenEvent ではなく setOnActiveLeafChangeEvent を使うのは
// 同名ファイルを複数開いたときなどに対応するため
// WARNING: AQSでpreviewをしたあとに現在のタブ以外で開いた場合
// プレビュー前に表示されているファイルのLint diagnosticsが正しく表示されない問題がある
// (最後にプレビューしたdiagnosticsが表示される)
this.unsetActiveLeafChangeHandler = setOnActiveLeafChangeEvent(
async (leaf) => {
const file = leaf?.view.file;
if (!file) {
return;
}
await lintFile(file, this.settings, false);
},
this.name,
);
this.unsetExWCommandHandler = setOnExWCommandEvent(
(file) => lintFile(file, this.settings, true),
this.name,
);
}
```
### 制限事項
分割して開く場合に、以下の問題が残る。
- `WARNING` で記載されているコメント
- これの回避は厳しい
- [[🦉Another Quick Switcher]]のpreview機能コア実装に依存するので...
- 🏳️ これは諦める
- Lintが2度実行される
- auto fixが入らなければ大きな問題にはならないはず
- Lint時間が2倍かかるだけだが、無視できる
- 🙈 これは無視する
## コミット
https://github.com/tadashi-aikawa/carnelian/commit/699d23f2e26b5b0113540722963b1fa31c8ae32b