arphaman created this revision.
arphaman added reviewers: jkorous, sammccall, ilya-biryukov.
arphaman added a project: clang-tools-extra.
Herald added subscribers: dexonsmith, MaskRay, ioeric.
This patch builds on top of the "extra flags" extension added in r307241.
It adds the ability to specify user-defined custom compilation command for an
opened file through the LSP layer. This is a non-standard extension to the
protocol.
The particular use-case is follows: our clients do not have a compilation
database and will specify all compilation commands dynamically when a file is
open.
Repository:
rCTE Clang Tools Extra
https://reviews.llvm.org/D49523
Files:
clangd/ClangdLSPServer.cpp
clangd/GlobalCompilationDatabase.cpp
clangd/GlobalCompilationDatabase.h
clangd/Protocol.cpp
clangd/Protocol.h
test/clangd/override-compile-command.test
Index: test/clangd/override-compile-command.test
===================================================================
--- /dev/null
+++ test/clangd/override-compile-command.test
@@ -0,0 +1,76 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","version":1,"text":"int main() { int i; return i; }"},"metadata":{"compilationCommand":["clang", "-c", "foo.c", "-Wall", "-Werror"]}}}
+# CHECK: "method": "textDocument/publishDiagnostics",
+# CHECK-NEXT: "params": {
+# CHECK-NEXT: "diagnostics": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "message": "variable 'i' is uninitialized when used here",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 28,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 27,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "severity": 1
+# CHECK-NEXT: }
+# CHECK-NEXT: ],
+# CHECK-NEXT: "uri": "file://{{.*}}/foo.c"
+# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///foo.c","version":2},"contentChanges":[{"text":"int main() { int i; return i; }"}]}}
+# CHECK: "method": "textDocument/publishDiagnostics",
+# CHECK-NEXT: "params": {
+# CHECK-NEXT: "diagnostics": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "message": "variable 'i' is uninitialized when used here",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 28,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 27,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "severity": 1
+# CHECK-NEXT: }
+# CHECK-NEXT: ],
+# CHECK-NEXT: "uri": "file://{{.*}}/foo.c"
+# CHECK-NEXT: }
+
+# extraFlags works together with compilationCommand!
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///bar.c","languageId":"c","version":1,"text":"int main() { int i; return i; }"},"metadata":{"compilationCommand":["clang", "-c", "bar.c", "-Wall", "-Werror"], "extraFlags":["-Wno-error=uninitialized"]}}}
+# CHECK: "method": "textDocument/publishDiagnostics",
+# CHECK-NEXT: "params": {
+# CHECK-NEXT: "diagnostics": [
+# CHECK-NEXT: {
+# CHECK-NEXT: "message": "variable 'i' is uninitialized when used here",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": 28,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": 27,
+# CHECK-NEXT: "line": 0
+# CHECK-NEXT: }
+# CHECK-NEXT: },
+# CHECK-NEXT: "severity": 2
+# CHECK-NEXT: }
+# CHECK-NEXT: ],
+# CHECK-NEXT: "uri": "file://{{.*}}/bar.c"
+# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","id":5,"method":"shutdown"}
+---
+{"jsonrpc":"2.0":"method":"exit"}
+
+
Index: clangd/Protocol.h
===================================================================
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -160,6 +160,7 @@
struct Metadata {
std::vector<std::string> extraFlags;
+ std::vector<std::string> compilationCommand;
};
bool fromJSON(const llvm::json::Value &, Metadata &);
Index: clangd/Protocol.cpp
===================================================================
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -122,6 +122,7 @@
if (!O)
return false;
O.map("extraFlags", R.extraFlags);
+ O.map("compilationCommand", R.compilationCommand);
return true;
}
Index: clangd/GlobalCompilationDatabase.h
===================================================================
--- clangd/GlobalCompilationDatabase.h
+++ clangd/GlobalCompilationDatabase.h
@@ -68,10 +68,16 @@
/// Sets the extra flags that should be added to a file.
void setExtraFlagsForFile(PathRef File, std::vector<std::string> ExtraFlags);
+ /// Overrides the compilation command for a particular file.
+ void overrideCompilationCommandForFile(
+ PathRef File, std::vector<std::string> CompilationCommand);
+
private:
tooling::CompilationDatabase *getCDBForFile(PathRef File) const;
tooling::CompilationDatabase *getCDBInDirLocked(PathRef File) const;
void addExtraFlags(PathRef File, tooling::CompileCommand &C) const;
+ llvm::Optional<tooling::CompileCommand>
+ getOverridenCompilationCommand(PathRef File) const;
mutable std::mutex Mutex;
/// Caches compilation databases loaded from directories(keys are
@@ -81,6 +87,8 @@
/// Stores extra flags per file.
llvm::StringMap<std::vector<std::string>> ExtraFlagsForFile;
+ /// Stores overriden compilation commands per file.
+ llvm::StringMap<std::vector<std::string>> OverridenCompilationCommands;
/// Used for command argument pointing to folder where compile_commands.json
/// is located.
llvm::Optional<Path> CompileCommandsDir;
Index: clangd/GlobalCompilationDatabase.cpp
===================================================================
--- clangd/GlobalCompilationDatabase.cpp
+++ clangd/GlobalCompilationDatabase.cpp
@@ -40,6 +40,10 @@
llvm::Optional<tooling::CompileCommand>
DirectoryBasedGlobalCompilationDatabase::getCompileCommand(PathRef File) const {
+ if (auto Command = getOverridenCompilationCommand(File)) {
+ addExtraFlags(File, *Command);
+ return std::move(*Command);
+ }
if (auto CDB = getCDBForFile(File)) {
auto Candidates = CDB->getCompileCommands(File);
if (!Candidates.empty()) {
@@ -87,6 +91,24 @@
Args.insert(Args.end() - 1, It->second.begin(), It->second.end());
}
+void DirectoryBasedGlobalCompilationDatabase::overrideCompilationCommandForFile(
+ PathRef File, std::vector<std::string> CompilationCommand) {
+ std::lock_guard<std::mutex> Lock(Mutex);
+ OverridenCompilationCommands[File] = std::move(CompilationCommand);
+}
+
+llvm::Optional<tooling::CompileCommand>
+DirectoryBasedGlobalCompilationDatabase::getOverridenCompilationCommand(
+ PathRef File) const {
+ std::lock_guard<std::mutex> Lock(Mutex);
+ auto It = OverridenCompilationCommands.find(File);
+ if (It == OverridenCompilationCommands.end())
+ return None;
+ return tooling::CompileCommand(llvm::sys::path::parent_path(File),
+ llvm::sys::path::filename(File), It->second,
+ /*Output=*/"");
+}
+
tooling::CompilationDatabase *
DirectoryBasedGlobalCompilationDatabase::getCDBInDirLocked(PathRef Dir) const {
// FIXME(ibiryukov): Invalidate cached compilation databases on changes
Index: clangd/ClangdLSPServer.cpp
===================================================================
--- clangd/ClangdLSPServer.cpp
+++ clangd/ClangdLSPServer.cpp
@@ -132,10 +132,17 @@
void ClangdLSPServer::onDocumentDidOpen(DidOpenTextDocumentParams &Params) {
PathRef File = Params.textDocument.uri.file();
- if (Params.metadata && !Params.metadata->extraFlags.empty()) {
- NonCachedCDB.setExtraFlagsForFile(File,
- std::move(Params.metadata->extraFlags));
- CDB.invalidate(File);
+ if (Params.metadata) {
+ if (!Params.metadata->extraFlags.empty()) {
+ NonCachedCDB.setExtraFlagsForFile(File,
+ std::move(Params.metadata->extraFlags));
+ CDB.invalidate(File);
+ }
+ if (!Params.metadata->compilationCommand.empty()) {
+ NonCachedCDB.overrideCompilationCommandForFile(
+ File, std::move(Params.metadata->compilationCommand));
+ CDB.invalidate(File);
+ }
}
std::string &Contents = Params.textDocument.text;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits