Index: clangd/ClangdLSPServer.cpp =================================================================== --- clangd/ClangdLSPServer.cpp +++ clangd/ClangdLSPServer.cpp @@ -506,6 +506,8 @@ } LSPDiag["clangd_fixes"] = std::move(ClangdFixes); } + if (!Diag.category.empty()) + LSPDiag["category"] = Diag.category; DiagnosticsJSON.push_back(std::move(LSPDiag)); auto &FixItsForDiagnostic = LocalFixIts[Diag]; Index: clangd/Diagnostics.h =================================================================== --- clangd/Diagnostics.h +++ clangd/Diagnostics.h @@ -37,6 +37,7 @@ std::string File; clangd::Range Range; DiagnosticsEngine::Level Severity = DiagnosticsEngine::Note; + std::string Category; // Since File is only descriptive, we store a separate flag to distinguish // diags from the main file. bool InsideMainFile = false; Index: clangd/Diagnostics.cpp =================================================================== --- clangd/Diagnostics.cpp +++ clangd/Diagnostics.cpp @@ -226,6 +226,7 @@ clangd::Diagnostic Res; Res.range = D.Range; Res.severity = getSeverity(D.Severity); + Res.category = D.Category; return Res; }; @@ -292,6 +293,9 @@ D.InsideMainFile = InsideMainFile; D.File = Info.getSourceManager().getFilename(Info.getLocation()); D.Severity = DiagLevel; + D.Category = DiagnosticIDs::getCategoryNameFromID( + DiagnosticIDs::getCategoryNumberForDiag(Info.getID())) + .str(); return D; }; Index: clangd/Protocol.h =================================================================== --- clangd/Protocol.h +++ clangd/Protocol.h @@ -544,6 +544,12 @@ /// The diagnostic's message. std::string message; + + /// The diagnostic's category. Can be omitted. + /// An LSP extension that's used to send the name of the category over to the + /// client. The category typically describes the compilation stage during + /// which the issue was produced, e.g. "Semantic Issue" or "Parse Issue". + std::string category; }; /// A LSP-specific comparator used to find diagnostic in a container like Index: test/clangd/compile-commands-path-in-initialize.test =================================================================== --- test/clangd/compile-commands-path-in-initialize.test +++ test/clangd/compile-commands-path-in-initialize.test @@ -23,6 +23,7 @@ # CHECK-NEXT: "params": { # CHECK-NEXT: "diagnostics": [ # CHECK-NEXT: { +# CHECK-NEXT: "category": "#pragma message Directive", # CHECK-NEXT: "message": "MACRO is one", --- {"jsonrpc":"2.0","id":0,"method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabasePath":"INPUT_DIR/build-2"}}} @@ -30,6 +31,7 @@ # CHECK-NEXT: "params": { # CHECK-NEXT: "diagnostics": [ # CHECK-NEXT: { +# CHECK-NEXT: "category": "#pragma message Directive", # CHECK-NEXT: "message": "MACRO is two", --- {"jsonrpc":"2.0","id":10000,"method":"shutdown"} Index: test/clangd/compile-commands-path.test =================================================================== --- test/clangd/compile-commands-path.test +++ test/clangd/compile-commands-path.test @@ -23,6 +23,7 @@ # CHECK-NEXT: "params": { # CHECK-NEXT: "diagnostics": [ # CHECK-NEXT: { +# CHECK-NEXT: "category": "#pragma message Directive", # CHECK-NEXT: "message": "MACRO is not defined", --- {"jsonrpc":"2.0","id":0,"method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabasePath":"INPUT_DIR/build-1"}}} @@ -30,6 +31,7 @@ # CHECK-NEXT: "params": { # CHECK-NEXT: "diagnostics": [ # CHECK-NEXT: { +# CHECK-NEXT: "category": "#pragma message Directive", # CHECK-NEXT: "message": "MACRO is one", --- {"jsonrpc":"2.0","id":0,"method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabasePath":"INPUT_DIR/build-2"}}} @@ -37,6 +39,7 @@ # CHECK-NEXT: "params": { # CHECK-NEXT: "diagnostics": [ # CHECK-NEXT: { +# CHECK-NEXT: "category": "#pragma message Directive", # CHECK-NEXT: "message": "MACRO is two", --- {"jsonrpc":"2.0","id":10000,"method":"shutdown"} Index: test/clangd/diagnostics.test =================================================================== --- test/clangd/diagnostics.test +++ test/clangd/diagnostics.test @@ -6,6 +6,7 @@ # CHECK-NEXT: "params": { # CHECK-NEXT: "diagnostics": [ # CHECK-NEXT: { +# CHECK-NEXT: "category": "Semantic Issue", # CHECK-NEXT: "message": "Return type of 'main' is not 'int'", # CHECK-NEXT: "range": { # CHECK-NEXT: "end": { Index: test/clangd/did-change-configuration-params.test =================================================================== --- test/clangd/did-change-configuration-params.test +++ test/clangd/did-change-configuration-params.test @@ -24,6 +24,7 @@ # CHECK-NEXT: "params": { # CHECK-NEXT: "diagnostics": [ # CHECK-NEXT: { +# CHECK-NEXT: "category": "Semantic Issue", # CHECK-NEXT: "message": "Variable 'i' is uninitialized when used here", # CHECK-NEXT: "range": { # CHECK-NEXT: "end": { Index: test/clangd/execute-command.test =================================================================== --- test/clangd/execute-command.test +++ test/clangd/execute-command.test @@ -6,6 +6,7 @@ # CHECK-NEXT: "params": { # CHECK-NEXT: "diagnostics": [ # CHECK-NEXT: { +# CHECK-NEXT: "category": "Semantic Issue", # CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses", # CHECK-NEXT: "range": { # CHECK-NEXT: "end": { Index: test/clangd/extra-flags.test =================================================================== --- test/clangd/extra-flags.test +++ test/clangd/extra-flags.test @@ -6,6 +6,7 @@ # CHECK-NEXT: "params": { # CHECK-NEXT: "diagnostics": [ # CHECK-NEXT: { +# CHECK-NEXT: "category": "Semantic Issue", # CHECK-NEXT: "message": "Variable 'i' is uninitialized when used here", # CHECK-NEXT: "range": { # CHECK-NEXT: "end": { @@ -28,6 +29,7 @@ # CHECK-NEXT: "params": { # CHECK-NEXT: "diagnostics": [ # CHECK-NEXT: { +# CHECK-NEXT: "category": "Semantic Issue", # CHECK-NEXT: "message": "Variable 'i' is uninitialized when used here", # CHECK-NEXT: "range": { # CHECK-NEXT: "end": { Index: test/clangd/fixits.test =================================================================== --- test/clangd/fixits.test +++ test/clangd/fixits.test @@ -6,6 +6,7 @@ # CHECK-NEXT: "params": { # CHECK-NEXT: "diagnostics": [ # CHECK-NEXT: { +# CHECK-NEXT: "category": "Semantic Issue", # CHECK-NEXT: "message": "Using the result of an assignment as a condition without parentheses", # CHECK-NEXT: "range": { # CHECK-NEXT: "end": {