diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -341,7 +341,8 @@ *NegotiatedOffsetEncoding); ClangdServerOpts.SemanticHighlighting = - Params.capabilities.SemanticHighlighting; + Params.capabilities.SemanticHighlighting | + Params.capabilities.ExperimentalSemanticHighlighting; if (Params.rootUri && *Params.rootUri) ClangdServerOpts.WorkspaceRoot = Params.rootUri->file(); else if (Params.rootPath && !Params.rootPath->empty()) @@ -423,11 +424,18 @@ }}}}; if (NegotiatedOffsetEncoding) Result["offsetEncoding"] = *NegotiatedOffsetEncoding; + llvm::json::Object TMScopes{{"scopes", buildHighlightScopeLookupTable()}}; + // Theia needs the text mate scopes in the normal capabilities object. if (Params.capabilities.SemanticHighlighting) Result.getObject("capabilities") - ->insert( - {"semanticHighlighting", - llvm::json::Object{{"scopes", buildHighlightScopeLookupTable()}}}); + ->insert({"semanticHighlighting", (llvm::json::Object)TMScopes}); + // The vscode language client can currently only get the text mate scopes via + // the experimental server capability. + if (Params.capabilities.ExperimentalSemanticHighlighting) + Result.getObject("capabilities") + ->insert({"experimental", + llvm::json::Object{ + {"semanticHighlighting", (llvm::json::Object)TMScopes}}}); Reply(std::move(Result)); } diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -416,6 +416,10 @@ /// textDocument.semanticHighlightingCapabilities.semanticHighlighting bool SemanticHighlighting = false; + /// Only used because there is no other way to pass the text mate scopes to + /// the vscode extension other than as experimental server capabilities. + bool ExperimentalSemanticHighlighting = false; + /// Supported encodings for LSP character offsets. (clangd extension). llvm::Optional> offsetEncoding; diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -272,6 +272,12 @@ const llvm::json::Object *O = Params.getAsObject(); if (!O) return false; + if (auto *Experimental = O->getObject("experimental")) + if (auto *SemanticHighlighting = + Experimental->getObject("semanticHighlightingCapabilities")) + if (auto SemanticHighlightingSupport = + SemanticHighlighting->getBoolean("semanticHighlighting")) + R.ExperimentalSemanticHighlighting = *SemanticHighlightingSupport; if (auto *TextDocument = O->getObject("textDocument")) { if (auto *SemanticHighlighting = TextDocument->getObject("semanticHighlightingCapabilities")) { diff --git a/clang-tools-extra/clangd/test/experimental-semantic-highlighting.test b/clang-tools-extra/clangd/test/experimental-semantic-highlighting.test new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clangd/test/experimental-semantic-highlighting.test @@ -0,0 +1,41 @@ +# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"experimental":{"semanticHighlightingCapabilities":{"semanticHighlighting":true}}},"trace":"off"}} +--- +# CHECK: "id": 0, +# CHECK: "experimental": { +# CHECK-NEXT: "semanticHighlighting": { +# CHECK-NEXT: "scopes": [ +# CHECK-NEXT: [ +# CHECK-NEXT: "variable.other.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "entity.name.function.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "entity.name.function.method.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "variable.other.field.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "entity.name.type.class.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "entity.name.type.enum.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "variable.other.enummember.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "entity.name.namespace.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "entity.name.type.template.cpp" +# CHECK-NEXT: ] +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: }, +--- +{"jsonrpc":"2.0","id":3,"method":"shutdown"} +--- +{"jsonrpc":"2.0","method":"exit"} diff --git a/clang-tools-extra/clangd/test/semantic-highlighting.test b/clang-tools-extra/clangd/test/semantic-highlighting.test --- a/clang-tools-extra/clangd/test/semantic-highlighting.test +++ b/clang-tools-extra/clangd/test/semantic-highlighting.test @@ -2,7 +2,7 @@ {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"textDocument":{"semanticHighlightingCapabilities":{"semanticHighlighting":true}}},"trace":"off"}} --- # CHECK: "id": 0, -# CHECK: "semanticHighlighting": { +# CHECK: "semanticHighlighting": { # CHECK-NEXT: "scopes": [ # CHECK-NEXT: [ # CHECK-NEXT: "variable.other.cpp"