Commit 34217cf8 authored by Mark Nauwelaerts's avatar Mark Nauwelaerts

lspclient: add server support for diagnostics notification

parent 1577295c
......@@ -28,6 +28,11 @@
#include <KTextEditor/Cursor>
#include <KTextEditor/Range>
// Following types roughly follow the types/interfaces as defined in LSP protocol spec
// although some deviation may arise where it has been deemed useful
// Moreover, to avoid introducing a custom 'optional' type, absence of an optional
// part/member is usually signalled by some 'invalid' marker (empty, negative).
enum class LSPErrorCode
{
// Defined by JSON RPC
......@@ -227,4 +232,36 @@ struct LSPSignatureHelp
int activeParameter;
};
enum class LSPDiagnosticSeverity
{
Unknown = 0,
Error = 1,
Warning = 2,
Information = 3,
Hint = 4,
};
struct LSPDiagnosticRelatedInformation
{
// empty url / invalid range when absent
LSPLocation location;
QString message;
};
struct LSPDiagnostics
{
LSPRange range;
LSPDiagnosticSeverity severity;
QString code;
QString source;
QString message;
LSPDiagnosticRelatedInformation relatedInformation;
};
struct LSPPublishDiagnosticsParams
{
QUrl uri;
QList<LSPDiagnostics> diagnostics;
};
#endif
......@@ -156,6 +156,10 @@ from_json(LSPServerCapabilities & caps, const QJsonObject & json)
caps.documentHighlightProvider = json.value(QStringLiteral("documentHighlightProvider")).toBool();
}
// TODO move all parsing here
static LSPPublishDiagnosticsParams
parseDiagnostics(const QJsonObject & result);
using GenericReplyType = QJsonValue;
using GenericReplyHandler = ReplyHandler<GenericReplyType>;
......@@ -333,9 +337,7 @@ private:
if (result.contains(MEMBER_ID)) {
msgid = result[MEMBER_ID].toInt();
} else {
// notification; never mind those for now
qCWarning(LSPCLIENT) << "discarding notification"
<< msg[MEMBER_METHOD].toString();
processNotification(result);
continue;
}
// could be request
......@@ -419,7 +421,10 @@ private:
{ QStringLiteral("textDocument"),
QJsonObject {
{ QStringLiteral("documentSymbol"),
QJsonObject { { QStringLiteral("hierarchicalDocumentSymbolSupport"), true } }
QJsonObject { { QStringLiteral("hierarchicalDocumentSymbolSupport"), true } },
},
{ QStringLiteral("publishDiagnostics"),
QJsonObject { { QStringLiteral("relatedInformation"), true } }
}
}
}
......@@ -562,6 +567,16 @@ public:
auto params = textDocumentParams(document);
send(init_request(QStringLiteral("textDocument/didClose"), params));
}
void processNotification(const QJsonObject & msg)
{
auto method = msg[MEMBER_METHOD].toString();
if (method == QStringLiteral("textDocument/publishDiagnostics")) {
emit q->publishDiagnostics(parseDiagnostics(msg[MEMBER_PARAMS].toObject()));
} else {
qCWarning(LSPCLIENT) << "discarding notification" << method;
}
}
};
// follow suit; as performed in kate docmanager
......@@ -818,6 +833,27 @@ parseSignatureHelp(const QJsonValue & result)
return ret;
}
static LSPPublishDiagnosticsParams
parseDiagnostics(const QJsonObject & result)
{
LSPPublishDiagnosticsParams ret;
ret.uri = normalizeUrl(QUrl(result.value(MEMBER_URI).toString()));
for (const auto & vdiag : result.value(QStringLiteral("diagnostics")).toArray()) {
auto diag = vdiag.toObject();
auto range = parseRange(diag.value(MEMBER_RANGE).toObject());
auto severity = (LSPDiagnosticSeverity) diag.value(QStringLiteral("severity")).toInt();
auto code = diag.value(QStringLiteral("code")).toString();
auto source = diag.value(QStringLiteral("source")).toString();
auto message = diag.value(MEMBER_MESSAGE).toString();
auto related = diag.value(QStringLiteral("relatedInformation")).toObject();
auto relLocation = parseLocation(related.value(MEMBER_LOCATION).toObject());
auto relMessage = related.value(MEMBER_MESSAGE).toString();
ret.diagnostics.push_back({range, severity, code, source, message, relLocation, relMessage});
}
return ret;
}
// generic convert handler
// sprinkle some connection-like context safety
// not so likely relevant/needed due to typical sequence of events,
......
......@@ -144,6 +144,10 @@ public:
void didSave(const QUrl & document, const QString & text);
void didClose(const QUrl & document);
// notifcation = signal
Q_SIGNALS:
void publishDiagnostics(const LSPPublishDiagnosticsParams & );
private:
// pimpl data holder
LSPClientServerPrivate * const d;
......
......@@ -46,6 +46,12 @@ int main(int argc, char ** argv)
q.exec();
QObject::disconnect(conn);
auto diagnostics_h = [] (const LSPPublishDiagnosticsParams & diag) {
std::cout << "diagnostics " << diag.uri.path().toUtf8().toStdString() << " count: " << diag.diagnostics.length();
};
QObject::connect(&lsp, &LSPClientServer::publishDiagnostics, diagnostics_h);
auto document = QUrl(QString::fromLatin1(argv[3]));
QFile file(document.path());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment