Chapter 07

Diagnostic Message

takl
takl
2020.12.22に更新

次は診断メッセージです。エラーとかを表示するやつですね。便利なので是非使いたいところです。

仕様はPublishDiagnostics Notificationにあります。

PublishDiagnostics は Server 側から Client 側に送るメッセージです。初期化時に Client が PublishDiagnostics に対応しているか調べなければなりません。調べる方法はまたInitialize Requestを読まなければならないのですが、要するに初期化メッセージの params.capabilities.textDocument.publishDiagnostics が真か調べればよいです。

というわけで初期化コードは次のようになります。

oreore.js
let publishDiagnosticsCapable = false;

requestTable["initialize"] = (msg) => {
    if (msg.params && msg.params.capabilities) {
        if (msg.params.capabilities.textDocument && msg.params.capabilities.textDocument.publishDiagnostics) {
            publishDiagnosticsCapable = true;
        }
    }

    const capabilities = {
        textDocumentSync: 1,
    };

    sendMessage({ jsonrpc: "2.0", id: msg.id, result: { capabilities } });
}

今回は compile 関数の中で問答無用に診断メッセージを表示させるようにしてみましょう。

oreore.js
function sendPublishDiagnostics(uri, diagnostics) {
    if (publishDiagnosticsCapable) {
        sendMessage({ jsonrpc: "2.0", method: "textDocument/publishDiagnostics", params: { uri, diagnostics } });
    }
}

function compile(uri, src) {
    const diagnostics = [
        {
            range:
            {
                start: { line: 0, character: 0 },
                end: { line: 0, character: 5 }
            },
            message: "diagnostic message 1"
        },
        {
            range:
            {
                start: { line: 1, character: 0 },
                end: { line: 1, character: 5 }
            },
            message: "diagnostic message 2"
        }
    ];
    sendPublishDiagnostics(uri, diagnostics)
    
    // TODO: implement
}

こんな感じで表示されます。

一度出した診断メッセージは Language Client が勝手に削除したりはしません。このような仕様になっている理由はPublishDiagnostics Notificationにありますが、要するに診断メッセージを消せるタイミングは言語毎に異なるからです。

今回は単純にファイルを閉じたときに削除することにしましょう。

oreore.js
notificationTable["textDocument/didClose"] = (msg) => {
    const uri = msg.params.textDocument.uri;
    sendPublishDiagnostics(uri, []);
}

* ここまでのソースコード *