## 経緯 同一ファイルを複数表示したり、[[🦉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