Skip to content

Commit 878c141

Browse files
[mlir-lsp] Add DiagnosticTag from LSP spec (llvm#91396)
Adds the [DiagnosticTag][diagtag] LSP construct to the LSP support headers. I also added a unit test file to validate that the `tags` array is omitted entirely if it's empty. The LSP spec requires that `Diagnostic::tags` be an array; in order to conform to that I used `std::vector`, as `SmallVector` doesn't have JSON decoding support (you can encode it to JSON, but not decode it from JSON). [diagtag]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#diagnosticTag
1 parent 7e35a9a commit 878c141

File tree

4 files changed

+83
-1
lines changed

4 files changed

+83
-1
lines changed

mlir/include/mlir/Tools/lsp-server-support/Protocol.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,16 @@ enum class DiagnosticSeverity {
677677
Hint = 4
678678
};
679679

680+
enum class DiagnosticTag {
681+
Unnecessary = 1,
682+
Deprecated = 2,
683+
};
684+
685+
/// Add support for JSON serialization.
686+
llvm::json::Value toJSON(DiagnosticTag tag);
687+
bool fromJSON(const llvm::json::Value &value, DiagnosticTag &result,
688+
llvm::json::Path path);
689+
680690
struct Diagnostic {
681691
/// The source range where the message applies.
682692
Range range;
@@ -696,6 +706,9 @@ struct Diagnostic {
696706
/// a scope collide all definitions can be marked via this property.
697707
std::optional<std::vector<DiagnosticRelatedInformation>> relatedInformation;
698708

709+
/// Additional metadata about the diagnostic.
710+
std::vector<DiagnosticTag> tags;
711+
699712
/// The diagnostic's category. Can be omitted.
700713
/// An LSP extension that's used to send the name of the category over to the
701714
/// client. The category typically describes the compilation stage during

mlir/lib/Tools/lsp-server-support/Protocol.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,20 @@ llvm::json::Value mlir::lsp::toJSON(const DiagnosticRelatedInformation &info) {
646646
// Diagnostic
647647
//===----------------------------------------------------------------------===//
648648

649+
llvm::json::Value mlir::lsp::toJSON(DiagnosticTag tag) {
650+
return static_cast<int>(tag);
651+
}
652+
653+
bool mlir::lsp::fromJSON(const llvm::json::Value &value, DiagnosticTag &result,
654+
llvm::json::Path path) {
655+
if (std::optional<int64_t> i = value.getAsInteger()) {
656+
result = (DiagnosticTag)*i;
657+
return true;
658+
}
659+
660+
return false;
661+
}
662+
649663
llvm::json::Value mlir::lsp::toJSON(const Diagnostic &diag) {
650664
llvm::json::Object result{
651665
{"range", diag.range},
@@ -658,6 +672,8 @@ llvm::json::Value mlir::lsp::toJSON(const Diagnostic &diag) {
658672
result["source"] = diag.source;
659673
if (diag.relatedInformation)
660674
result["relatedInformation"] = *diag.relatedInformation;
675+
if (!diag.tags.empty())
676+
result["tags"] = diag.tags;
661677
return std::move(result);
662678
}
663679

@@ -675,7 +691,8 @@ bool mlir::lsp::fromJSON(const llvm::json::Value &value, Diagnostic &result,
675691
mapOptOrNull(value, "category", result.category, path) &&
676692
mapOptOrNull(value, "source", result.source, path) &&
677693
mapOptOrNull(value, "relatedInformation", result.relatedInformation,
678-
path);
694+
path) &&
695+
mapOptOrNull(value, "tags", result.tags, path);
679696
}
680697

681698
//===----------------------------------------------------------------------===//

mlir/unittests/Tools/lsp-server-support/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
add_mlir_unittest(MLIRLspServerSupportTests
2+
Protocol.cpp
23
Transport.cpp
34
)
45
target_link_libraries(MLIRLspServerSupportTests
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//===- Protocol.cpp - LSP JSON protocol unit tests ------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "mlir/Tools/lsp-server-support/Protocol.h"
10+
11+
#include "gtest/gtest.h"
12+
13+
using namespace mlir;
14+
using namespace mlir::lsp;
15+
using namespace testing;
16+
17+
namespace {
18+
19+
TEST(ProtocolTest, DiagnosticTagPresent) {
20+
Diagnostic diagnostic;
21+
diagnostic.tags.push_back(DiagnosticTag::Unnecessary);
22+
23+
llvm::json::Value json = toJSON(diagnostic);
24+
const llvm::json::Object *o = json.getAsObject();
25+
const llvm::json::Array *v = o->get("tags")->getAsArray();
26+
EXPECT_EQ(*v, llvm::json::Array{1});
27+
28+
Diagnostic parsed;
29+
llvm::json::Path::Root root = llvm::json::Path::Root();
30+
bool success = fromJSON(json, parsed, llvm::json::Path(root));
31+
EXPECT_TRUE(success);
32+
ASSERT_EQ(parsed.tags.size(), (size_t)1);
33+
EXPECT_EQ(parsed.tags.at(0), DiagnosticTag::Unnecessary);
34+
}
35+
36+
TEST(ProtocolTest, DiagnosticTagNotPresent) {
37+
Diagnostic diagnostic;
38+
39+
llvm::json::Value json = toJSON(diagnostic);
40+
const llvm::json::Object *o = json.getAsObject();
41+
const llvm::json::Value *v = o->get("tags");
42+
EXPECT_EQ(v, nullptr);
43+
44+
Diagnostic parsed;
45+
llvm::json::Path::Root root = llvm::json::Path::Root();
46+
bool success = fromJSON(json, parsed, llvm::json::Path(root));
47+
EXPECT_TRUE(success);
48+
EXPECT_TRUE(parsed.tags.empty());
49+
}
50+
51+
} // namespace

0 commit comments

Comments
 (0)