[PATCH] D36150: [clangd] LSP extension to switch between source/header file
Nebiroth added a comment. In https://reviews.llvm.org/D36150#879194, @ilya-biryukov wrote: > Looks good. > Do you want me to submit this patch for you? Yes please. https://reviews.llvm.org/D36150 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D37150: [clangd] Command line arg to specify compile_commands.json path
Nebiroth updated this revision to Diff 116559. Nebiroth added a comment. Fixed inverted compile_commands check logic that made tests fail. More readable command arg checks. https://reviews.llvm.org/D37150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/tool/ClangdMain.cpp Index: clangd/tool/ClangdMain.cpp === --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -11,16 +11,23 @@ #include "JSONRPCDispatcher.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Program.h" - #include #include #include #include +#include using namespace clang; using namespace clang::clangd; +static llvm::cl::opt CompileCommandsDir( +"compile-commands-dir", +llvm::cl::desc("Specify a path to look for compile_commands.json. If path " + "is invalid, clangd will look in the current directory and " + "parent paths of each source file.")); + static llvm::cl::opt WorkerThreadsCount("j", llvm::cl::desc("Number of async workers used by clangd"), @@ -56,18 +63,40 @@ if (RunSynchronously) WorkerThreadsCount = 0; + /// Validate command line arguments. llvm::raw_ostream &Outs = llvm::outs(); llvm::raw_ostream &Logs = llvm::errs(); JSONOutput Out(Outs, Logs); - // Change stdin to binary to not lose \r\n on windows. - llvm::sys::ChangeStdinToBinary(); + // If --compile-commands-dir arg was invoked, check value and override default + // path. + namespace path = llvm::sys::path; + llvm::Optional CompileCommandsDirPath; + + if (CompileCommandsDir.empty()) +CompileCommandsDirPath = llvm::None; + else if (!llvm::sys::path::is_absolute(CompileCommandsDir)) { +llvm::errs() +<< "Path specified by --compile-commands-dir must be an absolute " + "path. The argument will be ignored.\n"; +CompileCommandsDirPath = llvm::None; + } else if (!llvm::sys::fs::exists(CompileCommandsDir)) { +llvm::errs() << "Path specified by --compile-commands-dir does not exist. " +"The argument will be " +"ignored.\n"; +CompileCommandsDirPath = llvm::None; + } else +CompileCommandsDirPath = CompileCommandsDir; llvm::Optional ResourceDirRef = None; if (!ResourceDir.empty()) ResourceDirRef = ResourceDir; + /// Change stdin to binary to not lose \r\n on windows. + llvm::sys::ChangeStdinToBinary(); + + /// Initialize and run ClangdLSPServer. ClangdLSPServer LSPServer(Out, WorkerThreadsCount, EnableSnippets, -ResourceDirRef); +ResourceDirRef, CompileCommandsDirPath); LSPServer.run(std::cin); } Index: clangd/GlobalCompilationDatabase.h === --- clangd/GlobalCompilationDatabase.h +++ clangd/GlobalCompilationDatabase.h @@ -47,15 +47,17 @@ class DirectoryBasedGlobalCompilationDatabase : public GlobalCompilationDatabase { public: - DirectoryBasedGlobalCompilationDatabase(clangd::Logger &Logger); + DirectoryBasedGlobalCompilationDatabase( + clangd::Logger &Logger, llvm::Optional NewCompileCommandsDir); std::vector getCompileCommands(PathRef File) override; void setExtraFlagsForFile(PathRef File, std::vector ExtraFlags); private: tooling::CompilationDatabase *getCompilationDatabase(PathRef File); + tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File); std::mutex Mutex; /// Caches compilation databases loaded from directories(keys are @@ -67,6 +69,9 @@ llvm::StringMap> ExtraFlagsForFile; /// Used for logging. clangd::Logger &Logger; + /// Used for command argument pointing to folder where compile_commands.json + /// is located. + llvm::Optional CompileCommandsDir; }; } // namespace clangd } // namespace clang Index: clangd/GlobalCompilationDatabase.cpp === --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -38,8 +38,9 @@ } DirectoryBasedGlobalCompilationDatabase:: -DirectoryBasedGlobalCompilationDatabase(clangd::Logger &Logger) -: Logger(Logger) {} +DirectoryBasedGlobalCompilationDatabase( +clangd::Logger &Logger, llvm::Optional NewCompileCommandsDir) +: Logger(Logger), CompileCommandsDir(NewCompileCommandsDir) {} std::vector DirectoryBasedGlobalCompilationDatabase::getCompileCommands(PathRef File) { @@ -67,34 +68,48 @@ } tooling::CompilationDatabase * -DirectoryBasedGlobalCompilationDatabase::getCompilationDatabase(PathRef File) { - std::lock_guard Lock(Mutex); +DirectoryBasedGlobalCompilationDatabase::tryLoadDatabaseFromPath(PathRef File) { namespace path = llvm::sys::path; + aut
[PATCH] D37150: [clangd] Command line arg to specify compile_commands.json path
Nebiroth added inline comments. Comment at: clangd/tool/ClangdMain.cpp:20 #include +#include malaperle wrote: > William, did you perhaps miss this comment? I don't think unistd.h makes > sense here. I indeed missed it. https://reviews.llvm.org/D37150 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth created this revision. Implementation of Document Highlights Request as described in LSP. https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,29 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 455 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"range": {"start": {"line": 16, "character": 4}, "end": {"line": 16, "character": 12}}, "number": 1},{"range": {"start": {"line": 17, "character": 0}, "end": {"line": 17, "character": 7}}, "number": 1}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"range": {"start": {"line": 12, "character": 4}, "end": {"line": 12, "character": 9}}, "number": 1},{"range": {"start": {"line": 18, "character": 17}, "end": {"line": 18, "character": 21}}, "number": 1},{"range": {"start": {"line": 19, "character": 4}, "end": {"line": 19, "character": 8}}, "number": 1}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"range": {"start": {"line": 4, "character": 5}, "end": {"line": 4, "character": 22}}, "number": 1},{"range": {"start": {"line": 21, "character": 8}, "end": {"line": 21, "character": 25}}, "number": 1}]} + Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -47,7 +47,9 @@ virtual void onCompletion(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, -JSONOutput &Out) = 0; +JSONOutput &Out) = 0; + virtual void onDocumentHighlight(TextDocumentPositionParams Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,24 @@ ProtocolCallbacks &Callbacks; }; +struct DocumentHighlightHandler : Handler { + DocumentHighlightHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentPositionParams::parse(Params, Output); +if (!TDPP) { + Output.log("Failed to decode TextDocumentPositionParams!\n"); + return; +} + +Callbacks.onDocumentHighlight(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -240,4 +258,7 @@ Dispatcher.registerHandler( "textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/documentHighlight", + llvm::make_unique(Out, Callbacks)); } Index: clangd/Protocol.h === --- clangd/Protocol.h +++ clangd/Protocol.h @@ -416,6 +416,41 @@ static std::string unparse(const CompletionItem &P); }; +enum class DocumentHighlightKind { + Text = 1, + Read = 2, + Write = 3 +}; + +/** + * A document highlight is
[PATCH] D37150: [clangd] Command line arg to specify compile_commands.json path
Nebiroth updated this revision to Diff 117217. Nebiroth added a comment. Fixed missed comments and suggstions. https://reviews.llvm.org/D37150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/tool/ClangdMain.cpp Index: clangd/tool/ClangdMain.cpp === --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -11,16 +11,22 @@ #include "JSONRPCDispatcher.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Program.h" - #include #include #include #include using namespace clang; using namespace clang::clangd; +static llvm::cl::opt CompileCommandsDir( +"compile-commands-dir", +llvm::cl::desc("Specify a path to look for compile_commands.json. If path " + "is invalid, clangd will look in the current directory and " + "parent paths of each source file.")); + static llvm::cl::opt WorkerThreadsCount("j", llvm::cl::desc("Number of async workers used by clangd"), @@ -56,18 +62,37 @@ if (RunSynchronously) WorkerThreadsCount = 0; + /// Validate command line arguments. llvm::raw_ostream &Outs = llvm::outs(); llvm::raw_ostream &Logs = llvm::errs(); JSONOutput Out(Outs, Logs); - // Change stdin to binary to not lose \r\n on windows. - llvm::sys::ChangeStdinToBinary(); + // If --compile-commands-dir arg was invoked, check value and override default + // path. + namespace path = llvm::sys::path; + llvm::Optional CompileCommandsDirPath; + + if (CompileCommandsDir.empty()) { +CompileCommandsDirPath = llvm::None; + } else if (!llvm::sys::path::is_absolute(CompileCommandsDir) || + !llvm::sys::fs::exists(CompileCommandsDir)) { +llvm::errs() << "Path specified by --compile-commands-dir either does not " +"exist or is not an absolute " +"path. The argument will be ignored.\n"; +CompileCommandsDirPath = llvm::None; + } else { +CompileCommandsDirPath = CompileCommandsDir; + } llvm::Optional ResourceDirRef = None; if (!ResourceDir.empty()) ResourceDirRef = ResourceDir; + /// Change stdin to binary to not lose \r\n on windows. + llvm::sys::ChangeStdinToBinary(); + + /// Initialize and run ClangdLSPServer. ClangdLSPServer LSPServer(Out, WorkerThreadsCount, EnableSnippets, -ResourceDirRef); +ResourceDirRef, CompileCommandsDirPath); LSPServer.run(std::cin); } Index: clangd/GlobalCompilationDatabase.h === --- clangd/GlobalCompilationDatabase.h +++ clangd/GlobalCompilationDatabase.h @@ -47,15 +47,17 @@ class DirectoryBasedGlobalCompilationDatabase : public GlobalCompilationDatabase { public: - DirectoryBasedGlobalCompilationDatabase(clangd::Logger &Logger); + DirectoryBasedGlobalCompilationDatabase( + clangd::Logger &Logger, llvm::Optional NewCompileCommandsDir); std::vector getCompileCommands(PathRef File) override; void setExtraFlagsForFile(PathRef File, std::vector ExtraFlags); private: tooling::CompilationDatabase *getCompilationDatabase(PathRef File); + tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File); std::mutex Mutex; /// Caches compilation databases loaded from directories(keys are @@ -67,6 +69,9 @@ llvm::StringMap> ExtraFlagsForFile; /// Used for logging. clangd::Logger &Logger; + /// Used for command argument pointing to folder where compile_commands.json + /// is located. + llvm::Optional CompileCommandsDir; }; } // namespace clangd } // namespace clang Index: clangd/GlobalCompilationDatabase.cpp === --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -8,10 +8,10 @@ //===-===// #include "GlobalCompilationDatabase.h" +#include "Logger.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" -#include "Logger.h" namespace clang { namespace clangd { @@ -38,8 +38,9 @@ } DirectoryBasedGlobalCompilationDatabase:: -DirectoryBasedGlobalCompilationDatabase(clangd::Logger &Logger) -: Logger(Logger) {} +DirectoryBasedGlobalCompilationDatabase( +clangd::Logger &Logger, llvm::Optional NewCompileCommandsDir) +: Logger(Logger), CompileCommandsDir(NewCompileCommandsDir) {} std::vector DirectoryBasedGlobalCompilationDatabase::getCompileCommands(PathRef File) { @@ -67,34 +68,48 @@ } tooling::CompilationDatabase * -DirectoryBasedGlobalCompilationDatabase::getCompilationDatabase(PathRef File) { - std::lock_guard Lock(Mutex); +D
[PATCH] D37150: [clangd] Command line arg to specify compile_commands.json path
Nebiroth updated this revision to Diff 117327. Nebiroth added a comment. Fixed changes that were lost while merging with head. https://reviews.llvm.org/D37150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/tool/ClangdMain.cpp Index: clangd/tool/ClangdMain.cpp === --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -11,16 +11,22 @@ #include "JSONRPCDispatcher.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Program.h" - #include #include #include #include using namespace clang; using namespace clang::clangd; +static llvm::cl::opt CompileCommandsDir( +"compile-commands-dir", +llvm::cl::desc("Specify a path to look for compile_commands.json. If path " + "is invalid, clangd will look in the current directory and " + "parent paths of each source file.")); + static llvm::cl::opt WorkerThreadsCount("j", llvm::cl::desc("Number of async workers used by clangd"), @@ -56,18 +62,37 @@ if (RunSynchronously) WorkerThreadsCount = 0; + /// Validate command line arguments. llvm::raw_ostream &Outs = llvm::outs(); llvm::raw_ostream &Logs = llvm::errs(); JSONOutput Out(Outs, Logs); - // Change stdin to binary to not lose \r\n on windows. - llvm::sys::ChangeStdinToBinary(); + // If --compile-commands-dir arg was invoked, check value and override default + // path. + namespace path = llvm::sys::path; + llvm::Optional CompileCommandsDirPath; + + if (CompileCommandsDir.empty()) { +CompileCommandsDirPath = llvm::None; + } else if (!llvm::sys::path::is_absolute(CompileCommandsDir) || + !llvm::sys::fs::exists(CompileCommandsDir)) { +llvm::errs() << "Path specified by --compile-commands-dir either does not " +"exist or is not an absolute " +"path. The argument will be ignored.\n"; +CompileCommandsDirPath = llvm::None; + } else { +CompileCommandsDirPath = CompileCommandsDir; + } llvm::Optional ResourceDirRef = None; if (!ResourceDir.empty()) ResourceDirRef = ResourceDir; + /// Change stdin to binary to not lose \r\n on windows. + llvm::sys::ChangeStdinToBinary(); + + /// Initialize and run ClangdLSPServer. ClangdLSPServer LSPServer(Out, WorkerThreadsCount, EnableSnippets, -ResourceDirRef); +ResourceDirRef, CompileCommandsDirPath); LSPServer.run(std::cin); } Index: clangd/GlobalCompilationDatabase.h === --- clangd/GlobalCompilationDatabase.h +++ clangd/GlobalCompilationDatabase.h @@ -47,15 +47,17 @@ class DirectoryBasedGlobalCompilationDatabase : public GlobalCompilationDatabase { public: - DirectoryBasedGlobalCompilationDatabase(clangd::Logger &Logger); + DirectoryBasedGlobalCompilationDatabase( + clangd::Logger &Logger, llvm::Optional NewCompileCommandsDir); std::vector getCompileCommands(PathRef File) override; void setExtraFlagsForFile(PathRef File, std::vector ExtraFlags); private: tooling::CompilationDatabase *getCompilationDatabase(PathRef File); + tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File); std::mutex Mutex; /// Caches compilation databases loaded from directories(keys are @@ -67,6 +69,9 @@ llvm::StringMap> ExtraFlagsForFile; /// Used for logging. clangd::Logger &Logger; + /// Used for command argument pointing to folder where compile_commands.json + /// is located. + llvm::Optional CompileCommandsDir; }; } // namespace clangd } // namespace clang Index: clangd/GlobalCompilationDatabase.cpp === --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -8,10 +8,10 @@ //===-===// #include "GlobalCompilationDatabase.h" +#include "Logger.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" -#include "Logger.h" namespace clang { namespace clangd { @@ -38,8 +38,9 @@ } DirectoryBasedGlobalCompilationDatabase:: -DirectoryBasedGlobalCompilationDatabase(clangd::Logger &Logger) -: Logger(Logger) {} +DirectoryBasedGlobalCompilationDatabase( +clangd::Logger &Logger, llvm::Optional NewCompileCommandsDir) +: Logger(Logger), CompileCommandsDir(NewCompileCommandsDir) {} std::vector DirectoryBasedGlobalCompilationDatabase::getCompileCommands(PathRef File) { @@ -67,34 +68,46 @@ } tooling::CompilationDatabase * -DirectoryBasedGlobalCompilationDatabase::getCompilationDatabase(PathRef File) { - std::lock_guard
[PATCH] D37150: [clangd] Command line arg to specify compile_commands.json path
Nebiroth updated this revision to Diff 117337. Nebiroth marked 2 inline comments as done. Nebiroth added a comment. Changed placement of logging instruction to reduce logging output. https://reviews.llvm.org/D37150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/tool/ClangdMain.cpp Index: clangd/tool/ClangdMain.cpp === --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -11,16 +11,22 @@ #include "JSONRPCDispatcher.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Program.h" - #include #include #include #include using namespace clang; using namespace clang::clangd; +static llvm::cl::opt CompileCommandsDir( +"compile-commands-dir", +llvm::cl::desc("Specify a path to look for compile_commands.json. If path " + "is invalid, clangd will look in the current directory and " + "parent paths of each source file.")); + static llvm::cl::opt WorkerThreadsCount("j", llvm::cl::desc("Number of async workers used by clangd"), @@ -56,18 +62,37 @@ if (RunSynchronously) WorkerThreadsCount = 0; + /// Validate command line arguments. llvm::raw_ostream &Outs = llvm::outs(); llvm::raw_ostream &Logs = llvm::errs(); JSONOutput Out(Outs, Logs); - // Change stdin to binary to not lose \r\n on windows. - llvm::sys::ChangeStdinToBinary(); + // If --compile-commands-dir arg was invoked, check value and override default + // path. + namespace path = llvm::sys::path; + llvm::Optional CompileCommandsDirPath; + + if (CompileCommandsDir.empty()) { +CompileCommandsDirPath = llvm::None; + } else if (!llvm::sys::path::is_absolute(CompileCommandsDir) || + !llvm::sys::fs::exists(CompileCommandsDir)) { +llvm::errs() << "Path specified by --compile-commands-dir either does not " +"exist or is not an absolute " +"path. The argument will be ignored.\n"; +CompileCommandsDirPath = llvm::None; + } else { +CompileCommandsDirPath = CompileCommandsDir; + } llvm::Optional ResourceDirRef = None; if (!ResourceDir.empty()) ResourceDirRef = ResourceDir; + /// Change stdin to binary to not lose \r\n on windows. + llvm::sys::ChangeStdinToBinary(); + + /// Initialize and run ClangdLSPServer. ClangdLSPServer LSPServer(Out, WorkerThreadsCount, EnableSnippets, -ResourceDirRef); +ResourceDirRef, CompileCommandsDirPath); LSPServer.run(std::cin); } Index: clangd/GlobalCompilationDatabase.h === --- clangd/GlobalCompilationDatabase.h +++ clangd/GlobalCompilationDatabase.h @@ -47,15 +47,17 @@ class DirectoryBasedGlobalCompilationDatabase : public GlobalCompilationDatabase { public: - DirectoryBasedGlobalCompilationDatabase(clangd::Logger &Logger); + DirectoryBasedGlobalCompilationDatabase( + clangd::Logger &Logger, llvm::Optional NewCompileCommandsDir); std::vector getCompileCommands(PathRef File) override; void setExtraFlagsForFile(PathRef File, std::vector ExtraFlags); private: tooling::CompilationDatabase *getCompilationDatabase(PathRef File); + tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File); std::mutex Mutex; /// Caches compilation databases loaded from directories(keys are @@ -67,6 +69,9 @@ llvm::StringMap> ExtraFlagsForFile; /// Used for logging. clangd::Logger &Logger; + /// Used for command argument pointing to folder where compile_commands.json + /// is located. + llvm::Optional CompileCommandsDir; }; } // namespace clangd } // namespace clang Index: clangd/GlobalCompilationDatabase.cpp === --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -8,10 +8,10 @@ //===-===// #include "GlobalCompilationDatabase.h" +#include "Logger.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" -#include "Logger.h" namespace clang { namespace clangd { @@ -38,8 +38,9 @@ } DirectoryBasedGlobalCompilationDatabase:: -DirectoryBasedGlobalCompilationDatabase(clangd::Logger &Logger) -: Logger(Logger) {} +DirectoryBasedGlobalCompilationDatabase( +clangd::Logger &Logger, llvm::Optional NewCompileCommandsDir) +: Logger(Logger), CompileCommandsDir(NewCompileCommandsDir) {} std::vector DirectoryBasedGlobalCompilationDatabase::getCompileCommands(PathRef File) { @@ -67,31 +68,49 @@ } tooling::CompilationDatabase * -DirectoryBasedGlobalCompilationDatabase::g
[PATCH] D37150: [clangd] Command line arg to specify compile_commands.json path
Nebiroth updated this revision to Diff 117340. Nebiroth added a comment. Improved logging message when unable to find compilation database in specified overriden directory. https://reviews.llvm.org/D37150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/tool/ClangdMain.cpp Index: clangd/tool/ClangdMain.cpp === --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -11,16 +11,22 @@ #include "JSONRPCDispatcher.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Program.h" - #include #include #include #include using namespace clang; using namespace clang::clangd; +static llvm::cl::opt CompileCommandsDir( +"compile-commands-dir", +llvm::cl::desc("Specify a path to look for compile_commands.json. If path " + "is invalid, clangd will look in the current directory and " + "parent paths of each source file.")); + static llvm::cl::opt WorkerThreadsCount("j", llvm::cl::desc("Number of async workers used by clangd"), @@ -56,18 +62,37 @@ if (RunSynchronously) WorkerThreadsCount = 0; + /// Validate command line arguments. llvm::raw_ostream &Outs = llvm::outs(); llvm::raw_ostream &Logs = llvm::errs(); JSONOutput Out(Outs, Logs); - // Change stdin to binary to not lose \r\n on windows. - llvm::sys::ChangeStdinToBinary(); + // If --compile-commands-dir arg was invoked, check value and override default + // path. + namespace path = llvm::sys::path; + llvm::Optional CompileCommandsDirPath; + + if (CompileCommandsDir.empty()) { +CompileCommandsDirPath = llvm::None; + } else if (!llvm::sys::path::is_absolute(CompileCommandsDir) || + !llvm::sys::fs::exists(CompileCommandsDir)) { +llvm::errs() << "Path specified by --compile-commands-dir either does not " +"exist or is not an absolute " +"path. The argument will be ignored.\n"; +CompileCommandsDirPath = llvm::None; + } else { +CompileCommandsDirPath = CompileCommandsDir; + } llvm::Optional ResourceDirRef = None; if (!ResourceDir.empty()) ResourceDirRef = ResourceDir; + /// Change stdin to binary to not lose \r\n on windows. + llvm::sys::ChangeStdinToBinary(); + + /// Initialize and run ClangdLSPServer. ClangdLSPServer LSPServer(Out, WorkerThreadsCount, EnableSnippets, -ResourceDirRef); +ResourceDirRef, CompileCommandsDirPath); LSPServer.run(std::cin); } Index: clangd/GlobalCompilationDatabase.h === --- clangd/GlobalCompilationDatabase.h +++ clangd/GlobalCompilationDatabase.h @@ -47,15 +47,17 @@ class DirectoryBasedGlobalCompilationDatabase : public GlobalCompilationDatabase { public: - DirectoryBasedGlobalCompilationDatabase(clangd::Logger &Logger); + DirectoryBasedGlobalCompilationDatabase( + clangd::Logger &Logger, llvm::Optional NewCompileCommandsDir); std::vector getCompileCommands(PathRef File) override; void setExtraFlagsForFile(PathRef File, std::vector ExtraFlags); private: tooling::CompilationDatabase *getCompilationDatabase(PathRef File); + tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File); std::mutex Mutex; /// Caches compilation databases loaded from directories(keys are @@ -67,6 +69,9 @@ llvm::StringMap> ExtraFlagsForFile; /// Used for logging. clangd::Logger &Logger; + /// Used for command argument pointing to folder where compile_commands.json + /// is located. + llvm::Optional CompileCommandsDir; }; } // namespace clangd } // namespace clang Index: clangd/GlobalCompilationDatabase.cpp === --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -8,10 +8,10 @@ //===-===// #include "GlobalCompilationDatabase.h" +#include "Logger.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" -#include "Logger.h" namespace clang { namespace clangd { @@ -38,8 +38,9 @@ } DirectoryBasedGlobalCompilationDatabase:: -DirectoryBasedGlobalCompilationDatabase(clangd::Logger &Logger) -: Logger(Logger) {} +DirectoryBasedGlobalCompilationDatabase( +clangd::Logger &Logger, llvm::Optional NewCompileCommandsDir) +: Logger(Logger), CompileCommandsDir(NewCompileCommandsDir) {} std::vector DirectoryBasedGlobalCompilationDatabase::getCompileCommands(PathRef File) { @@ -67,31 +68,50 @@ } tooling::CompilationDatabase * -DirectoryBasedGlobalCompilationDatabase::getCompila
[PATCH] D37150: [clangd] Command line arg to specify compile_commands.json path
Nebiroth added a comment. In https://reviews.llvm.org/D37150#885749, @ilya-biryukov wrote: > Thanks for fixing the last comment. > Do you want me to land this for you? Yes please! https://reviews.llvm.org/D37150 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 117351. Nebiroth marked 3 inline comments as done. Nebiroth added a comment. Addressed initial comments. Formatted ClangdUnit.h https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,29 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 455 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"range": {"start": {"line": 16, "character": 4}, "end": {"line": 16, "character": 12}}, "number": 1},{"range": {"start": {"line": 17, "character": 0}, "end": {"line": 17, "character": 7}}, "number": 1}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"range": {"start": {"line": 12, "character": 4}, "end": {"line": 12, "character": 9}}, "number": 1},{"range": {"start": {"line": 18, "character": 17}, "end": {"line": 18, "character": 21}}, "number": 1},{"range": {"start": {"line": 19, "character": 4}, "end": {"line": 19, "character": 8}}, "number": 1}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"range": {"start": {"line": 4, "character": 5}, "end": {"line": 4, "character": 22}}, "number": 1},{"range": {"start": {"line": 21, "character": 8}, "end": {"line": 21, "character": 25}}, "number": 1}]} + Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -47,7 +47,9 @@ virtual void onCompletion(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, -JSONOutput &Out) = 0; +JSONOutput &Out) = 0; + virtual void onDocumentHighlight(TextDocumentPositionParams Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,24 @@ ProtocolCallbacks &Callbacks; }; +struct DocumentHighlightHandler : Handler { + DocumentHighlightHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentPositionParams::parse(Params, Output); +if (!TDPP) { + Output.log("Failed to decode TextDocumentPositionParams!\n"); + return; +} + +Callbacks.onDocumentHighlight(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -240,4 +258,7 @@ Dispatcher.registerHandler( "textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/documentHighlight", + llvm::make_unique(Out, Callbacks)); } Index: clangd/Protocol.h === --- clangd/Protocol.h +++ clangd/Protocol.h @@ -416,6 +416,41 @@ static std::string unparse(const CompletionItem &P); }; +enum class DocumentHighlightKind { + Text =
[PATCH] D38639: [clangd] #include statements support for Open definition
Nebiroth created this revision. ctrl-clicking on #include statements now opens the file being pointed by that statement. https://reviews.llvm.org/D38639 Files: clangd/ClangdServer.cpp clangd/ClangdUnit.cpp clangd/ClangdUnit.h unittests/clangd/ClangdTests.cpp Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -7,7 +7,6 @@ // //===--===// -#include "ClangdLSPServer.h" #include "ClangdServer.h" #include "Logger.h" #include "clang/Basic/VirtualFileSystem.h" @@ -900,82 +899,55 @@ } } -TEST_F(ClangdVFSTest, CheckSourceHeaderSwitch) { +TEST_F(ClangdVFSTest, CheckDefinitionIncludes) { MockFSProvider FS; ErrorCheckingDiagConsumer DiagConsumer; MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true); - ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), + ClangdServer Server(CDB, DiagConsumer, FS, 0, /*SnippetCompletions=*/false, EmptyLogger::getInstance()); - auto SourceContents = R"cpp( + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + const auto SourceContents = R"cpp( #include "foo.h" + #include "invalid.h" int b = a; )cpp"; - - auto FooCpp = getVirtualTestFilePath("foo.cpp"); + FS.Files[FooCpp] = SourceContents; auto FooH = getVirtualTestFilePath("foo.h"); - auto Invalid = getVirtualTestFilePath("main.cpp"); + const auto HeaderContents = "int a;"; FS.Files[FooCpp] = SourceContents; - FS.Files[FooH] = "int a;"; - FS.Files[Invalid] = "int main() { \n return 0; \n }"; + FS.Files[FooH] = HeaderContents; - llvm::Optional PathResult = Server.switchSourceHeader(FooCpp); - EXPECT_TRUE(PathResult.hasValue()); - ASSERT_EQ(PathResult.getValue(), FooH); - - PathResult = Server.switchSourceHeader(FooH); - EXPECT_TRUE(PathResult.hasValue()); - ASSERT_EQ(PathResult.getValue(), FooCpp); + Server.addDocument(FooH, HeaderContents); + Server.addDocument(FooCpp, SourceContents); - SourceContents = R"c( - #include "foo.HH" - int b = a; - )c"; + Position P = Position{1, 11}; - // Test with header file in capital letters and different extension, source - // file with different extension - auto FooC = getVirtualTestFilePath("bar.c"); - auto FooHH = getVirtualTestFilePath("bar.HH"); - - FS.Files[FooC] = SourceContents; - FS.Files[FooHH] = "int a;"; - - PathResult = Server.switchSourceHeader(FooC); - EXPECT_TRUE(PathResult.hasValue()); - ASSERT_EQ(PathResult.getValue(), FooHH); - - // Test with both capital letters - auto Foo2C = getVirtualTestFilePath("foo2.C"); - auto Foo2HH = getVirtualTestFilePath("foo2.HH"); - FS.Files[Foo2C] = SourceContents; - FS.Files[Foo2HH] = "int a;"; - - PathResult = Server.switchSourceHeader(Foo2C); - EXPECT_TRUE(PathResult.hasValue()); - ASSERT_EQ(PathResult.getValue(), Foo2HH); - - // Test with source file as capital letter and .hxx header file - auto Foo3C = getVirtualTestFilePath("foo3.C"); - auto Foo3HXX = getVirtualTestFilePath("foo3.hxx"); + std::vector Locations = (Server.findDefinitions(FooCpp, P)).Value; + EXPECT_TRUE(!Locations.empty()); + std::string s("file:///"); + std::string check = URI::unparse(Locations[0].uri); + check = check.erase(0, s.size()); + check = check.substr(0, check.size() - 1); + ASSERT_EQ(check, FooH); + ASSERT_EQ(Locations[0].range.start.line, 0); + ASSERT_EQ(Locations[0].range.start.character, 0); + ASSERT_EQ(Locations[0].range.end.line, 0); + ASSERT_EQ(Locations[0].range.end.character, 0); + + // Test ctrl-clicking on the #include part on the statement + Position P3 = Position{1, 3}; - SourceContents = R"c( - #include "foo3.hxx" - int b = a; - )c"; + Locations = (Server.findDefinitions(FooCpp, P3)).Value; + EXPECT_TRUE(!Locations.empty()); - FS.Files[Foo3C] = SourceContents; - FS.Files[Foo3HXX] = "int a;"; + // Test invalid include + Position P2 = Position{2, 11}; - PathResult = Server.switchSourceHeader(Foo3C); - EXPECT_TRUE(PathResult.hasValue()); - ASSERT_EQ(PathResult.getValue(), Foo3HXX); - - // Test if asking for a corresponding file that doesn't exist returns an empty - // string. - PathResult = Server.switchSourceHeader(Invalid); - EXPECT_FALSE(PathResult.hasValue()); + Locations = (Server.findDefinitions(FooCpp, P2)).Value; + EXPECT_TRUE(Locations.empty()); } TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) { Index: clangd/ClangdUnit.h === --- clangd/ClangdUnit.h +++ clangd/ClangdUnit.h @@ -127,11 +127,13 @@ struct PreambleData { PreambleData(PrecompiledPreamble Preamble, std::vector TopLevelDeclIDs, - std::vector Diags); + std::vector Diags, + std::map IncludeMap); PrecompiledPreamble Preamble; std::vector TopLevelDeclIDs; std::
[PATCH] D38639: [clangd] #include statements support for Open definition
Nebiroth updated this revision to Diff 118046. Nebiroth added a comment. Fixed accidental removal of CheckSourceHeaderSwitch test https://reviews.llvm.org/D38639 Files: clangd/ClangdServer.cpp clangd/ClangdUnit.cpp clangd/ClangdUnit.h unittests/clangd/ClangdTests.cpp Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -7,7 +7,6 @@ // //===--===// -#include "ClangdLSPServer.h" #include "ClangdServer.h" #include "Logger.h" #include "clang/Basic/VirtualFileSystem.h" @@ -978,6 +977,57 @@ EXPECT_FALSE(PathResult.hasValue()); } +TEST_F(ClangdVFSTest, CheckDefinitionIncludes) { + MockFSProvider FS; + ErrorCheckingDiagConsumer DiagConsumer; + MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true); + + ClangdServer Server(CDB, DiagConsumer, FS, 0, + /*SnippetCompletions=*/false, EmptyLogger::getInstance()); + + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + const auto SourceContents = R"cpp( + #include "foo.h" + #include "invalid.h" + int b = a; + )cpp"; + FS.Files[FooCpp] = SourceContents; + auto FooH = getVirtualTestFilePath("foo.h"); + const auto HeaderContents = "int a;"; + + FS.Files[FooCpp] = SourceContents; + FS.Files[FooH] = HeaderContents; + + Server.addDocument(FooH, HeaderContents); + Server.addDocument(FooCpp, SourceContents); + + Position P = Position{1, 11}; + + std::vector Locations = (Server.findDefinitions(FooCpp, P)).Value; + EXPECT_TRUE(!Locations.empty()); + std::string s("file:///"); + std::string check = URI::unparse(Locations[0].uri); + check = check.erase(0, s.size()); + check = check.substr(0, check.size() - 1); + ASSERT_EQ(check, FooH); + ASSERT_EQ(Locations[0].range.start.line, 0); + ASSERT_EQ(Locations[0].range.start.character, 0); + ASSERT_EQ(Locations[0].range.end.line, 0); + ASSERT_EQ(Locations[0].range.end.character, 0); + + // Test ctrl-clicking on the #include part on the statement + Position P3 = Position{1, 3}; + + Locations = (Server.findDefinitions(FooCpp, P3)).Value; + EXPECT_TRUE(!Locations.empty()); + + // Test invalid include + Position P2 = Position{2, 11}; + + Locations = (Server.findDefinitions(FooCpp, P2)).Value; + EXPECT_TRUE(Locations.empty()); +} + TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) { class NoConcurrentAccessDiagConsumer : public DiagnosticsConsumer { public: Index: clangd/ClangdUnit.h === --- clangd/ClangdUnit.h +++ clangd/ClangdUnit.h @@ -127,11 +127,13 @@ struct PreambleData { PreambleData(PrecompiledPreamble Preamble, std::vector TopLevelDeclIDs, - std::vector Diags); + std::vector Diags, + std::map IncludeMap); PrecompiledPreamble Preamble; std::vector TopLevelDeclIDs; std::vector Diags; + std::map IncludeMap; }; /// Manages resources, required by clangd. Allows to rebuild file with new @@ -261,7 +263,8 @@ /// Get definition of symbol at a specified \p Pos. std::vector findDefinitions(ParsedAST &AST, Position Pos, - clangd::Logger &Logger); + clangd::Logger &Logger, + std::map); /// For testing/debugging purposes. Note that this method deserializes all /// unserialized Decls, so use with care. Index: clangd/ClangdUnit.cpp === --- clangd/ClangdUnit.cpp +++ clangd/ClangdUnit.cpp @@ -78,6 +78,10 @@ return std::move(TopLevelDeclIDs); } + std::map takeIncludeMap() { +return std::move(IncludeMap); + } + void AfterPCHEmitted(ASTWriter &Writer) override { TopLevelDeclIDs.reserve(TopLevelDecls.size()); for (Decl *D : TopLevelDecls) { @@ -96,9 +100,55 @@ } } + void AfterExecute(CompilerInstance &CI) override { +const SourceManager &SM = CI.getSourceManager(); +unsigned n = SM.local_sloc_entry_size(); +SmallVector InclusionStack; +std::map::iterator it = IncludeMap.begin(); + +for (unsigned i = 0; i < n; ++i) { + bool Invalid = false; + const SrcMgr::SLocEntry &SL = SM.getLocalSLocEntry(i, &Invalid); + if (!SL.isFile() || Invalid) +continue; + const SrcMgr::FileInfo &FI = SL.getFile(); + SourceLocation L = FI.getIncludeLoc(); + InclusionStack.clear(); + + SourceLocation LocationToInsert; + + while (L.isValid()) { +PresumedLoc PLoc = SM.getPresumedLoc(L); +InclusionStack.push_back(L); +L = PLoc.isValid() ? PLoc.getIncludeLoc() : SourceLocation(); + } + if (InclusionStack.size() == 0) { +// Skip main file +continue; + } + + if (InclusionStack.size() > 1) { +// Don't care a
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 118482. Nebiroth added a comment. Rebased on master. https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -5,18 +5,21 @@ Content-Length: 143 {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootUri":"file:///path/to/workspace","capabilities":{},"trace":"off"}} -# CHECK: Content-Length: 535 +# CHECK: Content-Length: 580 # CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{ # CHECK: "textDocumentSync": 1, # CHECK: "documentFormattingProvider": true, # CHECK: "documentRangeFormattingProvider": true, # CHECK: "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]}, # CHECK: "codeActionProvider": true, # CHECK: "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]}, # CHECK: "signatureHelpProvider": {"triggerCharacters": ["(",","]}, -# CHECK: "definitionProvider": true +# CHECK: "definitionProvider": true, +# CHECK: "documentHighlightProvider": true # CHECK: }}} # Content-Length: 44 {"jsonrpc":"2.0","id":3,"method":"shutdown"} + + Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -5,16 +5,17 @@ Content-Length: 142 {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":"","rootUri":"file:///path/to/workspace","capabilities":{},"trace":"off"}} -# CHECK: Content-Length: 535 +# CHECK: Content-Length: 580 # CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{ # CHECK: "textDocumentSync": 1, # CHECK: "documentFormattingProvider": true, # CHECK: "documentRangeFormattingProvider": true, # CHECK: "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]}, # CHECK: "codeActionProvider": true, # CHECK: "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]}, # CHECK: "signatureHelpProvider": {"triggerCharacters": ["(",","]}, -# CHECK: "definitionProvider": true +# CHECK: "definitionProvider": true, +# CHECK: "documentHighlightProvider": true # CHECK: }}} # Content-Length: 44 Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,42 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} +# CHECK: Content-Length: 580 +# CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{ +# CHECK: "textDocumentSync": 1, +# CHECK: "documentFormattingProvider": true, +# CHECK: "documentRangeFormattingProvider": true, +# CHECK: "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]}, +# CHECK: "codeActionProvider": true, +# CHECK: "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]}, +# CHECK: "signatureHelpProvider": {"triggerCharacters": ["(",","]}, +# CHECK: "definitionProvider": true, +# CHECK: "documentHighlightProvider": true +# CHECK: }}} +# + +Content-Length: 455 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"range": {"start": {"line": 16, "character": 4}, "end": {"line": 16, "character": 12}}, "kind": 1},{"range": {"start": {"line": 17, "character": 0}, "end": {"line": 17, "character": 7}}, "kind": 1}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"charact
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth marked 3 inline comments as done. Nebiroth added inline comments. Comment at: clangd/ClangdUnit.cpp:1017 + + auto DeclLocationsFinder = std::make_shared( + llvm::errs(), SourceLocationBeg, AST.getASTContext(), ilya-biryukov wrote: > I wonder if we really need to rerun indexer twice here. Probably ok for the > first version, but we should definitely think about a faster way to get the > `Decl` under cursor than visiting the whole AST. Not sure if it's easy to do > with clang's AST, though, maybe we'll need a separate index for that. Yeah I realise it's definitely not the fastest way to go about it. Maybe there is a way to stop handling occurrences once the highlighted declaration is found. This would be the most straightforward way of improving the performance of the feature without re-writing a new AST indexer. https://reviews.llvm.org/D38425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth added a comment. Bumping this. I've worked on a patch for this feature that currently supports showing the declaration of whatever is being hovered on instead of the raw source code. It also has basic support to distinguish declarations in types ( class/struct, namespace, global variable, typedef, enum, namespace, etc.) so that we can have a 'kind' of a symbol like mentioned in the comments above. The step I am at right now is figuring out a way to display this information inside the box that will be displayed to the client once a response (MarkedString) is sent back by the server. I would like some feedback/suggestions on whether it's possible to "append" information to a MarkedString to be displayed on client? I was also considering extending LSP to include more than just a MarkedString for the response in order to have something a bit more flexible to use in-client. https://reviews.llvm.org/D35894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth marked an inline comment as done. Nebiroth added inline comments. Comment at: clangd/ClangdUnit.cpp:784 +/// Finds declarations locations that a given source location refers to. +class TargetDeclarationFinder : public index::IndexDataConsumer { + std::vector DeclarationLocations; ilya-biryukov wrote: > This `IndexDataConsumer` effectively does the same thing as > `DeclarationLocationsFinder`. > We should reuse the code between those two. > > To do that we could: > 1. Change `DeclarationLocationsFinder` to return a list of `Decl*`s and > `MacroDef*`s that are under caret. > 2. In `findDefinition` we should return locations of found `Decl` and > `MacroDef`. > 3. In `documentHighlights` we would rerun `DocumentHighlightsFinder`to > capture locations of `Decls` referenced in step 1. > > Do you think this approach would work? I have something similar to this implemented. Will upstream it soon. https://reviews.llvm.org/D38425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 118838. Nebiroth marked an inline comment as done. Nebiroth added a comment. Addressed review comments. Fixed some tests not having updated providers. Removed TargetDeclarationFinder for less code reuse. DocumentHighlight struct is now unparsed correctly. https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -5,18 +5,21 @@ Content-Length: 143 {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootUri":"file:///path/to/workspace","capabilities":{},"trace":"off"}} -# CHECK: Content-Length: 535 +# CHECK: Content-Length: 580 # CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{ # CHECK: "textDocumentSync": 1, # CHECK: "documentFormattingProvider": true, # CHECK: "documentRangeFormattingProvider": true, # CHECK: "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]}, # CHECK: "codeActionProvider": true, # CHECK: "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]}, # CHECK: "signatureHelpProvider": {"triggerCharacters": ["(",","]}, -# CHECK: "definitionProvider": true +# CHECK: "definitionProvider": true, +# CHECK: "documentHighlightProvider": true # CHECK: }}} # Content-Length: 44 {"jsonrpc":"2.0","id":3,"method":"shutdown"} + + Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -5,16 +5,17 @@ Content-Length: 142 {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":"","rootUri":"file:///path/to/workspace","capabilities":{},"trace":"off"}} -# CHECK: Content-Length: 535 +# CHECK: Content-Length: 580 # CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{ # CHECK: "textDocumentSync": 1, # CHECK: "documentFormattingProvider": true, # CHECK: "documentRangeFormattingProvider": true, # CHECK: "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]}, # CHECK: "codeActionProvider": true, # CHECK: "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]}, # CHECK: "signatureHelpProvider": {"triggerCharacters": ["(",","]}, -# CHECK: "definitionProvider": true +# CHECK: "definitionProvider": true, +# CHECK: "documentHighlightProvider": true # CHECK: }}} # Content-Length: 44 Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,42 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} +# CHECK: Content-Length: 580 +# CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{ +# CHECK: "textDocumentSync": 1, +# CHECK: "documentFormattingProvider": true, +# CHECK: "documentRangeFormattingProvider": true, +# CHECK: "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]}, +# CHECK: "codeActionProvider": true, +# CHECK: "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]}, +# CHECK: "signatureHelpProvider": {"triggerCharacters": ["(",","]}, +# CHECK: "definitionProvider": true, +# CHECK: "documentHighlightProvider": true +# CHECK: }}} +# + +Content-Length: 455 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"range": {"start": {"line": 16, "character": 4}, "end": {"line": 16, "character": 12}}, "kind": 1},{"range": {"start": {"line": 17, "character": 0}, "end": {"line": 17, "c
[PATCH] D38639: [clangd] #include statements support for Open definition
Nebiroth marked 21 inline comments as done. Nebiroth added inline comments. Comment at: clangd/ClangdUnit.cpp:103 + void AfterExecute(CompilerInstance &CI) override { +const SourceManager &SM = CI.getSourceManager(); ilya-biryukov wrote: > There's a much better public API to get all includes that were encountered by > the `Preprocessor`: we need to override `PPCallbacks ::InclusionDirective`. > > > `PrecompiledPreamble` does not currently expose this callbacks, but could you > add to `PreambleCallbacks` in a separate commit? > If I were to use InclusionDirective , how would that callback be called automatically? As far as I know, it wouldn't be called automatically for every file that gets indexed the same way AfterExecute would be. https://reviews.llvm.org/D38639 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth added a comment. In https://reviews.llvm.org/D35894#903594, @ilya-biryukov wrote: > In https://reviews.llvm.org/D35894#903552, @malaperle wrote: > > > I think he meant to have multiple sections in the hover, one C/C++ and one > > not. But we noticed you can have an array of MarkedString in Hover so it > > should be fine. > > > I totally misunderstood the question. Good to know it all works without > changing the LSP. > Just to make sure I got it right this time: the use-case is to, e.g., return > both a code snippet (having `"language": cpp`) and a documentation string > (without `language`) as a result of hover request? That's about it. I'm sitting on a code hover patch that does more or less what you just described. One MarkedString with it's language field set to "C++" returns the appropriate code snippet for the code hover and another MarkedString with it's language field set to "markdown" returns the associated scope. https://reviews.llvm.org/D35894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D39571: [clangd] DidChangeConfiguration Notification
Nebiroth updated this revision to Diff 126980. Nebiroth marked 5 inline comments as done. Nebiroth added a comment. Removed test file Added mutex lock when changing CDB Minor code cleanup Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D39571 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/DraftStore.cpp clangd/DraftStore.h clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -18,9 +18,10 @@ # CHECK-NEXT: ":" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "configurationChangeProvider": true, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, -# CHECK-NEXT: "documentHighlightProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] @@ -49,4 +50,4 @@ # CHECK-NEXT: "result": null Content-Length: 33 -{"jsonrpc":"2.0":"method":"exit"} +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -18,9 +18,10 @@ # CHECK-NEXT: ":" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "configurationChangeProvider": true, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, -# CHECK-NEXT: "documentHighlightProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -57,6 +57,8 @@ virtual void onRename(Ctx C, RenameParams &Parames) = 0; virtual void onDocumentHighlight(Ctx C, TextDocumentPositionParams &Params) = 0; + virtual void onChangeConfiguration(Ctx C, + DidChangeConfigurationParams &Params) = 0; }; void registerCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -73,4 +73,6 @@ Register("workspace/executeCommand", &ProtocolCallbacks::onCommand); Register("textDocument/documentHighlight", &ProtocolCallbacks::onDocumentHighlight); + Register("workspace/didChangeConfiguration", + &ProtocolCallbacks::onChangeConfiguration); } Index: clangd/Protocol.h === --- clangd/Protocol.h +++ clangd/Protocol.h @@ -257,6 +257,24 @@ }; bool fromJSON(const json::Expr &, DidChangeWatchedFilesParams &); +/// Clangd extension to manage a workspace/didChangeConfiguration notification +/// since the data received is described as 'any' type in LSP. +struct ClangdConfigurationParamsChange { + llvm::Optional compilationDatabasePath; +}; +bool fromJSON(const json::Expr &, ClangdConfigurationParamsChange &); + +struct DidChangeConfigurationParams { + DidChangeConfigurationParams() = default; + DidChangeConfigurationParams(ClangdConfigurationParamsChange settings): settings(settings) {} + + // We use this predefined struct because it is easier to use + // than the protocol specified type of 'any'. + ClangdConfigurationParamsChange settings; +}; +bool fromJSON(const json::Expr &, DidChangeConfigurationParams &); +json::Expr toJSON(const DidChangeConfigurationParams &); + struct FormattingOptions { /// Size of a tab in spaces. int tabSize; Index: clangd/Protocol.cpp === --- clangd/Protocol.cpp +++ clangd/Protocol.cpp @@ -366,5 +366,21 @@ }; } +bool fromJSON(const json::Expr &Params, DidChangeConfigurationParams &CCP) { + json::ObjectMapper O(Params); + return O && O.map("settings", CCP.settings); +} + +json::Expr toJSON(const DidChangeConfigurationParams &CCP) { + return json::obj{ +{"settings", CCP.settings}, + }; +} + +bool fromJSON(const json::Expr &Params, ClangdConfigurationParamsChange &CCPC) { + json::ObjectMapper O(Params); + re
[PATCH] D39375: [clang] Add PPCallbacks list to preprocessor when building a preacompiled preamble.
Nebiroth updated this revision to Diff 126984. Nebiroth marked an inline comment as done. Nebiroth added a comment. Minor code cleanup Repository: rC Clang https://reviews.llvm.org/D39375 Files: include/clang/Frontend/PrecompiledPreamble.h lib/Frontend/PrecompiledPreamble.cpp Index: lib/Frontend/PrecompiledPreamble.cpp === --- lib/Frontend/PrecompiledPreamble.cpp +++ lib/Frontend/PrecompiledPreamble.cpp @@ -351,6 +351,10 @@ if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) return BuildPreambleError::BeginSourceFileFailed; + std::unique_ptr DelegatedPPCallbacks = Callbacks.createPPCallbacks(); + + if (DelegatedPPCallbacks) +Clang->getPreprocessor().addPPCallbacks(std::move(DelegatedPPCallbacks)); Act->Execute(); // Run the callbacks. @@ -709,6 +713,7 @@ void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {} void PreambleCallbacks::HandleMacroDefined(const Token &MacroNameTok, const MacroDirective *MD) {} +std::unique_ptr PreambleCallbacks::createPPCallbacks() {return nullptr;} std::error_code clang::make_error_code(BuildPreambleError Error) { return std::error_code(static_cast(Error), BuildPreambleErrorCategory()); Index: include/clang/Frontend/PrecompiledPreamble.h === --- include/clang/Frontend/PrecompiledPreamble.h +++ include/clang/Frontend/PrecompiledPreamble.h @@ -260,6 +260,9 @@ /// used instead, but having only this method allows a simpler API. virtual void HandleMacroDefined(const Token &MacroNameTok, const MacroDirective *MD); + /// Creates wrapper class for PPCallbacks so we can also process information + /// about includes that are inside of a preamble + virtual std::unique_ptr createPPCallbacks(); }; enum class BuildPreambleError { Index: lib/Frontend/PrecompiledPreamble.cpp === --- lib/Frontend/PrecompiledPreamble.cpp +++ lib/Frontend/PrecompiledPreamble.cpp @@ -351,6 +351,10 @@ if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) return BuildPreambleError::BeginSourceFileFailed; + std::unique_ptr DelegatedPPCallbacks = Callbacks.createPPCallbacks(); + + if (DelegatedPPCallbacks) +Clang->getPreprocessor().addPPCallbacks(std::move(DelegatedPPCallbacks)); Act->Execute(); // Run the callbacks. @@ -709,6 +713,7 @@ void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {} void PreambleCallbacks::HandleMacroDefined(const Token &MacroNameTok, const MacroDirective *MD) {} +std::unique_ptr PreambleCallbacks::createPPCallbacks() {return nullptr;} std::error_code clang::make_error_code(BuildPreambleError Error) { return std::error_code(static_cast(Error), BuildPreambleErrorCategory()); Index: include/clang/Frontend/PrecompiledPreamble.h === --- include/clang/Frontend/PrecompiledPreamble.h +++ include/clang/Frontend/PrecompiledPreamble.h @@ -260,6 +260,9 @@ /// used instead, but having only this method allows a simpler API. virtual void HandleMacroDefined(const Token &MacroNameTok, const MacroDirective *MD); + /// Creates wrapper class for PPCallbacks so we can also process information + /// about includes that are inside of a preamble + virtual std::unique_ptr createPPCallbacks(); }; enum class BuildPreambleError { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth updated this revision to Diff 127131. Nebiroth added a comment. Rebase on master Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D35894 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/hover.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -31,6 +31,7 @@ # CHECK-NEXT: "clangd.applyFix" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "renameProvider": true, # CHECK-NEXT: "signatureHelpProvider": { # CHECK-NEXT:"triggerCharacters": [ Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -31,6 +31,7 @@ # CHECK-NEXT: "clangd.applyFix" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "renameProvider": true, # CHECK-NEXT: "signatureHelpProvider": { # CHECK-NEXT:"triggerCharacters": [ Index: test/clangd/hover.test === --- /dev/null +++ test/clangd/hover.test @@ -0,0 +1,56 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 611 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nint test = 5;\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};}\n//comments test\ntemplate\nT templateTest(T foo) {\nreturn foo;}\ntemplate\nclass classTemplateTest {\npublic: T test;};\nint main() {\nint a;\na;\nint b = ns1::test;\nns1::MyClass* Params;\nParams->anotherOperation();\nMACRO;\nint temp = 5;\ntemplateTest(temp);classTemplateTest test;}\n"}}} + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":0,"character":12}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"#define MACRO 1"}],"range":{"end":{"character":15,"line":0},"start":{"character":8,"line":0 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":1}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"int a"}],"range":{"end":{"character":5,"line":20},"start":{"character":0,"line":20 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":22,"character":15}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1"},{"language":"C++","value":"int test = 5"}],"range":{"end":{"character":12,"line":2},"start":{"character":0,"line":2 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":23,"character":10}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1"},{"language":"C++","value":"struct MyClass {"}],"range":{"end":{"character":16,"line":3},"start":{"character":0,"line":3 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":24,"character":13}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1::MyClass"},{"language":"C++","value":"void anotherOperation() {"}],"range":{"end":{"character":25,"line":5},"start":{"character":0,"line":5 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":25,"character":1}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"#define MACRO 1"}],"range":{"end":{"character":15,"line":0},"start":{"character":8,"line":0 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":26,"character":8}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":
[PATCH] D38639: [clangd] #include statements support for Open definition
Nebiroth updated this revision to Diff 127161. Nebiroth marked 27 inline comments as done. Nebiroth added a comment. inner class IncludeReferenceMap replaced by one map fillRangeVector() and findPreambleIncludes() code moved into wrapper class Open definition now returns an empty Range struct (line, character = 0) Fixed unit tests Minor code improvements Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38639 Files: clangd/ClangdServer.cpp clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.h unittests/clangd/ClangdTests.cpp Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -7,7 +7,6 @@ // //===--===// -#include "ClangdLSPServer.h" #include "ClangdServer.h" #include "Logger.h" #include "TestFS.h" @@ -749,6 +748,75 @@ EXPECT_FALSE(PathResult.hasValue()); } +TEST_F(ClangdVFSTest, CheckDefinitionIncludes) { + MockFSProvider FS; + ErrorCheckingDiagConsumer DiagConsumer; + MockCompilationDatabase CDB; + + ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), + /*StorePreamblesInMemory=*/true, + EmptyLogger::getInstance()); + + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + const auto SourceContents = R"cpp( + #include "foo.h" + #include "invalid.h" + int b = a; + // test + int foo; + #include "foo.h" + )cpp"; + FS.Files[FooCpp] = SourceContents; + auto FooH = getVirtualTestFilePath("foo.h"); + const auto HeaderContents = "int a;"; + + FS.Files[FooCpp] = SourceContents; + FS.Files[FooH] = HeaderContents; + + Server.addDocument(FooH, HeaderContents); + Server.addDocument(FooCpp, SourceContents); + + Position P = Position{1, 11}; + + auto ExpectedLocations = Server.findDefinitions(FooCpp, P); + ASSERT_TRUE(!!ExpectedLocations); + std::vector Locations = ExpectedLocations->Value; + EXPECT_TRUE(!Locations.empty()); + std::string s("file:///"); + std::string check = Locations[0].uri.uri; + check = check.erase(0, s.size() - 1); + check = check.substr(0, check.size()); + ASSERT_EQ(check, FooH); + ASSERT_EQ(Locations[0].range.start.line, 0); + ASSERT_EQ(Locations[0].range.start.character, 0); + ASSERT_EQ(Locations[0].range.end.line, 0); + ASSERT_EQ(Locations[0].range.end.character, 0); + + // Test ctrl-clicking on the #include part on the statement + Position P2 = Position{1, 3}; + + ExpectedLocations = Server.findDefinitions(FooCpp, P2); + ASSERT_TRUE(!!ExpectedLocations); + Locations = ExpectedLocations->Value; + EXPECT_TRUE(!Locations.empty()); + + // Test invalid include + Position P3 = Position{2, 11}; + + ExpectedLocations = Server.findDefinitions(FooCpp, P3); + ASSERT_TRUE(!!ExpectedLocations); + Locations = ExpectedLocations->Value; + EXPECT_TRUE(Locations.empty()); + + // Test include outside of Preamble + Position P4 = Position{6, 5}; + + ExpectedLocations = Server.findDefinitions(FooCpp, P4); + ASSERT_TRUE(!!ExpectedLocations); + Locations = ExpectedLocations->Value; + EXPECT_TRUE(!Locations.empty()); +} + TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) { class NoConcurrentAccessDiagConsumer : public DiagnosticsConsumer { public: Index: clangd/Protocol.h === --- clangd/Protocol.h +++ clangd/Protocol.h @@ -108,6 +108,14 @@ bool fromJSON(const json::Expr &, Range &); json::Expr toJSON(const Range &); +class RangeHash { +public: + std::size_t operator()(const Range &R) const { +return ((R.start.line & 0x18) << 3) | ((R.start.character & 0x18) << 1) | + ((R.end.line & 0x18) >> 1) | ((R.end.character & 0x18) >> 3); + } +}; + struct Location { /// The text document's URI. URI uri; Index: clangd/ClangdUnit.h === --- clangd/ClangdUnit.h +++ clangd/ClangdUnit.h @@ -22,6 +22,7 @@ #include #include #include +#include namespace llvm { class raw_ostream; @@ -59,6 +60,8 @@ std::vector Diags; }; +using IncludeReferenceMap = std::unordered_map; + /// Stores and provides access to parsed AST. class ParsedAST { public: @@ -69,7 +72,8 @@ std::shared_ptr Preamble, std::unique_ptr Buffer, std::shared_ptr PCHs, -IntrusiveRefCntPtr VFS, clangd::Logger &Logger); +IntrusiveRefCntPtr VFS, clangd::Logger &Logger, +IncludeReferenceMap &IRM); ParsedAST(ParsedAST &&Other); ParsedAST &operator=(ParsedAST &&Other); @@ -89,12 +93,14 @@ const std::vector &getDiagnostics() const; + IncludeReferenceMap &getIRM() { return IRM; }; + private: ParsedAST(std::shared_ptr Preamble, std::unique_ptr Clang, std::unique_ptr Action, std::vector TopLevelDecls, -std::vector Diags); +std::vector Diags, IncludeRef
[PATCH] D38639: [clangd] #include statements support for Open definition
Nebiroth updated this revision to Diff 127386. Nebiroth marked 14 inline comments as done. Nebiroth added a comment. Herald added a subscriber: mgrang. CppFilePreambleCallbacks no longer extends PPCallbacks CppFilePreambleCallbacks no longer needs SourceManager parameter Removed temporary vector TempPreambleIncludeLocations IncludeReferenceMap in ParsedAST no longer passed by reference Code handling includes outside of preambles is now separated in IncludeRefsCollector class Removed addLocation Changed isSameLine function name and now checks if searched location is in range instead of verifying the line Removed changes to findDefinitions interface Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38639 Files: clangd/ClangdServer.cpp clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.h unittests/clangd/ClangdTests.cpp Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -7,7 +7,6 @@ // //===--===// -#include "ClangdLSPServer.h" #include "ClangdServer.h" #include "Context.h" #include "TestFS.h" @@ -751,6 +750,75 @@ EXPECT_FALSE(PathResult.hasValue()); } +TEST_F(ClangdVFSTest, CheckDefinitionIncludes) { + MockFSProvider FS; + ErrorCheckingDiagConsumer DiagConsumer; + MockCompilationDatabase CDB; + + ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), + /*StorePreamblesInMemory=*/true, + EmptyLogger::getInstance()); + + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + const auto SourceContents = R"cpp( + #include "foo.h" + #include "invalid.h" + int b = a; + // test + int foo; + #include "foo.h" + )cpp"; + FS.Files[FooCpp] = SourceContents; + auto FooH = getVirtualTestFilePath("foo.h"); + const auto HeaderContents = "int a;"; + + FS.Files[FooCpp] = SourceContents; + FS.Files[FooH] = HeaderContents; + + Server.addDocument(FooH, HeaderContents); + Server.addDocument(FooCpp, SourceContents); + + Position P = Position{1, 11}; + + auto ExpectedLocations = Server.findDefinitions(FooCpp, P); + ASSERT_TRUE(!!ExpectedLocations); + std::vector Locations = ExpectedLocations->Value; + EXPECT_TRUE(!Locations.empty()); + std::string s("file:///"); + std::string check = Locations[0].uri.uri; + check = check.erase(0, s.size() - 1); + check = check.substr(0, check.size()); + ASSERT_EQ(check, FooH); + ASSERT_EQ(Locations[0].range.start.line, 0); + ASSERT_EQ(Locations[0].range.start.character, 0); + ASSERT_EQ(Locations[0].range.end.line, 0); + ASSERT_EQ(Locations[0].range.end.character, 0); + + // Test ctrl-clicking on the #include part on the statement + Position P2 = Position{1, 3}; + + ExpectedLocations = Server.findDefinitions(FooCpp, P2); + ASSERT_TRUE(!!ExpectedLocations); + Locations = ExpectedLocations->Value; + EXPECT_TRUE(!Locations.empty()); + + // Test invalid include + Position P3 = Position{2, 11}; + + ExpectedLocations = Server.findDefinitions(FooCpp, P3); + ASSERT_TRUE(!!ExpectedLocations); + Locations = ExpectedLocations->Value; + EXPECT_TRUE(Locations.empty()); + + // Test include outside of Preamble + Position P4 = Position{6, 5}; + + ExpectedLocations = Server.findDefinitions(FooCpp, P4); + ASSERT_TRUE(!!ExpectedLocations); + Locations = ExpectedLocations->Value; + EXPECT_TRUE(!Locations.empty()); +} + TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) { class NoConcurrentAccessDiagConsumer : public DiagnosticsConsumer { public: Index: clangd/Protocol.h === --- clangd/Protocol.h +++ clangd/Protocol.h @@ -108,6 +108,14 @@ bool fromJSON(const json::Expr &, Range &); json::Expr toJSON(const Range &); +class RangeHash { +public: + std::size_t operator()(const Range &R) const { +return ((R.start.line & 0x18) << 3) | ((R.start.character & 0x18) << 1) | + ((R.end.line & 0x18) >> 1) | ((R.end.character & 0x18) >> 3); + } +}; + struct Location { /// The text document's URI. URI uri; Index: clangd/ClangdUnit.h === --- clangd/ClangdUnit.h +++ clangd/ClangdUnit.h @@ -23,6 +23,7 @@ #include #include #include +#include namespace llvm { class raw_ostream; @@ -58,17 +59,22 @@ std::vector Diags; }; +using IncludeReferenceMap = std::unordered_map; + /// Stores and provides access to parsed AST. class ParsedAST { public: /// Attempts to run Clang and store parsed AST. If \p Preamble is non-null /// it is reused during parsing. static llvm::Optional - Build(const Context &Ctx, std::unique_ptr CI, -std::shared_ptr Preamble, -std::unique_ptr Buffer, -std::shared_ptr PCHs, -IntrusiveRefCntPtr VFS); + Build(const Context &Ctx, + std::unique_ptr
[PATCH] D41365: [clang] Add BeforeExecute method to PrecompiledPreamble
Nebiroth created this revision. Nebiroth added reviewers: malaperle, ilya-biryukov. Adds BeforeExecute method to PrecompiledPreamble to be called before Execute(). This method can be overriden. Repository: rC Clang https://reviews.llvm.org/D41365 Files: include/clang/Frontend/PrecompiledPreamble.h lib/Frontend/PrecompiledPreamble.cpp Index: lib/Frontend/PrecompiledPreamble.cpp === --- lib/Frontend/PrecompiledPreamble.cpp +++ lib/Frontend/PrecompiledPreamble.cpp @@ -328,6 +328,7 @@ Clang->setSourceManager( new SourceManager(Diagnostics, Clang->getFileManager())); + Callbacks.BeforeExecute(*Clang); auto PreambleDepCollector = std::make_shared(); Clang->addDependencyCollector(PreambleDepCollector); @@ -704,6 +705,7 @@ } } +void PreambleCallbacks::BeforeExecute(CompilerInstance &CI) {} void PreambleCallbacks::AfterExecute(CompilerInstance &CI) {} void PreambleCallbacks::AfterPCHEmitted(ASTWriter &Writer) {} void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {} Index: include/clang/Frontend/PrecompiledPreamble.h === --- include/clang/Frontend/PrecompiledPreamble.h +++ include/clang/Frontend/PrecompiledPreamble.h @@ -244,6 +244,9 @@ public: virtual ~PreambleCallbacks() = default; + /// Called before FrontendAction::Execute(). Can be used to assign a SourceManager + /// from a CompilerInstance. + virtual void BeforeExecute(CompilerInstance &CI); /// Called after FrontendAction::Execute(), but before /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of /// various CompilerInstance fields before they are destroyed. Index: lib/Frontend/PrecompiledPreamble.cpp === --- lib/Frontend/PrecompiledPreamble.cpp +++ lib/Frontend/PrecompiledPreamble.cpp @@ -328,6 +328,7 @@ Clang->setSourceManager( new SourceManager(Diagnostics, Clang->getFileManager())); + Callbacks.BeforeExecute(*Clang); auto PreambleDepCollector = std::make_shared(); Clang->addDependencyCollector(PreambleDepCollector); @@ -704,6 +705,7 @@ } } +void PreambleCallbacks::BeforeExecute(CompilerInstance &CI) {} void PreambleCallbacks::AfterExecute(CompilerInstance &CI) {} void PreambleCallbacks::AfterPCHEmitted(ASTWriter &Writer) {} void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {} Index: include/clang/Frontend/PrecompiledPreamble.h === --- include/clang/Frontend/PrecompiledPreamble.h +++ include/clang/Frontend/PrecompiledPreamble.h @@ -244,6 +244,9 @@ public: virtual ~PreambleCallbacks() = default; + /// Called before FrontendAction::Execute(). Can be used to assign a SourceManager + /// from a CompilerInstance. + virtual void BeforeExecute(CompilerInstance &CI); /// Called after FrontendAction::Execute(), but before /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of /// various CompilerInstance fields before they are destroyed. ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth marked 21 inline comments as done. Nebiroth added inline comments. Comment at: clangd/ClangdServer.h:306 + /// Run formatting for \p Rng inside \p File. + std::vector formatRange(PathRef File, Range Rng); + /// Run formatting for the whole \p File. ilya-biryukov wrote: > These functions are duplicates of existing ones, they should not be here. > Bad merge? Yes, this is a bad merge. Comment at: clangd/ClangdUnit.cpp:438 + // trimming the extra "::" + std::string Res; + PrintingPolicy WithScopePP(LangOpts); ilya-biryukov wrote: > We should avoid doing the string-matching when we have the AST. > Use something like this instead (haven't tested, but you should get the idea): > > ``` > /// Returns a NamedDecl that could be used to print the qualifier. > Decl* getScopeOfDecl(Decl* D) { > // Code from NamedDecl::printQualifiedName, we should probably move it into > const DeclContext *Ctx = D->getDeclContext(); > > // For ObjC methods, look through categories and use the interface as > context. > if (auto *MD = dyn_cast(D)) > if (auto *ID = MD->getClassInterface()) > Ctx = ID; > > if (Ctx->isFunctionOrMethod()) { > /// This is a function-local entity. > return nullptr; > } > > return Ctx; > } > > > std::string printScopeOfDecl(Decl* Scope) { > if (isa(Scope)) > return "global namespace"; > > if (isa(Scope)) > return cast(Scope)->printQualifiedName(); > > return ""; > } > > > // Later use like this: > auto ScopeText = printScopeOfDecl(getScopeOfDecl(D)); > ``` > I'm not sure I understand. The intention was to have a separate MarkedString display the scope for whatever we are hovering on. The way I understand the above code, this would display a scope that isn't as precise as I would like which defeats the purpose of having this feature in the first place. Comment at: clangd/ClangdUnit.cpp:498 Position Begin; - Begin.line = SourceMgr.getSpellingLineNumber(LocStart) - 1; - Begin.character = SourceMgr.getSpellingColumnNumber(LocStart) - 1; + Begin.line = SourceMgr.getExpansionLineNumber(LocStart) - 1; + Begin.character = SourceMgr.getExpansionColumnNumber(LocStart) - 1; ilya-biryukov wrote: > Why are we changing the semantics here? Why should we use expansion locations > instead of spelling locations here? Bad merge. Comment at: clangd/ClangdUnit.cpp:591 +// one line at a time to determine what will be included. +SourceLocation getFunctionComments(ParsedAST &AST, const Decl *D) { + ilya-biryukov wrote: > This code seems pretty involved. Don't `RawComment`s handle this case? Bad merge. Comment at: clangd/ClangdUnit.cpp:968 // createInvocationFromCommandLine sets DisableFree. + CI->LangOpts->CommentOpts.ParseAllComments = true; CI->getFrontendOpts().DisableFree = false; ilya-biryukov wrote: > This should clearly go before the comment! > Also, we're currently setting this flag when building the preamble, but not > when parsing the AST. We should definitely do that in both cases. Do you mean also adding this line somewhere in ASTUnit.cpp? Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D35894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth updated this revision to Diff 127413. Nebiroth marked 3 inline comments as done. Nebiroth added a comment. findHover properly returns an error Removed many cases of bad merging Separated getHover in two functions Minor indenting and NIT fixes Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D35894 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/hover.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -31,6 +31,7 @@ # CHECK-NEXT: "clangd.applyFix" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "renameProvider": true, # CHECK-NEXT: "signatureHelpProvider": { # CHECK-NEXT:"triggerCharacters": [ Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -31,6 +31,7 @@ # CHECK-NEXT: "clangd.applyFix" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "renameProvider": true, # CHECK-NEXT: "signatureHelpProvider": { # CHECK-NEXT:"triggerCharacters": [ Index: test/clangd/hover.test === --- /dev/null +++ test/clangd/hover.test @@ -0,0 +1,56 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 611 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nint test = 5;\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};}\n//comments test\ntemplate\nT templateTest(T foo) {\nreturn foo;}\ntemplate\nclass classTemplateTest {\npublic: T test;};\nint main() {\nint a;\na;\nint b = ns1::test;\nns1::MyClass* Params;\nParams->anotherOperation();\nMACRO;\nint temp = 5;\ntemplateTest(temp);classTemplateTest test;}\n"}}} + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":0,"character":12}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"#define MACRO 1"}],"range":{"end":{"character":15,"line":0},"start":{"character":8,"line":0 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":1}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"int a"}],"range":{"end":{"character":5,"line":20},"start":{"character":0,"line":20 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":22,"character":15}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1"},{"language":"C++","value":"int test = 5"}],"range":{"end":{"character":12,"line":2},"start":{"character":0,"line":2 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":23,"character":10}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1"},{"language":"C++","value":"struct MyClass {"}],"range":{"end":{"character":16,"line":3},"start":{"character":0,"line":3 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":24,"character":13}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1::MyClass"},{"language":"C++","value":"void anotherOperation() {"}],"range":{"end":{"character":25,"line":5},"start":{"character":0,"line":5 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":25,"character":1}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"#define MACRO 1"}],"range":{"end":{"character":15,"line":0},"start":{"character":8,"line":0 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textD
[PATCH] D38639: [clangd] #include statements support for Open definition
Nebiroth marked 8 inline comments as done. Nebiroth added inline comments. Comment at: clangd/ClangdUnit.cpp:85 + +if (SourceMgr.getMainFileID() == SourceMgr.getFileID(FilenameRange.getAsRange().getBegin()) && SourceMgr.isInMainFile(FilenameRange.getAsRange().getBegin())) { + // Only inclusion directives in the main file make sense. The user cannot ilya-biryukov wrote: > ilya-biryukov wrote: > > `clang-format` please > Do we need both checks? Doesn't `SourceMgr.isInMainFile` handles all the > cases? This check was here to prevent an issue that appeared previously. I don't think this check is needed anymore. Comment at: clangd/ClangdUnit.cpp:147 + IncludeReferenceMap &IRM; + std::vector> TempPreambleIncludeLocations; }; ilya-biryukov wrote: > We should have `SourceMgr` at all the proper places now, let's store > `IncludeReferenceMap` directly The idea was to pass a single map around to fill with every reference instead of having separate maps being merged together. Comment at: clangd/ClangdUnit.cpp:281 + IntrusiveRefCntPtr VFS, + IncludeReferenceMap IRM) { ilya-biryukov wrote: > What reference does this `IncludeReferenceMap` contain? Includes from the > preamble? This should contain every reference available for one file. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38639 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38639: [clangd] #include statements support for Open definition
Nebiroth updated this revision to Diff 127617. Nebiroth added a comment. Removed some useless inclusions Removed superfluous check when inserting data in map Moved addition to DeclarationLocations in finish() outside of DeclMacrosFinder Merged with revision 321087 (moved findDefinitions and findDocumentHighlights Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38639 Files: clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/CodeComplete.cpp clangd/Protocol.h clangd/XRefs.cpp unittests/clangd/ClangdTests.cpp Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -7,7 +7,6 @@ // //===--===// -#include "ClangdLSPServer.h" #include "ClangdServer.h" #include "Context.h" #include "TestFS.h" @@ -751,6 +750,75 @@ EXPECT_FALSE(PathResult.hasValue()); } +TEST_F(ClangdVFSTest, CheckDefinitionIncludes) { + MockFSProvider FS; + ErrorCheckingDiagConsumer DiagConsumer; + MockCompilationDatabase CDB; + + ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), + /*StorePreamblesInMemory=*/true, + EmptyLogger::getInstance()); + + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + const auto SourceContents = R"cpp( + #include "foo.h" + #include "invalid.h" + int b = a; + // test + int foo; + #include "foo.h" + )cpp"; + FS.Files[FooCpp] = SourceContents; + auto FooH = getVirtualTestFilePath("foo.h"); + const auto HeaderContents = "int a;"; + + FS.Files[FooCpp] = SourceContents; + FS.Files[FooH] = HeaderContents; + + Server.addDocument(FooH, HeaderContents); + Server.addDocument(FooCpp, SourceContents); + + Position P = Position{1, 11}; + + auto ExpectedLocations = Server.findDefinitions(FooCpp, P); + ASSERT_TRUE(!!ExpectedLocations); + std::vector Locations = ExpectedLocations->Value; + EXPECT_TRUE(!Locations.empty()); + std::string s("file:///"); + std::string check = Locations[0].uri.uri; + check = check.erase(0, s.size() - 1); + check = check.substr(0, check.size()); + ASSERT_EQ(check, FooH); + ASSERT_EQ(Locations[0].range.start.line, 0); + ASSERT_EQ(Locations[0].range.start.character, 0); + ASSERT_EQ(Locations[0].range.end.line, 0); + ASSERT_EQ(Locations[0].range.end.character, 0); + + // Test ctrl-clicking on the #include part on the statement + Position P2 = Position{1, 3}; + + ExpectedLocations = Server.findDefinitions(FooCpp, P2); + ASSERT_TRUE(!!ExpectedLocations); + Locations = ExpectedLocations->Value; + EXPECT_TRUE(!Locations.empty()); + + // Test invalid include + Position P3 = Position{2, 11}; + + ExpectedLocations = Server.findDefinitions(FooCpp, P3); + ASSERT_TRUE(!!ExpectedLocations); + Locations = ExpectedLocations->Value; + EXPECT_TRUE(Locations.empty()); + + // Test include outside of Preamble + Position P4 = Position{6, 5}; + + ExpectedLocations = Server.findDefinitions(FooCpp, P4); + ASSERT_TRUE(!!ExpectedLocations); + Locations = ExpectedLocations->Value; + EXPECT_TRUE(!Locations.empty()); +} + TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) { class NoConcurrentAccessDiagConsumer : public DiagnosticsConsumer { public: Index: clangd/XRefs.cpp === --- clangd/XRefs.cpp +++ clangd/XRefs.cpp @@ -18,6 +18,7 @@ class DeclarationAndMacrosFinder : public index::IndexDataConsumer { std::vector Decls; std::vector MacroInfos; + std::vector DeclarationLocations; const SourceLocation &SearchedLocation; const ASTContext &AST; Preprocessor &PP; @@ -37,14 +38,26 @@ return std::move(Decls); } + std::vector takeLocations() { +// Don't keep the same location multiple times. +// This can happen when nodes in the AST are visited twice. +std::sort(DeclarationLocations.begin(), DeclarationLocations.end()); +auto Last = +std::unique(DeclarationLocations.begin(), DeclarationLocations.end()); +DeclarationLocations.erase(Last, DeclarationLocations.end()); +return std::move(DeclarationLocations); + } + std::vector takeMacroInfos() { // Don't keep the same Macro info multiple times. std::sort(MacroInfos.begin(), MacroInfos.end()); auto Last = std::unique(MacroInfos.begin(), MacroInfos.end()); MacroInfos.erase(Last, MacroInfos.end()); return std::move(MacroInfos); } + const SourceLocation &getSearchedLocation() { return SearchedLocation; }; + bool handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles, ArrayRef Relations, FileID FID, @@ -62,6 +75,25 @@ SourceMgr.getFileID(SearchedLocation) == FID; } + void addDeclarationLocation(const SourceRange &ValSourceRange) { +const SourceManager &SourceMgr = AST.getSourceManager(); +const LangOptions &LangOpts = AST.getLangOpts(); +Sour
[PATCH] D41365: [clang] Add BeforeExecute method to PrecompiledPreamble
Nebiroth updated this revision to Diff 127619. Nebiroth marked 2 inline comments as done. Nebiroth added a comment. Modified comment Changed where BeforeExecute is called Repository: rC Clang https://reviews.llvm.org/D41365 Files: include/clang/Frontend/PrecompiledPreamble.h lib/Frontend/PrecompiledPreamble.cpp Index: lib/Frontend/PrecompiledPreamble.cpp === --- lib/Frontend/PrecompiledPreamble.cpp +++ lib/Frontend/PrecompiledPreamble.cpp @@ -348,6 +348,7 @@ std::unique_ptr Act; Act.reset(new PrecompilePreambleAction( StoreInMemory ? &Storage.asMemory().Data : nullptr, Callbacks)); + Callbacks.BeforeExecute(*Clang); if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) return BuildPreambleError::BeginSourceFileFailed; @@ -704,6 +705,7 @@ } } +void PreambleCallbacks::BeforeExecute(CompilerInstance &CI) {} void PreambleCallbacks::AfterExecute(CompilerInstance &CI) {} void PreambleCallbacks::AfterPCHEmitted(ASTWriter &Writer) {} void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {} Index: include/clang/Frontend/PrecompiledPreamble.h === --- include/clang/Frontend/PrecompiledPreamble.h +++ include/clang/Frontend/PrecompiledPreamble.h @@ -244,6 +244,9 @@ public: virtual ~PreambleCallbacks() = default; + /// Can be used to store references to various CompilerInstance fields + /// (e.g. SourceManager) that may be interesting to the consumers of other callbacks. + virtual void BeforeExecute(CompilerInstance &CI); /// Called after FrontendAction::Execute(), but before /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of /// various CompilerInstance fields before they are destroyed. Index: lib/Frontend/PrecompiledPreamble.cpp === --- lib/Frontend/PrecompiledPreamble.cpp +++ lib/Frontend/PrecompiledPreamble.cpp @@ -348,6 +348,7 @@ std::unique_ptr Act; Act.reset(new PrecompilePreambleAction( StoreInMemory ? &Storage.asMemory().Data : nullptr, Callbacks)); + Callbacks.BeforeExecute(*Clang); if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) return BuildPreambleError::BeginSourceFileFailed; @@ -704,6 +705,7 @@ } } +void PreambleCallbacks::BeforeExecute(CompilerInstance &CI) {} void PreambleCallbacks::AfterExecute(CompilerInstance &CI) {} void PreambleCallbacks::AfterPCHEmitted(ASTWriter &Writer) {} void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {} Index: include/clang/Frontend/PrecompiledPreamble.h === --- include/clang/Frontend/PrecompiledPreamble.h +++ include/clang/Frontend/PrecompiledPreamble.h @@ -244,6 +244,9 @@ public: virtual ~PreambleCallbacks() = default; + /// Can be used to store references to various CompilerInstance fields + /// (e.g. SourceManager) that may be interesting to the consumers of other callbacks. + virtual void BeforeExecute(CompilerInstance &CI); /// Called after FrontendAction::Execute(), but before /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of /// various CompilerInstance fields before they are destroyed. ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41365: [clang] Add BeforeExecute method to PrecompiledPreamble
Nebiroth updated this revision to Diff 127715. Nebiroth added a comment. Updated BeforeExecute comment Repository: rC Clang https://reviews.llvm.org/D41365 Files: include/clang/Frontend/PrecompiledPreamble.h lib/Frontend/PrecompiledPreamble.cpp Index: lib/Frontend/PrecompiledPreamble.cpp === --- lib/Frontend/PrecompiledPreamble.cpp +++ lib/Frontend/PrecompiledPreamble.cpp @@ -348,6 +348,7 @@ std::unique_ptr Act; Act.reset(new PrecompilePreambleAction( StoreInMemory ? &Storage.asMemory().Data : nullptr, Callbacks)); + Callbacks.BeforeExecute(*Clang); if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) return BuildPreambleError::BeginSourceFileFailed; @@ -704,6 +705,7 @@ } } +void PreambleCallbacks::BeforeExecute(CompilerInstance &CI) {} void PreambleCallbacks::AfterExecute(CompilerInstance &CI) {} void PreambleCallbacks::AfterPCHEmitted(ASTWriter &Writer) {} void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {} Index: include/clang/Frontend/PrecompiledPreamble.h === --- include/clang/Frontend/PrecompiledPreamble.h +++ include/clang/Frontend/PrecompiledPreamble.h @@ -244,6 +244,10 @@ public: virtual ~PreambleCallbacks() = default; + /// Called before FrontendAction::BeginSourceFile. + /// Can be used to store references to various CompilerInstance fields + /// (e.g. SourceManager) that may be interesting to the consumers of other callbacks. + virtual void BeforeExecute(CompilerInstance &CI); /// Called after FrontendAction::Execute(), but before /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of /// various CompilerInstance fields before they are destroyed. Index: lib/Frontend/PrecompiledPreamble.cpp === --- lib/Frontend/PrecompiledPreamble.cpp +++ lib/Frontend/PrecompiledPreamble.cpp @@ -348,6 +348,7 @@ std::unique_ptr Act; Act.reset(new PrecompilePreambleAction( StoreInMemory ? &Storage.asMemory().Data : nullptr, Callbacks)); + Callbacks.BeforeExecute(*Clang); if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) return BuildPreambleError::BeginSourceFileFailed; @@ -704,6 +705,7 @@ } } +void PreambleCallbacks::BeforeExecute(CompilerInstance &CI) {} void PreambleCallbacks::AfterExecute(CompilerInstance &CI) {} void PreambleCallbacks::AfterPCHEmitted(ASTWriter &Writer) {} void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {} Index: include/clang/Frontend/PrecompiledPreamble.h === --- include/clang/Frontend/PrecompiledPreamble.h +++ include/clang/Frontend/PrecompiledPreamble.h @@ -244,6 +244,10 @@ public: virtual ~PreambleCallbacks() = default; + /// Called before FrontendAction::BeginSourceFile. + /// Can be used to store references to various CompilerInstance fields + /// (e.g. SourceManager) that may be interesting to the consumers of other callbacks. + virtual void BeforeExecute(CompilerInstance &CI); /// Called after FrontendAction::Execute(), but before /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of /// various CompilerInstance fields before they are destroyed. ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41365: [clang] Add BeforeExecute method to PrecompiledPreamble
Nebiroth added a comment. Yes please land this. Repository: rC Clang https://reviews.llvm.org/D41365 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38639: [clangd] #include statements support for Open definition
Nebiroth updated this revision to Diff 127900. Nebiroth marked 11 inline comments as done. Nebiroth added a comment. Minor code cleanup Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38639 Files: clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.h clangd/XRefs.cpp unittests/clangd/ClangdTests.cpp Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -7,7 +7,6 @@ // //===--===// -#include "ClangdLSPServer.h" #include "ClangdServer.h" #include "Context.h" #include "TestFS.h" @@ -751,6 +750,75 @@ EXPECT_FALSE(PathResult.hasValue()); } +TEST_F(ClangdVFSTest, CheckDefinitionIncludes) { + MockFSProvider FS; + ErrorCheckingDiagConsumer DiagConsumer; + MockCompilationDatabase CDB; + + ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), + /*StorePreamblesInMemory=*/true, + EmptyLogger::getInstance()); + + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + const auto SourceContents = R"cpp( + #include "foo.h" + #include "invalid.h" + int b = a; + // test + int foo; + #include "foo.h" + )cpp"; + FS.Files[FooCpp] = SourceContents; + auto FooH = getVirtualTestFilePath("foo.h"); + const auto HeaderContents = "int a;"; + + FS.Files[FooCpp] = SourceContents; + FS.Files[FooH] = HeaderContents; + + Server.addDocument(FooH, HeaderContents); + Server.addDocument(FooCpp, SourceContents); + + Position P = Position{1, 11}; + + auto ExpectedLocations = Server.findDefinitions(FooCpp, P); + ASSERT_TRUE(!!ExpectedLocations); + std::vector Locations = ExpectedLocations->Value; + EXPECT_TRUE(!Locations.empty()); + std::string s("file:///"); + std::string check = Locations[0].uri.uri; + check = check.erase(0, s.size() - 1); + check = check.substr(0, check.size()); + ASSERT_EQ(check, FooH); + ASSERT_EQ(Locations[0].range.start.line, 0); + ASSERT_EQ(Locations[0].range.start.character, 0); + ASSERT_EQ(Locations[0].range.end.line, 0); + ASSERT_EQ(Locations[0].range.end.character, 0); + + // Test ctrl-clicking on the #include part on the statement + Position P2 = Position{1, 3}; + + ExpectedLocations = Server.findDefinitions(FooCpp, P2); + ASSERT_TRUE(!!ExpectedLocations); + Locations = ExpectedLocations->Value; + EXPECT_TRUE(!Locations.empty()); + + // Test invalid include + Position P3 = Position{2, 11}; + + ExpectedLocations = Server.findDefinitions(FooCpp, P3); + ASSERT_TRUE(!!ExpectedLocations); + Locations = ExpectedLocations->Value; + EXPECT_TRUE(Locations.empty()); + + // Test include outside of Preamble + Position P4 = Position{6, 5}; + + ExpectedLocations = Server.findDefinitions(FooCpp, P4); + ASSERT_TRUE(!!ExpectedLocations); + Locations = ExpectedLocations->Value; + EXPECT_TRUE(!Locations.empty()); +} + TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) { class NoConcurrentAccessDiagConsumer : public DiagnosticsConsumer { public: Index: clangd/XRefs.cpp === --- clangd/XRefs.cpp +++ clangd/XRefs.cpp @@ -18,6 +18,7 @@ class DeclarationAndMacrosFinder : public index::IndexDataConsumer { std::vector Decls; std::vector MacroInfos; + std::vector DeclarationLocations; const SourceLocation &SearchedLocation; const ASTContext &AST; Preprocessor &PP; @@ -37,14 +38,26 @@ return std::move(Decls); } + std::vector takeLocations() { +// Don't keep the same location multiple times. +// This can happen when nodes in the AST are visited twice. +std::sort(DeclarationLocations.begin(), DeclarationLocations.end()); +auto Last = +std::unique(DeclarationLocations.begin(), DeclarationLocations.end()); +DeclarationLocations.erase(Last, DeclarationLocations.end()); +return std::move(DeclarationLocations); + } + std::vector takeMacroInfos() { // Don't keep the same Macro info multiple times. std::sort(MacroInfos.begin(), MacroInfos.end()); auto Last = std::unique(MacroInfos.begin(), MacroInfos.end()); MacroInfos.erase(Last, MacroInfos.end()); return std::move(MacroInfos); } + const SourceLocation &getSearchedLocation() { return SearchedLocation; }; + bool handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles, ArrayRef Relations, FileID FID, @@ -62,6 +75,25 @@ SourceMgr.getFileID(SearchedLocation) == FID; } + void addDeclarationLocation(const SourceRange &ValSourceRange) { +const SourceManager &SourceMgr = AST.getSourceManager(); +const LangOptions &LangOpts = AST.getLangOpts(); +SourceLocation LocStart = ValSourceRange.getBegin(); +SourceLocation LocEnd = Lexer::getLocForEndOfToken(ValSourceRange.getEnd(), + 0, SourceMgr, LangOpts); +
[PATCH] D37150: [clangd] Command line arg to specify compile_commands.json path
Nebiroth created this revision. Adds compileCommands command line argument to specify an absolute path directly to the requested compile_commands.json for flags. https://reviews.llvm.org/D37150 Files: clangd/GlobalCompilationDatabase.cpp Index: clangd/GlobalCompilationDatabase.cpp === --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -11,6 +11,24 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + +static cl::opt CompileCommands("compileCommands", + cl::desc("Start with absolute path to compile_commands.json")); +} namespace clang { namespace clangd { @@ -36,6 +54,8 @@ /*Output=*/""); } + + std::vector DirectoryBasedGlobalCompilationDatabase::getCompileCommands(PathRef File) { std::vector Commands; @@ -64,35 +84,62 @@ tooling::CompilationDatabase * DirectoryBasedGlobalCompilationDatabase::getCompilationDatabase(PathRef File) { std::lock_guard Lock(Mutex); - namespace path = llvm::sys::path; + // if --compileCommands arg was invoked, check value and override default path + std::size_t found = CompileCommands.find_first_of("/"); + std::string TempString = CompileCommands; + if (found != std::string::npos) + { + File = TempString; + } + + std::string Error; + bool badPath = false; + File = path::parent_path(File); + auto CachedIt = CompilationDatabases.find(File); + if (CachedIt != CompilationDatabases.end()) +return CachedIt->second.get(); + auto CDB = tooling::CompilationDatabase::loadFromDirectory(File, Error); + if (!CDB) { + if (!Error.empty()) { +badPath = true; + } + } assert((path::is_absolute(File, path::Style::posix) || path::is_absolute(File, path::Style::windows)) && "path must be absolute"); - for (auto Path = path::parent_path(File); !Path.empty(); + if (badPath) + { +for (auto Path = path::parent_path(File); !Path.empty(); Path = path::parent_path(Path)) { auto CachedIt = CompilationDatabases.find(Path); if (CachedIt != CompilationDatabases.end()) return CachedIt->second.get(); -std::string Error; auto CDB = tooling::CompilationDatabase::loadFromDirectory(Path, Error); if (!CDB) { if (!Error.empty()) { // FIXME(ibiryukov): logging // Output.log("Error when trying to load compilation database from " + //Twine(Path) + ": " + Twine(Error) + "\n"); - } - continue; + } } // FIXME(ibiryukov): Invalidate cached compilation databases on changes auto result = CDB.get(); CompilationDatabases.insert(std::make_pair(Path, std::move(CDB))); return result; +} } + else + { +auto result = CDB.get(); +CompilationDatabases.insert(std::make_pair(File, std::move(CDB))); +return result; + } + // FIXME(ibiryukov): logging // Output.log("Failed to find compilation database for " + Twine(File) + ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D37150: [clangd] Command line arg to specify compile_commands.json path
Nebiroth updated this revision to Diff 113895. Nebiroth added a comment. Added function to avoid code reuse and extra nesting. https://reviews.llvm.org/D37150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/tool/ClangdMain.cpp test/clangd/hover.test Index: test/clangd/hover.test === --- /dev/null +++ test/clangd/hover.test @@ -0,0 +1,26 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 172 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"int main() {\nint a;\na;\n}\n"}}} + +Content-Length: 143 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":0,"character":5}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":{"contents": {"language": "C++", "value": "int main() {\nint a;\na;\n}"}, "range": {"start": {"line": 0, "character": 0}, "end": {"line": 3, "character": 1 + +Content-Length: 143 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":1,"character":5}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":{"contents": {"language": "C++", "value": "int a"}, "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 5 + +Content-Length: 44 + +{"jsonrpc":"2.0","id":3,"method":"shutdown"} Index: clangd/tool/ClangdMain.cpp === --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -12,6 +12,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Program.h" +#include "llvm/Support/Path.h" #include #include @@ -25,16 +26,29 @@ llvm::cl::desc("parse on main thread"), llvm::cl::init(false), llvm::cl::Hidden); +static llvm::cl::opt +CompileCommands("compile-commands-dir", + llvm::cl::desc("Specify a path to look for compile_commands.json. If path is invalid, clangd will look in the current directory and parent paths of each source file.")); + + int main(int argc, char *argv[]) { llvm::cl::ParseCommandLineOptions(argc, argv, "clangd"); llvm::raw_ostream &Outs = llvm::outs(); llvm::raw_ostream &Logs = llvm::errs(); JSONOutput Out(Outs, Logs); + // If --compileCommands arg was invoked, check value and override default path. + namespace path = llvm::sys::path; + if (!llvm::sys::path::is_absolute(CompileCommands) || CompileCommands.empty()) +Logs << "Path specified for compilation database must be absolute. Verifying current folder instead."; + + if (!llvm::sys::fs::exists(CompileCommands)) +Logs << "File does not exist. Verifying current folder instead."; + // Change stdin to binary to not lose \r\n on windows. llvm::sys::ChangeStdinToBinary(); - ClangdLSPServer LSPServer(Out, RunSynchronously); + ClangdLSPServer LSPServer(Out, RunSynchronously, CompileCommands); LSPServer.run(std::cin); } Index: clangd/GlobalCompilationDatabase.h === --- clangd/GlobalCompilationDatabase.h +++ clangd/GlobalCompilationDatabase.h @@ -33,8 +33,9 @@ public: virtual ~GlobalCompilationDatabase() = default; - virtual std::vector + virtual std::vector getCompileCommands(PathRef File) = 0; + std::string CompileCommands; /// FIXME(ibiryukov): add facilities to track changes to compilation flags of /// existing targets. @@ -49,6 +50,7 @@ getCompileCommands(PathRef File) override; void setExtraFlagsForFile(PathRef File, std::vector ExtraFlags); + tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File, std::string &Error); private: tooling::CompilationDatabase *getCompilationDatabase(PathRef File); Index: clangd/GlobalCompilationDatabase.cpp === --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -11,6 +11,16 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/Timer.h" +#in
[PATCH] D36150: [clangd] LSP extension to switch between source/header file
Nebiroth updated this revision to Diff 114046. Nebiroth added a comment. Refactored switchSourceHeader function help from ilya Added helper function to check for uppercase on current file. https://reviews.llvm.org/D36150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/hover.test Index: test/clangd/hover.test === --- /dev/null +++ test/clangd/hover.test @@ -0,0 +1,26 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 172 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"int main() {\nint a;\na;\n}\n"}}} + +Content-Length: 143 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":0,"character":5}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":{"contents": {"language": "C++", "value": "int main() {\nint a;\na;\n}"}, "range": {"start": {"line": 0, "character": 0}, "end": {"line": 3, "character": 1 + +Content-Length: 143 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":1,"character":5}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":{"contents": {"language": "C++", "value": "int a"}, "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 5 + +Content-Length: 44 + +{"jsonrpc":"2.0","id":3,"method":"shutdown"} Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -48,6 +48,8 @@ JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; + virtual void onSwitchSourceHeader(TextDocumentIdentifier Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,23 @@ ProtocolCallbacks &Callbacks; }; +struct SwitchSourceHeaderHandler : Handler { + SwitchSourceHeaderHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentIdentifier::parse(Params); +if (!TDPP) { + return; +} + +Callbacks.onSwitchSourceHeader(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -239,4 +256,7 @@ llvm::make_unique(Out, Callbacks)); Dispatcher.registerHandler("textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/switchSourceHeader", + llvm::make_unique(Out, Callbacks)); } Index: clangd/ClangdServer.h === --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -182,6 +182,12 @@ /// Get definition of symbol at a specified \p Line and \p Column in \p File. Tagged> findDefinitions(PathRef File, Position Pos); + /// If an extension hasn't been found in the lowercase array, try with uppercase. + bool checkUpperCaseExtensions(StringRef BaseArray[], int ArraySize, StringRef PathExt); + + /// Helper function that returns a path to the corresponding source file when given a header file and vice versa. + llvm::Optional switchSourceHeader(PathRef Path); + /// Run formatting for \p Rng inside \p File. std::vector formatRange(PathRef File, Range Rng); /// Run formatting for the whole \p File. Index: clangd/ClangdServer.cpp === --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -15,9 +15,11 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include +using namespace llvm; using namespace clang; using namespace clang::clangd; @@ -286,3 +288,84 @@ }); return make_tagged(std::move(Result), TaggedFS.Tag); } + + +bool ClangdServer::checkUpperCaseExtensions(StringRef BaseArray[], int ArraySize, StringRef PathExt) +{ + std::string UpperExtensions[A
[PATCH] D36150: [clangd] LSP extension to switch between source/header file
Nebiroth updated this revision to Diff 114048. Nebiroth added a comment. Remove unintentional file addition Updating D36150: [clangd] LSP extension to switch between source/header file ll# https://reviews.llvm.org/D36150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -48,6 +48,8 @@ JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; + virtual void onSwitchSourceHeader(TextDocumentIdentifier Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,23 @@ ProtocolCallbacks &Callbacks; }; +struct SwitchSourceHeaderHandler : Handler { + SwitchSourceHeaderHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentIdentifier::parse(Params); +if (!TDPP) { + return; +} + +Callbacks.onSwitchSourceHeader(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -239,4 +256,7 @@ llvm::make_unique(Out, Callbacks)); Dispatcher.registerHandler("textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/switchSourceHeader", + llvm::make_unique(Out, Callbacks)); } Index: clangd/ClangdServer.h === --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -182,6 +182,12 @@ /// Get definition of symbol at a specified \p Line and \p Column in \p File. Tagged> findDefinitions(PathRef File, Position Pos); + /// If an extension hasn't been found in the lowercase array, try with uppercase. + bool checkUpperCaseExtensions(StringRef BaseArray[], int ArraySize, StringRef PathExt); + + /// Helper function that returns a path to the corresponding source file when given a header file and vice versa. + llvm::Optional switchSourceHeader(PathRef Path); + /// Run formatting for \p Rng inside \p File. std::vector formatRange(PathRef File, Range Rng); /// Run formatting for the whole \p File. Index: clangd/ClangdServer.cpp === --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -15,9 +15,11 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include +using namespace llvm; using namespace clang; using namespace clang::clangd; @@ -286,3 +288,84 @@ }); return make_tagged(std::move(Result), TaggedFS.Tag); } + + +bool ClangdServer::checkUpperCaseExtensions(StringRef BaseArray[], int ArraySize, StringRef PathExt) +{ + std::string UpperExtensions[ArraySize]; + for(int i = 0; i < ArraySize; i++) + { +UpperExtensions[i] = BaseArray[i]; + } + // Uppercase the whole array + for (std::string & s : UpperExtensions) + std::transform(s.begin(), s.end(), s.begin(), + [](unsigned char c) { return std::toupper(c); }); + + bool isUpperCase = false; + // Iterator such as std::begin won't work here so we use a standard loop + for(int i = 0; i < ArraySize; i++) + { +if (UpperExtensions[i] == PathExt.str()) +{ + isUpperCase = true; +} + } + return isUpperCase; +} + +llvm::Optional ClangdServer::switchSourceHeader(PathRef Path) { + + StringRef SourceExtensions[] = {".cpp", ".c", ".cc", ".cxx", ".c++", ".m", ".mm"}; + StringRef HeaderExtensions[] = {".h", ".hh", ".hpp", ".hxx", ".inc"}; + + StringRef PathExt = llvm::sys::path::extension(Path); + + // Lookup in a list of known extensions. + auto SourceIter = std::find(std::begin(SourceExtensions), std::end(SourceExtensions), PathExt); + bool IsSource = SourceIter != std::end(SourceExtensions); + + if (!IsSource) + { +IsSource = checkUpperCaseExtensions(SourceExtensions, llvm::array_lengthof(SourceExtensions), PathExt); + } + + auto HeaderIter = std::find(std::begin(HeaderExtensions), std::end(HeaderExtensions), PathExt); + bool IsHeader = HeaderIter != std::end(HeaderExtensions); + + if (!IsHeader) + { +IsHeader = checkUpperCaseExtensions(Heade
[PATCH] D36150: [clangd] LSP extension to switch between source/header file
Nebiroth updated this revision to Diff 114054. Nebiroth added a comment. Some more code cleanup. https://reviews.llvm.org/D36150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -48,6 +48,8 @@ JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; + virtual void onSwitchSourceHeader(TextDocumentIdentifier Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,23 @@ ProtocolCallbacks &Callbacks; }; +struct SwitchSourceHeaderHandler : Handler { + SwitchSourceHeaderHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentIdentifier::parse(Params); +if (!TDPP) { + return; +} + +Callbacks.onSwitchSourceHeader(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -239,4 +256,7 @@ llvm::make_unique(Out, Callbacks)); Dispatcher.registerHandler("textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/switchSourceHeader", + llvm::make_unique(Out, Callbacks)); } Index: clangd/ClangdServer.h === --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -182,6 +182,12 @@ /// Get definition of symbol at a specified \p Line and \p Column in \p File. Tagged> findDefinitions(PathRef File, Position Pos); + /// If an extension hasn't been found in the lowercase array, try with uppercase. + bool checkUpperCaseExtensions(StringRef BaseArray[], int ArraySize, StringRef PathExt); + + /// Helper function that returns a path to the corresponding source file when given a header file and vice versa. + llvm::Optional switchSourceHeader(PathRef Path); + /// Run formatting for \p Rng inside \p File. std::vector formatRange(PathRef File, Range Rng); /// Run formatting for the whole \p File. Index: clangd/ClangdServer.cpp === --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -15,9 +15,11 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include +using namespace llvm; using namespace clang; using namespace clang::clangd; @@ -286,3 +288,89 @@ }); return make_tagged(std::move(Result), TaggedFS.Tag); } + + +bool ClangdServer::checkUpperCaseExtensions(StringRef BaseArray[], int ArraySize, StringRef PathExt) +{ + std::string UpperExtensions[ArraySize]; + for(int i = 0; i < ArraySize; i++) + { +UpperExtensions[i] = BaseArray[i]; + } + // Uppercase the whole array + for (std::string & s : UpperExtensions) + std::transform(s.begin(), s.end(), s.begin(), + [](unsigned char c) { return std::toupper(c); }); + + bool isUpperCase = false; + // Iterator such as std::begin won't work here so we use a standard loop + for(int i = 0; i < ArraySize; i++) + { +if (UpperExtensions[i] == PathExt.str()) +{ + isUpperCase = true; +} + } + return isUpperCase; +} + +llvm::Optional ClangdServer::switchSourceHeader(PathRef Path) { + + StringRef SourceExtensions[] = {".cpp", ".c", ".cc", ".cxx", ".c++", ".m", ".mm"}; + StringRef HeaderExtensions[] = {".h", ".hh", ".hpp", ".hxx", ".inc"}; + + StringRef PathExt = llvm::sys::path::extension(Path); + + // Lookup in a list of known extensions. + auto SourceIter = std::find(std::begin(SourceExtensions), std::end(SourceExtensions), PathExt); + bool IsSource = SourceIter != std::end(SourceExtensions); + + if (!IsSource) + { +IsSource = checkUpperCaseExtensions(SourceExtensions, llvm::array_lengthof(SourceExtensions), PathExt); + } + + auto HeaderIter = std::find(std::begin(HeaderExtensions), std::end(HeaderExtensions), PathExt); + bool IsHeader = HeaderIter != std::end(HeaderExtensions); + + if (!IsHeader) + { +IsHeader = checkUpperCaseExtensions(HeaderExtensions, llvm::array_lengthof(HeaderExtensions), PathExt); + } + + // We can only switch between extensions known extensions. + if (!IsSource && !IsHeader) +ret
[PATCH] D37150: [clangd] Command line arg to specify compile_commands.json path
Nebiroth updated this revision to Diff 114199. Nebiroth marked 7 inline comments as done. Nebiroth added a comment. Modified CompileCommandsDir to only look in the specified path if the value is set. Moved CompileCommandsDir field to DirectoryBasedGlobalCompilationDatabase class. Minor refactoring. https://reviews.llvm.org/D37150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/tool/ClangdMain.cpp Index: clangd/tool/ClangdMain.cpp === --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -12,7 +12,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Program.h" - +#include "llvm/Support/Path.h" #include #include #include @@ -25,16 +25,36 @@ llvm::cl::desc("parse on main thread"), llvm::cl::init(false), llvm::cl::Hidden); +static llvm::cl::opt +CompileCommandsDir("compile-commands-dir", + llvm::cl::desc("Specify a path to look for compile_commands.json. If path is invalid, clangd will look in the current directory and parent paths of each source file.")); + + int main(int argc, char *argv[]) { llvm::cl::ParseCommandLineOptions(argc, argv, "clangd"); llvm::raw_ostream &Outs = llvm::outs(); llvm::raw_ostream &Logs = llvm::errs(); JSONOutput Out(Outs, Logs); + // If --CompileCommandsDir arg was invoked, check value and override default path. + namespace path = llvm::sys::path; + + if (!llvm::sys::path::is_absolute(CompileCommandsDir)) + { +Logs << "Path specified by --compile-commands-dir must be an absolute path. The argument will be ignored.\n"; +CompileCommandsDir = ""; + } + + if (!llvm::sys::fs::exists(CompileCommandsDir)) + { +Logs << "File does not exist. The argument will be ignored.\n"; +CompileCommandsDir = ""; + } + // Change stdin to binary to not lose \r\n on windows. llvm::sys::ChangeStdinToBinary(); - ClangdLSPServer LSPServer(Out, RunSynchronously); + ClangdLSPServer LSPServer(Out, RunSynchronously, CompileCommandsDir); LSPServer.run(std::cin); } Index: clangd/GlobalCompilationDatabase.h === --- clangd/GlobalCompilationDatabase.h +++ clangd/GlobalCompilationDatabase.h @@ -33,9 +33,9 @@ public: virtual ~GlobalCompilationDatabase() = default; - virtual std::vector + virtual std::vector getCompileCommands(PathRef File) = 0; - + /// FIXME(ibiryukov): add facilities to track changes to compilation flags of /// existing targets. }; @@ -45,13 +45,16 @@ class DirectoryBasedGlobalCompilationDatabase : public GlobalCompilationDatabase { public: + DirectoryBasedGlobalCompilationDatabase(Path NewCompileCommandsDir): CompileCommandsDir(NewCompileCommandsDir){} std::vector getCompileCommands(PathRef File) override; void setExtraFlagsForFile(PathRef File, std::vector ExtraFlags); + tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File, std::string &Error); private: tooling::CompilationDatabase *getCompilationDatabase(PathRef File); + Path CompileCommandsDir; std::mutex Mutex; /// Caches compilation databases loaded from directories(keys are Index: clangd/GlobalCompilationDatabase.cpp === --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -61,37 +61,47 @@ ExtraFlagsForFile[File] = std::move(ExtraFlags); } +tooling::CompilationDatabase * DirectoryBasedGlobalCompilationDatabase::tryLoadDatabaseFromPath(PathRef File, std::string &Error) +{ + auto CachedIt = CompilationDatabases.find(File); + if (CachedIt != CompilationDatabases.end()) +return (CachedIt->second.get()); + auto CDB = tooling::CompilationDatabase::loadFromDirectory(File, Error); + if (CDB && Error.empty()) + { +auto result = CDB.get(); +CompilationDatabases.insert(std::make_pair(File, std::move(CDB))); +return result; + } + return nullptr; +} + tooling::CompilationDatabase * DirectoryBasedGlobalCompilationDatabase::getCompilationDatabase(PathRef File) { std::lock_guard Lock(Mutex); - + namespace path = llvm::sys::path; - - assert((path::is_absolute(File, path::Style::posix) || - path::is_absolute(File, path::Style::windows)) && - "path must be absolute"); + std::string Error; + if (!CompileCommandsDir.empty()) { +File = CompileCommandsDir; +File = path::parent_path(File); +auto CDB = tryLoadDatabaseFromPath(File, Error); + +if (CDB && Error.empty()) + return CDB; +else + return nullptr; + } for (auto Path = path::parent_path(File); !Path.empty(); - Path = path::parent_path(Path)) { - -auto CachedIt = Compila
[PATCH] D37150: [clangd] Command line arg to specify compile_commands.json path
Nebiroth updated this revision to Diff 114371. Nebiroth marked 10 inline comments as done. Nebiroth added a comment. Ran clang-format on modified files. More minor refactoring. https://reviews.llvm.org/D37150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/tool/ClangdMain.cpp Index: clangd/tool/ClangdMain.cpp === --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -11,8 +11,8 @@ #include "JSONRPCDispatcher.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Program.h" - #include #include #include @@ -25,16 +25,43 @@ llvm::cl::desc("parse on main thread"), llvm::cl::init(false), llvm::cl::Hidden); +static llvm::cl::opt CompileCommandsDir( +"compile-commands-dir", +llvm::cl::desc("Specify a path to look for compile_commands.json. If path " + "is invalid, clangd will look in the current directory and " + "parent paths of each source file.")); + int main(int argc, char *argv[]) { llvm::cl::ParseCommandLineOptions(argc, argv, "clangd"); llvm::raw_ostream &Outs = llvm::outs(); llvm::raw_ostream &Logs = llvm::errs(); JSONOutput Out(Outs, Logs); + // If --compile-commands-dir arg was invoked, check value and override default + // path. + namespace path = llvm::sys::path; + + if (!llvm::sys::path::is_absolute(CompileCommandsDir)) { +Out.log("Path specified by --compile-commands-dir must be an absolute " +"path. The argument will be ignored.\n"); +CompileCommandsDir = ""; + } + + if (!llvm::sys::fs::exists(CompileCommandsDir)) { +Out.log("Path specified by --compile-commands-dir. The argument will be " +"ignored.\n"); +CompileCommandsDir = ""; + } + llvm::Optional CompileCommandsDirPath; + // Change stdin to binary to not lose \r\n on windows. llvm::sys::ChangeStdinToBinary(); + if (CompileCommandsDir.empty()) +CompileCommandsDirPath = llvm::None; + else +CompileCommandsDirPath = CompileCommandsDir; - ClangdLSPServer LSPServer(Out, RunSynchronously); + ClangdLSPServer LSPServer(Out, RunSynchronously, CompileCommandsDirPath); LSPServer.run(std::cin); } Index: clangd/GlobalCompilationDatabase.h === --- clangd/GlobalCompilationDatabase.h +++ clangd/GlobalCompilationDatabase.h @@ -45,13 +45,18 @@ class DirectoryBasedGlobalCompilationDatabase : public GlobalCompilationDatabase { public: + DirectoryBasedGlobalCompilationDatabase( + llvm::Optional NewCompileCommandsDir) + : CompileCommandsDir(NewCompileCommandsDir.getValue()) {} std::vector getCompileCommands(PathRef File) override; void setExtraFlagsForFile(PathRef File, std::vector ExtraFlags); private: tooling::CompilationDatabase *getCompilationDatabase(PathRef File); + Path CompileCommandsDir; + tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File); std::mutex Mutex; /// Caches compilation databases loaded from directories(keys are Index: clangd/GlobalCompilationDatabase.cpp === --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -62,43 +62,55 @@ } tooling::CompilationDatabase * -DirectoryBasedGlobalCompilationDatabase::getCompilationDatabase(PathRef File) { - std::lock_guard Lock(Mutex); - +DirectoryBasedGlobalCompilationDatabase::tryLoadDatabaseFromPath(PathRef File) { namespace path = llvm::sys::path; + auto CachedIt = CompilationDatabases.find(File); + std::string Error = ""; assert((path::is_absolute(File, path::Style::posix) || path::is_absolute(File, path::Style::windows)) && "path must be absolute"); - for (auto Path = path::parent_path(File); !Path.empty(); - Path = path::parent_path(Path)) { - -auto CachedIt = CompilationDatabases.find(Path); -if (CachedIt != CompilationDatabases.end()) - return CachedIt->second.get(); -std::string Error; -auto CDB = tooling::CompilationDatabase::loadFromDirectory(Path, Error); -if (!CDB) { - if (!Error.empty()) { -// FIXME(ibiryukov): logging -// Output.log("Error when trying to load compilation database from " + -//Twine(Path) + ": " + Twine(Error) + "\n"); - } - continue; -} + if (CachedIt != CompilationDatabases.end()) +return (CachedIt->second.get()); + auto CDB = tooling::CompilationDatabase::loadFromDirectory(File, Error); + if (CDB && Error.empty()) { +auto result = CDB.get(); +CompilationDatabases.insert(std::make_pair(File, std::move(CDB))); // FIXME(ibiryukov): Invalidate cached compil
[PATCH] D36150: [clangd] LSP extension to switch between source/header file
Nebiroth updated this revision to Diff 114424. Nebiroth marked 7 inline comments as done. Nebiroth added a comment. Ran clang-format on modified files. Minor refactoring. https://reviews.llvm.org/D36150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h clangd/tool/ClangdMain.cpp Index: clangd/tool/ClangdMain.cpp === --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -12,7 +12,6 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Program.h" - #include #include #include Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -47,7 +47,9 @@ virtual void onCompletion(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, -JSONOutput &Out) = 0; +JSONOutput &Out) = 0; + virtual void onSwitchSourceHeader(TextDocumentIdentifier Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,22 @@ ProtocolCallbacks &Callbacks; }; +struct SwitchSourceHeaderHandler : Handler { + SwitchSourceHeaderHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentIdentifier::parse(Params); +if (!TDPP) + return; + +Callbacks.onSwitchSourceHeader(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -237,6 +253,10 @@ Dispatcher.registerHandler( "textDocument/completion", llvm::make_unique(Out, Callbacks)); - Dispatcher.registerHandler("textDocument/definition", + Dispatcher.registerHandler( + "textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/switchSourceHeader", + llvm::make_unique(Out, Callbacks)); } Index: clangd/ClangdServer.h === --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -182,6 +182,9 @@ /// Get definition of symbol at a specified \p Line and \p Column in \p File. Tagged> findDefinitions(PathRef File, Position Pos); + /// Helper function that returns a path to the corresponding source file when given a header file and vice versa. + llvm::Optional switchSourceHeader(PathRef Path); + /// Run formatting for \p Rng inside \p File. std::vector formatRange(PathRef File, Range Rng); /// Run formatting for the whole \p File. Index: clangd/ClangdServer.cpp === --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -15,9 +15,11 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include +using namespace llvm; using namespace clang; using namespace clang::clangd; @@ -273,16 +275,76 @@ return DumpFuture.get(); } -Tagged> -ClangdServer::findDefinitions(PathRef File, Position Pos) { +Tagged> ClangdServer::findDefinitions(PathRef File, +Position Pos) { auto FileContents = DraftMgr.getDraft(File); - assert(FileContents.Draft && "findDefinitions is called for non-added document"); + assert(FileContents.Draft && + "findDefinitions is called for non-added document"); std::vector Result; auto TaggedFS = FSProvider.getTaggedFileSystem(File); - Units.runOnUnit(File, *FileContents.Draft, ResourceDir, CDB, PCHs, - TaggedFS.Value, [&](ClangdUnit &Unit) { -Result = Unit.findDefinitions(Pos); - }); + Units.runOnUnit( + File, *FileContents.Draft, ResourceDir, CDB, PCHs, TaggedFS.Value, + [&](ClangdUnit &Unit) { Result = Unit.findDefinitions(Pos); }); return make_tagged(std::move(Result), TaggedFS.Tag); } + +llvm::Optional ClangdServer::switchSourceHeader(PathRef Path) { + + StringRef SourceExtensions[] = {".cpp", ".c", ".cc", ".cxx", + ".c++", ".m", ".mm"}; + StringRef HeaderExtensions[] = {".h", ".hh", ".hpp", ".hxx", ".inc"}; + + StringRef PathExt = llvm::sys::path::extension(Path); + + // Lookup in
[PATCH] D36150: [clangd] LSP extension to switch between source/header file
Nebiroth marked 5 inline comments as done. Nebiroth added inline comments. Comment at: clangd/ClangdLSPServer.cpp:234 + else +ResultUri = URI::fromFile(""); + ilya-biryukov wrote: > Running `unparse` on an instance created via `URI::fromFile("")` will result > in `"file:///"`. > > Have you considered returning a list of paths as a result from > `switchHeaderSource`? > That way you could capture the "no file matched" case with an empty list. > Later when an implementation will look into index, that would allow to return > multiple source files for a header file, which also happens in some C++ > projects. > > Returning an empty string is also an option we could start with. I think I will start by returning an empty string for now. Returning a list of paths sounds like a good idea once an indexer is implemented, but that would require changing some parts of the code like find_if which returns only the first instance of a match. https://reviews.llvm.org/D36150 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D36150: [clangd] LSP extension to switch between source/header file
Nebiroth updated this revision to Diff 114652. Nebiroth added a comment. Return value when no file is found is now an empty string instead of file:// Minor code style changes and cleanup. Ran clang-format on ClangdServer.h https://reviews.llvm.org/D36150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h clangd/tool/ClangdMain.cpp Index: clangd/tool/ClangdMain.cpp === --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -12,7 +12,6 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Program.h" - #include #include #include Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -47,7 +47,9 @@ virtual void onCompletion(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, -JSONOutput &Out) = 0; +JSONOutput &Out) = 0; + virtual void onSwitchSourceHeader(TextDocumentIdentifier Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,22 @@ ProtocolCallbacks &Callbacks; }; +struct SwitchSourceHeaderHandler : Handler { + SwitchSourceHeaderHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentIdentifier::parse(Params); +if (!TDPP) + return; + +Callbacks.onSwitchSourceHeader(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -237,6 +253,10 @@ Dispatcher.registerHandler( "textDocument/completion", llvm::make_unique(Out, Callbacks)); - Dispatcher.registerHandler("textDocument/definition", + Dispatcher.registerHandler( + "textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/switchSourceHeader", + llvm::make_unique(Out, Callbacks)); } Index: clangd/ClangdServer.h === --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -182,6 +182,10 @@ /// Get definition of symbol at a specified \p Line and \p Column in \p File. Tagged> findDefinitions(PathRef File, Position Pos); + /// Helper function that returns a path to the corresponding source file when + /// given a header file and vice versa. + llvm::Optional switchSourceHeader(PathRef Path); + /// Run formatting for \p Rng inside \p File. std::vector formatRange(PathRef File, Range Rng); /// Run formatting for the whole \p File. Index: clangd/ClangdServer.cpp === --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -15,6 +15,7 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include @@ -273,16 +274,76 @@ return DumpFuture.get(); } -Tagged> -ClangdServer::findDefinitions(PathRef File, Position Pos) { +Tagged> ClangdServer::findDefinitions(PathRef File, +Position Pos) { auto FileContents = DraftMgr.getDraft(File); - assert(FileContents.Draft && "findDefinitions is called for non-added document"); + assert(FileContents.Draft && + "findDefinitions is called for non-added document"); std::vector Result; auto TaggedFS = FSProvider.getTaggedFileSystem(File); - Units.runOnUnit(File, *FileContents.Draft, ResourceDir, CDB, PCHs, - TaggedFS.Value, [&](ClangdUnit &Unit) { -Result = Unit.findDefinitions(Pos); - }); + Units.runOnUnit( + File, *FileContents.Draft, ResourceDir, CDB, PCHs, TaggedFS.Value, + [&](ClangdUnit &Unit) { Result = Unit.findDefinitions(Pos); }); return make_tagged(std::move(Result), TaggedFS.Tag); } + +llvm::Optional ClangdServer::switchSourceHeader(PathRef Path) { + + StringRef SourceExtensions[] = {".cpp", ".c", ".cc", ".cxx", + ".c++", ".m", ".mm"}; + StringRef HeaderExtensions[] = {".h", ".hh", ".hpp", ".hxx", ".inc"}; + + StringRef PathExt = llvm::sys::path::extension(Path); + + // Lookup in a list of known exten
[PATCH] D37150: [clangd] Command line arg to specify compile_commands.json path
Nebiroth updated this revision to Diff 114654. Nebiroth added a comment. Simpilified a pointer return value. https://reviews.llvm.org/D37150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/tool/ClangdMain.cpp Index: clangd/tool/ClangdMain.cpp === --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -11,8 +11,8 @@ #include "JSONRPCDispatcher.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Program.h" - #include #include #include @@ -25,16 +25,43 @@ llvm::cl::desc("parse on main thread"), llvm::cl::init(false), llvm::cl::Hidden); +static llvm::cl::opt CompileCommandsDir( +"compile-commands-dir", +llvm::cl::desc("Specify a path to look for compile_commands.json. If path " + "is invalid, clangd will look in the current directory and " + "parent paths of each source file.")); + int main(int argc, char *argv[]) { llvm::cl::ParseCommandLineOptions(argc, argv, "clangd"); llvm::raw_ostream &Outs = llvm::outs(); llvm::raw_ostream &Logs = llvm::errs(); JSONOutput Out(Outs, Logs); + // If --compile-commands-dir arg was invoked, check value and override default + // path. + namespace path = llvm::sys::path; + + if (!llvm::sys::path::is_absolute(CompileCommandsDir)) { +Out.log("Path specified by --compile-commands-dir must be an absolute " +"path. The argument will be ignored.\n"); +CompileCommandsDir = ""; + } + + if (!llvm::sys::fs::exists(CompileCommandsDir)) { +Out.log("Path specified by --compile-commands-dir. The argument will be " +"ignored.\n"); +CompileCommandsDir = ""; + } + llvm::Optional CompileCommandsDirPath; + // Change stdin to binary to not lose \r\n on windows. llvm::sys::ChangeStdinToBinary(); + if (CompileCommandsDir.empty()) +CompileCommandsDirPath = llvm::None; + else +CompileCommandsDirPath = CompileCommandsDir; - ClangdLSPServer LSPServer(Out, RunSynchronously); + ClangdLSPServer LSPServer(Out, RunSynchronously, CompileCommandsDirPath); LSPServer.run(std::cin); } Index: clangd/GlobalCompilationDatabase.h === --- clangd/GlobalCompilationDatabase.h +++ clangd/GlobalCompilationDatabase.h @@ -45,13 +45,18 @@ class DirectoryBasedGlobalCompilationDatabase : public GlobalCompilationDatabase { public: + DirectoryBasedGlobalCompilationDatabase( + llvm::Optional NewCompileCommandsDir) + : CompileCommandsDir(NewCompileCommandsDir.getValue()) {} std::vector getCompileCommands(PathRef File) override; void setExtraFlagsForFile(PathRef File, std::vector ExtraFlags); private: tooling::CompilationDatabase *getCompilationDatabase(PathRef File); + Path CompileCommandsDir; + tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File); std::mutex Mutex; /// Caches compilation databases loaded from directories(keys are Index: clangd/GlobalCompilationDatabase.cpp === --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -62,43 +62,52 @@ } tooling::CompilationDatabase * -DirectoryBasedGlobalCompilationDatabase::getCompilationDatabase(PathRef File) { - std::lock_guard Lock(Mutex); - +DirectoryBasedGlobalCompilationDatabase::tryLoadDatabaseFromPath(PathRef File) { namespace path = llvm::sys::path; + auto CachedIt = CompilationDatabases.find(File); + std::string Error = ""; assert((path::is_absolute(File, path::Style::posix) || path::is_absolute(File, path::Style::windows)) && "path must be absolute"); - for (auto Path = path::parent_path(File); !Path.empty(); - Path = path::parent_path(Path)) { - -auto CachedIt = CompilationDatabases.find(Path); -if (CachedIt != CompilationDatabases.end()) - return CachedIt->second.get(); -std::string Error; -auto CDB = tooling::CompilationDatabase::loadFromDirectory(Path, Error); -if (!CDB) { - if (!Error.empty()) { -// FIXME(ibiryukov): logging -// Output.log("Error when trying to load compilation database from " + -//Twine(Path) + ": " + Twine(Error) + "\n"); - } - continue; -} + if (CachedIt != CompilationDatabases.end()) +return (CachedIt->second.get()); + auto CDB = tooling::CompilationDatabase::loadFromDirectory(File, Error); + if (CDB && Error.empty()) { +auto result = CDB.get(); +CompilationDatabases.insert(std::make_pair(File, std::move(CDB))); // FIXME(ibiryukov): Invalidate cached compilation databases on changes -auto result = CDB.get(); -Compil
[PATCH] D37150: [clangd] Command line arg to specify compile_commands.json path
Nebiroth updated this revision to Diff 115462. Nebiroth marked an inline comment as done. Nebiroth added a comment. Fixed a few comments. Rebased on latest clangd version. https://reviews.llvm.org/D37150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/tool/ClangdMain.cpp Index: clangd/tool/ClangdMain.cpp === --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -11,16 +11,23 @@ #include "JSONRPCDispatcher.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Program.h" - #include #include #include #include using namespace clang; using namespace clang::clangd; +static llvm::cl::opt CompileCommandsDir( +"compile-commands-dir", +llvm::cl::desc("Specify a path to look for compile_commands.json. If path " + "is invalid, clangd will look in the current directory and " + "parent paths of each source file.")); + + static llvm::cl::opt WorkerThreadsCount("j", llvm::cl::desc("Number of async workers used by clangd"), @@ -59,15 +66,37 @@ llvm::raw_ostream &Outs = llvm::outs(); llvm::raw_ostream &Logs = llvm::errs(); JSONOutput Out(Outs, Logs); - + // Change stdin to binary to not lose \r\n on windows. llvm::sys::ChangeStdinToBinary(); + // If --compile-commands-dir arg was invoked, check value and override default + // path. + namespace path = llvm::sys::path; + + if (!llvm::sys::path::is_absolute(CompileCommandsDir)) { +Out.log("Path specified by --compile-commands-dir must be an absolute " +"path. The argument will be ignored.\n"); +CompileCommandsDir = ""; + } + + if (!llvm::sys::fs::exists(CompileCommandsDir)) { +Out.log("Path specified by --compile-commands-dir does not exist. The argument will be " +"ignored.\n"); +CompileCommandsDir = ""; + } + llvm::Optional CompileCommandsDirPath; + + if (CompileCommandsDir.empty()) +CompileCommandsDirPath = llvm::None; + else +CompileCommandsDirPath = CompileCommandsDir; + llvm::Optional ResourceDirRef = None; if (!ResourceDir.empty()) ResourceDirRef = ResourceDir; ClangdLSPServer LSPServer(Out, WorkerThreadsCount, EnableSnippets, -ResourceDirRef); +ResourceDirRef, CompileCommandsDirPath); LSPServer.run(std::cin); } Index: clangd/GlobalCompilationDatabase.h === --- clangd/GlobalCompilationDatabase.h +++ clangd/GlobalCompilationDatabase.h @@ -45,14 +45,19 @@ class DirectoryBasedGlobalCompilationDatabase : public GlobalCompilationDatabase { public: + DirectoryBasedGlobalCompilationDatabase( + llvm::Optional NewCompileCommandsDir) + : CompileCommandsDir(NewCompileCommandsDir) {} std::vector getCompileCommands(PathRef File) override; void setExtraFlagsForFile(PathRef File, std::vector ExtraFlags); private: - tooling::CompilationDatabase *getCompilationDatabase(PathRef File); + tooling::CompilationDatabase *getCompilationDatabase(PathRef File); + tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File); + llvm::Optional CompileCommandsDir; std::mutex Mutex; /// Caches compilation databases loaded from directories(keys are /// directories). Index: clangd/GlobalCompilationDatabase.cpp === --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -62,43 +62,50 @@ } tooling::CompilationDatabase * -DirectoryBasedGlobalCompilationDatabase::getCompilationDatabase(PathRef File) { - std::lock_guard Lock(Mutex); - +DirectoryBasedGlobalCompilationDatabase::tryLoadDatabaseFromPath(PathRef File) { namespace path = llvm::sys::path; + auto CachedIt = CompilationDatabases.find(File); + std::string Error = ""; assert((path::is_absolute(File, path::Style::posix) || path::is_absolute(File, path::Style::windows)) && "path must be absolute"); - for (auto Path = path::parent_path(File); !Path.empty(); - Path = path::parent_path(Path)) { - -auto CachedIt = CompilationDatabases.find(Path); -if (CachedIt != CompilationDatabases.end()) - return CachedIt->second.get(); -std::string Error; -auto CDB = tooling::CompilationDatabase::loadFromDirectory(Path, Error); -if (!CDB) { - if (!Error.empty()) { -// FIXME(ibiryukov): logging -// Output.log("Error when trying to load compilation database from " + -//Twine(Path) + ": " + Twine(Error) + "\n"); - } - continue; -} + if (CachedIt != CompilationDatabases.end()) +return CachedIt->second.get(); + auto CDB = tooling::Compilatio
[PATCH] D36150: [clangd] LSP extension to switch between source/header file
Nebiroth added a comment. In https://reviews.llvm.org/D36150#867971, @ilya-biryukov wrote: > Overall looks good, but still needs at least a few tests. I have a test for this commit that uses included source and header files, would that be okay to do or should I generate files dynamically? If so, how can I accomplish this? https://reviews.llvm.org/D36150 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D36150: [clangd] LSP extension to switch between source/header file
Nebiroth updated this revision to Diff 116038. Nebiroth added a comment. Added unit test. https://reviews.llvm.org/D36150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h unittests/clangd/ClangdTests.cpp Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -892,5 +892,83 @@ } } +TEST_F(ClangdVFSTest, CheckSourceHeaderSwitch) { + MockFSProvider FS; + ErrorCheckingDiagConsumer DiagConsumer; + MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true); + + ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), + /*SnippetCompletions=*/false); + + auto SourceContents = R"cpp( + #include "foo.h" + int b = a; + )cpp"; + + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + auto FooH = getVirtualTestFilePath("foo.h"); + auto invalid = getVirtualTestFilePath("main.cpp"); + + FS.Files[FooCpp] = SourceContents; + FS.Files[FooH] = "int a;"; + FS.Files[invalid] = "int main() { \n return 0; \n }"; + + llvm::Optional pathResult = Server.switchSourceHeader(FooCpp); + EXPECT_TRUE(pathResult.hasValue()); + ASSERT_EQ(pathResult.getValue(), FooH); + + pathResult = Server.switchSourceHeader(FooH); + EXPECT_TRUE(pathResult.hasValue()); + ASSERT_EQ(pathResult.getValue(), FooCpp); + + SourceContents = R"c( + #include "foo.HH" + int b = a; + )c"; + + // Test with header file in capital letters and different extension, source file with different extension + auto FooC = getVirtualTestFilePath("bar.c"); + auto FooHH = getVirtualTestFilePath("bar.HH"); + + FS.Files[FooC] = SourceContents; + FS.Files[FooHH] = "int a;"; + + pathResult = Server.switchSourceHeader(FooC); + EXPECT_TRUE(pathResult.hasValue()); + ASSERT_EQ(pathResult.getValue(), FooHH); + + // Test with both capital letters + auto Foo2C = getVirtualTestFilePath("foo2.C"); + auto Foo2HH = getVirtualTestFilePath("foo2.HH"); + FS.Files[Foo2C] = SourceContents; + FS.Files[Foo2HH] = "int a;"; + + pathResult = Server.switchSourceHeader(Foo2C); + EXPECT_TRUE(pathResult.hasValue()); + ASSERT_EQ(pathResult.getValue(), Foo2HH); + + // Test with source file as capital letter and .hxx header file + auto Foo3C = getVirtualTestFilePath("foo3.C"); + auto Foo3HXX = getVirtualTestFilePath("foo3.hxx"); + + SourceContents = R"c( + #include "foo3.hxx" + int b = a; + )c"; + + FS.Files[Foo3C] = SourceContents; + FS.Files[Foo3HXX] = "int a;"; + + pathResult = Server.switchSourceHeader(Foo3C); + EXPECT_TRUE(pathResult.hasValue()); + ASSERT_EQ(pathResult.getValue(), Foo3HXX); + + + // Test if asking for a corresponding file that doesn't exist returns an empty string. + pathResult = Server.switchSourceHeader(invalid); + EXPECT_FALSE(pathResult.hasValue()); + +} + } // namespace clangd } // namespace clang Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -48,6 +48,8 @@ JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; + virtual void onSwitchSourceHeader(TextDocumentIdentifier Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,22 @@ ProtocolCallbacks &Callbacks; }; +struct SwitchSourceHeaderHandler : Handler { + SwitchSourceHeaderHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentIdentifier::parse(Params); +if (!TDPP) + return; + +Callbacks.onSwitchSourceHeader(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -240,4 +256,7 @@ Dispatcher.registerHandler( "textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/switchSourceHeader", + llvm::make_unique(Out, Callbacks)); } Index: clangd/ClangdServer.h === --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -241,6 +241,10 @@ /// Get definition of symbol at a specified \p Line and \p Column in \p File. Tagged> findDefinitions(PathRef File, Position Pos); + /// Helper function tha
[PATCH] D37150: [clangd] Command line arg to specify compile_commands.json path
Nebiroth updated this revision to Diff 116198. Nebiroth added a comment. More consistent logging in clangdmain. Restructured argument checking in ClangdMain Fixed empty compile-commands-dir triggering error messages. Fixed failing standard tests. https://reviews.llvm.org/D37150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/tool/ClangdMain.cpp Index: clangd/tool/ClangdMain.cpp === --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -11,16 +11,24 @@ #include "JSONRPCDispatcher.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Program.h" - #include #include #include #include +#include using namespace clang; using namespace clang::clangd; +static llvm::cl::opt CompileCommandsDir( +"compile-commands-dir", +llvm::cl::desc("Specify a path to look for compile_commands.json. If path " + "is invalid, clangd will look in the current directory and " + "parent paths of each source file.")); + + static llvm::cl::opt WorkerThreadsCount("j", llvm::cl::desc("Number of async workers used by clangd"), @@ -56,18 +64,44 @@ if (RunSynchronously) WorkerThreadsCount = 0; + /// Validate command line arguments. llvm::raw_ostream &Outs = llvm::outs(); llvm::raw_ostream &Logs = llvm::errs(); - JSONOutput Out(Outs, Logs); + JSONOutput Out(Outs, Logs); - // Change stdin to binary to not lose \r\n on windows. - llvm::sys::ChangeStdinToBinary(); + // If --compile-commands-dir arg was invoked, check value and override default + // path. + namespace path = llvm::sys::path; + llvm::Optional CompileCommandsDirPath; + + if (CompileCommandsDir.empty()) +CompileCommandsDirPath = llvm::None; + else + { +if (!llvm::sys::path::is_absolute(CompileCommandsDir)) { + llvm::errs() << "Path specified by --compile-commands-dir must be an absolute " + "path. The argument will be ignored.\n"; + CompileCommandsDir = ""; +} + +if (!llvm::sys::fs::exists(CompileCommandsDir)) { + llvm::errs() << "Path specified by --compile-commands-dir does not exist. The argument will be " + "ignored.\n"; + CompileCommandsDir = ""; +} +CompileCommandsDirPath = CompileCommandsDir; + } llvm::Optional ResourceDirRef = None; if (!ResourceDir.empty()) ResourceDirRef = ResourceDir; + /// Change stdin to binary to not lose \r\n on windows. + llvm::sys::ChangeStdinToBinary(); + + /// Initialize and run ClangdLSPServer. + ClangdLSPServer LSPServer(Out, WorkerThreadsCount, EnableSnippets, -ResourceDirRef); +ResourceDirRef, CompileCommandsDirPath); LSPServer.run(std::cin); } Index: clangd/GlobalCompilationDatabase.h === --- clangd/GlobalCompilationDatabase.h +++ clangd/GlobalCompilationDatabase.h @@ -45,14 +45,19 @@ class DirectoryBasedGlobalCompilationDatabase : public GlobalCompilationDatabase { public: + DirectoryBasedGlobalCompilationDatabase( + llvm::Optional NewCompileCommandsDir) + : CompileCommandsDir(NewCompileCommandsDir) {} std::vector getCompileCommands(PathRef File) override; void setExtraFlagsForFile(PathRef File, std::vector ExtraFlags); private: - tooling::CompilationDatabase *getCompilationDatabase(PathRef File); + tooling::CompilationDatabase *getCompilationDatabase(PathRef File); + tooling::CompilationDatabase *tryLoadDatabaseFromPath(PathRef File); + llvm::Optional CompileCommandsDir; std::mutex Mutex; /// Caches compilation databases loaded from directories(keys are /// directories). Index: clangd/GlobalCompilationDatabase.cpp === --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -62,43 +62,54 @@ } tooling::CompilationDatabase * -DirectoryBasedGlobalCompilationDatabase::getCompilationDatabase(PathRef File) { - std::lock_guard Lock(Mutex); - +DirectoryBasedGlobalCompilationDatabase::tryLoadDatabaseFromPath(PathRef File) { + namespace path = llvm::sys::path; + auto CachedIt = CompilationDatabases.find(File); + std::string Error = ""; assert((path::is_absolute(File, path::Style::posix) || path::is_absolute(File, path::Style::windows)) && "path must be absolute"); - for (auto Path = path::parent_path(File); !Path.empty(); - Path = path::parent_path(Path)) { - -auto CachedIt = CompilationDatabases.find(Path); -if (CachedIt != CompilationDatabases.end()) - return CachedIt->second.get(); -std::string Error; -auto CDB = tooling::CompilationDatabase::loadFromDir
[PATCH] D36150: [clangd] LSP extension to switch between source/header file
Nebiroth updated this revision to Diff 116387. Nebiroth marked 2 inline comments as done. Nebiroth added a comment. Rebased on latest version. Corrected code style issues in test file. https://reviews.llvm.org/D36150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h unittests/clangd/ClangdTests.cpp Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -7,6 +7,7 @@ // //===--===// +#include "ClangdLSPServer.h" #include "ClangdServer.h" #include "Logger.h" #include "clang/Basic/VirtualFileSystem.h" @@ -899,6 +900,84 @@ } } +TEST_F(ClangdVFSTest, CheckSourceHeaderSwitch) { + MockFSProvider FS; + ErrorCheckingDiagConsumer DiagConsumer; + MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true); + + ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), + /*SnippetCompletions=*/false, EmptyLogger::getInstance()); + + auto SourceContents = R"cpp( + #include "foo.h" + int b = a; + )cpp"; + + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + auto FooH = getVirtualTestFilePath("foo.h"); + auto Invalid = getVirtualTestFilePath("main.cpp"); + + FS.Files[FooCpp] = SourceContents; + FS.Files[FooH] = "int a;"; + FS.Files[Invalid] = "int main() { \n return 0; \n }"; + + llvm::Optional PathResult = Server.switchSourceHeader(FooCpp); + EXPECT_TRUE(PathResult.hasValue()); + ASSERT_EQ(PathResult.getValue(), FooH); + + PathResult = Server.switchSourceHeader(FooH); + EXPECT_TRUE(PathResult.hasValue()); + ASSERT_EQ(PathResult.getValue(), FooCpp); + + SourceContents = R"c( + #include "foo.HH" + int b = a; + )c"; + + // Test with header file in capital letters and different extension, source + // file with different extension + auto FooC = getVirtualTestFilePath("bar.c"); + auto FooHH = getVirtualTestFilePath("bar.HH"); + + FS.Files[FooC] = SourceContents; + FS.Files[FooHH] = "int a;"; + + PathResult = Server.switchSourceHeader(FooC); + EXPECT_TRUE(PathResult.hasValue()); + ASSERT_EQ(PathResult.getValue(), FooHH); + + // Test with both capital letters + auto Foo2C = getVirtualTestFilePath("foo2.C"); + auto Foo2HH = getVirtualTestFilePath("foo2.HH"); + FS.Files[Foo2C] = SourceContents; + FS.Files[Foo2HH] = "int a;"; + + PathResult = Server.switchSourceHeader(Foo2C); + EXPECT_TRUE(PathResult.hasValue()); + ASSERT_EQ(PathResult.getValue(), Foo2HH); + + // Test with source file as capital letter and .hxx header file + auto Foo3C = getVirtualTestFilePath("foo3.C"); + auto Foo3HXX = getVirtualTestFilePath("foo3.hxx"); + + SourceContents = R"c( + #include "foo3.hxx" + int b = a; + )c"; + + FS.Files[Foo3C] = SourceContents; + FS.Files[Foo3HXX] = "int a;"; + + PathResult = Server.switchSourceHeader(Foo3C); + EXPECT_TRUE(PathResult.hasValue()); + ASSERT_EQ(PathResult.getValue(), Foo3HXX); + + // Test if asking for a corresponding file that doesn't exist returns an empty + // string. + PathResult = Server.switchSourceHeader(Invalid); + EXPECT_FALSE(PathResult.hasValue()); +} + TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) { class NoConcurrentAccessDiagConsumer : public DiagnosticsConsumer { public: Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -48,6 +48,8 @@ JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; + virtual void onSwitchSourceHeader(TextDocumentIdentifier Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,22 @@ ProtocolCallbacks &Callbacks; }; +struct SwitchSourceHeaderHandler : Handler { + SwitchSourceHeaderHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentIdentifier::parse(Params, Output); +if (!TDPP) + return; + +Callbacks.onSwitchSourceHeader(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -240,4 +256,7 @@ Dispatcher.registerHandler( "textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHan
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth updated this revision to Diff 123958. Nebiroth marked 10 inline comments as done. Nebiroth added a comment. Removed accidentally included files Fixed some coding standard issues Removed getDeclarationLocation declaration from header file Replaced getFunctionComments with clang implementation onCodeHover now follows error-reporting pattern https://reviews.llvm.org/D35894 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/hover.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -5,6 +5,7 @@ Content-Length: 143 {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootUri":"file:///path/to/workspace","capabilities":{},"trace":"off"}} + # CHECK: "id": 0, # CHECK-NEXT: "jsonrpc": "2.0", # CHECK-NEXT: "result": { @@ -30,6 +31,7 @@ # CHECK-NEXT: "clangd.applyFix" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "renameProvider": true, # CHECK-NEXT: "signatureHelpProvider": { # CHECK-NEXT:"triggerCharacters": [ Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -30,6 +30,7 @@ # CHECK-NEXT: "clangd.applyFix" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "renameProvider": true, # CHECK-NEXT: "signatureHelpProvider": { # CHECK-NEXT:"triggerCharacters": [ @@ -40,6 +41,7 @@ # CHECK-NEXT: "textDocumentSync": 1 # CHECK-NEXT:} # CHECK-NEXT: } + Content-Length: 44 {"jsonrpc":"2.0","id":3,"method":"shutdown"} Index: test/clangd/hover.test === --- /dev/null +++ test/clangd/hover.test @@ -0,0 +1,52 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 407 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nint test = 5;\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};}\nint main() {\nint a;\na;\nint b = ns1::test;\nns1::MyClass* Params;\nParams->anotherOperation();\nMACRO;}\n"}}} + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":0,"character":12}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"#define MACRO 1"}],"range":{"end":{"character":15,"line":0},"start":{"character":8,"line":0 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":14,"character":1}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"int a"}],"range":{"end":{"character":5,"line":13},"start":{"character":0,"line":13 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":15,"character":15}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1"},{"language":"C++","value":"int test = 5"}],"range":{"end":{"character":12,"line":2},"start":{"character":0,"line":2 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":16,"character":10}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1"},{"language":"C++","value":"struct MyClass {"}],"range":{"end":{"character":16,"line":3},"start":{"character":0,"line":3 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":13}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1::MyClass"},{"language":"C++","value":"void anotherOperation() {"}],"range":{"end":{"character":25,"line":5},"start":{"character":0,
[PATCH] D39571: [clangd] DidChangeConfiguration Notification
Nebiroth updated this revision to Diff 124024. Nebiroth marked 19 inline comments as done. Nebiroth added a comment. Fixed DraftStore thread-safe API being broken Removed superfluous getCompilationDatabase call Changed name of struct to ClangDConfigurationParamsChange Removed operator ! overload for struct Minor code cleanup https://reviews.llvm.org/D39571 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/DraftStore.cpp clangd/DraftStore.h clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/did-change-configuration.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -18,6 +18,7 @@ # CHECK-NEXT: ":" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "configurationChangeProvider": true, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { @@ -48,4 +49,4 @@ # CHECK-NEXT: "result": null Content-Length: 33 -{"jsonrpc":"2.0":"method":"exit"} +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -1,3 +1,4 @@ + # RUN: clangd -pretty -run-synchronously < %s | FileCheck -strict-whitespace %s # It is absolutely vital that this file has CRLF line endings. # @@ -18,6 +19,7 @@ # CHECK-NEXT: ":" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "configurationChangeProvider": true, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { @@ -45,4 +47,4 @@ {"jsonrpc":"2.0","id":3,"method":"shutdown"} Content-Length: 33 -{"jsonrpc":"2.0":"method":"exit"} +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: test/clangd/did-change-configuration.test === --- /dev/null +++ test/clangd/did-change-configuration.test @@ -0,0 +1,46 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 150 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///foo.c","languageId":"c","version":1,"text":"voidmain(){}"}}} + +Content-Length: 86 + +{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":""}} +#Failed to decode workspace/didChangeConfiguration request. +#Incorrect mapping node + +Content-Length: 114 + +{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabasePath":{ +#Failed to decode workspace/didChangeConfiguration request. +#compilationDatabasePath is not a scalar node + +Content-Length: 140 + +{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabasePath":"/","testBadValue":"foo1234"}}} +#Ignored unknown field "testBadValue" +#Failed to find compilation database for / in overriden directory / +#Bad field, bad compilation database + +Content-Length: 722 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///compile_commands.json","languageId":"json","version":1,"text":"[\n{\n"directory":"/",\n"command":"/usr/bin/c++-DGTEST_HAS_RTTI=0-D_GNU_SOURCE-D__STDC_CONSTANT_MACROS-D__STDC_FORMAT_MACROS-D__STDC_LIMIT_MACROS-Ilib/Demangle-I../lib/Demangle-I/usr/include/libxml2-Iinclude-I../include-fPIC-fvisibility-inlines-hidden-Werror=date-time-std=c++11-Wall-W-Wno-unused-parameter-Wwrite-strings-Wcast-qual-Wno-missing-field-initializers-pedantic-Wno-long-long-Wno-maybe-uninitialized-Wdelete-non-virtual-dtor-Wno-comment-O0-g-fno-exceptions-fno-rtti-o/foo.c.o-c/foo.c",\n"file":"/foo.c"\n},"}}} + +Content-Length: 115 + +{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabasePath":"/"}}} +#CHECK:{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"diagnostics":[{"message":"type specifier missing, defaults to 'int'","range":{"end":{"character":1,"line":0},"start":{"character":1,"line":0}},"severity":2},{"message":"control reaches end of non-void function","range":{"end":{"character":12,"line":0},"start":{"character":12,"line":0}},"severity":2}],"uri"
[PATCH] D39571: [clangd] DidChangeConfiguration Notification
Nebiroth added inline comments. Comment at: clangd/GlobalCompilationDatabase.cpp:108 Logger.log("Failed to find compilation database for " + Twine(File) + - "in overriden directory " + CompileCommandsDir.getValue() + + " in overriden directory " + CompileCommandsDir.getValue() + "\n"); ilya-biryukov wrote: > Accidental change? Twine(File) and "in overriden directory" did not have a space to separate otherwise. https://reviews.llvm.org/D39571 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth updated this revision to Diff 124116. Nebiroth marked 32 inline comments as done. Nebiroth added a comment. Minor code cleanup and improvements getRawCommentForDeclNoCache() now called for every Decl and only once per Decl getHover() now properly handles templates https://reviews.llvm.org/D35894 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/hover.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -30,6 +30,7 @@ # CHECK-NEXT: "clangd.applyFix" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "renameProvider": true, # CHECK-NEXT: "signatureHelpProvider": { # CHECK-NEXT:"triggerCharacters": [ Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -30,6 +30,7 @@ # CHECK-NEXT: "clangd.applyFix" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "renameProvider": true, # CHECK-NEXT: "signatureHelpProvider": { # CHECK-NEXT:"triggerCharacters": [ Index: test/clangd/hover.test === --- /dev/null +++ test/clangd/hover.test @@ -0,0 +1,52 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 407 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nint test = 5;\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};}\nint main() {\nint a;\na;\nint b = ns1::test;\nns1::MyClass* Params;\nParams->anotherOperation();\nMACRO;}\n"}}} + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":0,"character":12}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"#define MACRO 1"}],"range":{"end":{"character":15,"line":0},"start":{"character":8,"line":0 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":14,"character":1}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"int a"}],"range":{"end":{"character":5,"line":13},"start":{"character":0,"line":13 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":15,"character":15}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1"},{"language":"C++","value":"int test = 5"}],"range":{"end":{"character":12,"line":2},"start":{"character":0,"line":2 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":16,"character":10}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1"},{"language":"C++","value":"struct MyClass {"}],"range":{"end":{"character":16,"line":3},"start":{"character":0,"line":3 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":13}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1::MyClass"},{"language":"C++","value":"void anotherOperation() {"}],"range":{"end":{"character":25,"line":5},"start":{"character":0,"line":5 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":1}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"#define MACRO 1"}],"range":{"end":{"character":15,"line":0},"start":{"character":8,"line":0 + +Content-Length: 44 + +{"jsonrpc":"2.0","id":3,"method":"shutdown"} + + Index: clangd/ProtocolHandlers.h ===
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth marked 31 inline comments as done. Nebiroth added inline comments. Comment at: clangd/ClangdServer.h:291 + /// Get document highlights for a symbol hovered on. + Tagged> findDocumentHighlights(PathRef File, +Position Pos); malaperle wrote: > can this thing fail? Should it be Expectedhttps://reviews.llvm.org/D38425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 124224. Nebiroth marked an inline comment as done. Nebiroth added a comment. Getting DocumentHighlightKind is now done in DocumentHighlightsFinder Removed duplicated and unused code Refactored method and variable names https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,37 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 455 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":12,"line":16},"start":{"character":4,"line":16}}},{"kind":0,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}}]} + + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":9,"line":12},"start":{"character":4,"line":12}}},{"kind":1,"range":{"end":{"character":21,"line":18},"start":{"character":17,"line":18}}},{"kind":216,"range":{"end":{"character":21,"line":18},"start":{"character":17,"line":18}}},{"kind":220,"range":{"end":{"character":8,"line":19},"start":{"character":4,"line":19}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":22,"line":4},"start":{"character":5,"line":4}}},{"kind":0,"range":{"end":{"character":25,"line":21},"start":{"character":8,"line":21}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -54,6 +54,8 @@ virtual void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) = 0; virtual void onCommand(Ctx C, ExecuteCommandParams &Params) = 0; virtual void onRename(Ctx C, RenameParams &Parames) = 0; + virtual void onDocumentHighlight(Ctx C, + TextDocumentPositionParams &Params) = 0; }; void registerCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp ===
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 124230. Nebiroth marked 6 inline comments as done. Nebiroth added a comment. Fixed a few outstanding issues that were reported as completed https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,37 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 455 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":12,"line":16},"start":{"character":4,"line":16}}},{"kind":0,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}}]} + + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":9,"line":12},"start":{"character":4,"line":12}}},{"kind":1,"range":{"end":{"character":21,"line":18},"start":{"character":17,"line":18}}},{"kind":216,"range":{"end":{"character":21,"line":18},"start":{"character":17,"line":18}}},{"kind":220,"range":{"end":{"character":8,"line":19},"start":{"character":4,"line":19}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":22,"line":4},"start":{"character":5,"line":4}}},{"kind":0,"range":{"end":{"character":25,"line":21},"start":{"character":8,"line":21}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -54,6 +54,8 @@ virtual void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) = 0; virtual void onCommand(Ctx C, ExecuteCommandParams &Params) = 0; virtual void onRename(Ctx C, RenameParams &Parames) = 0; + virtual void onDocumentHighlight(Ctx C, + TextDocumentPositionParams &Params) = 0; }; void registerCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cp
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 124238. Nebiroth marked 3 inline comments as done. Nebiroth added a comment. Fixed test checking for values from an incorrect bit shift https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h clangd/main.cpp test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,38 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 455 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":12,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}}]} + + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":9,"line":12},"start":{"character":4,"line":12}}},{"kind":1,"range":{"end":{"character":21,"line":18},"start":{"character":17,"line":18}}},{"kind":3,"range":{"end":{"character":8,"line":19},"start":{"character":4,"line":19}}}]} + + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":22,"line":4},"start":{"character":5,"line":4}}},{"kind":1,"range":{"end":{"character":25,"line":21},"start":{"character":8,"line":21}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: clangd/main.cpp === --- /dev/null +++ clangd/main.cpp @@ -0,0 +1,22 @@ +#define MACRO 1 +namespace ns1 { +struct MyClass { +int xasd; +void anotherOperation(){ +} +static int foo(MyClass*) { +return 0; +} + +}; +struct Foo { +int xasd; +}; +} +int main() { +int bonjour; +bonjour = 2; +ns1::Foo bar = { xasd : 1}; +bar.xasd = 3; +ns1::MyClass* Params; +Params->anotherOperation();} \ No newline at end of file Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -54,6 +54,8 @@ virtual void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) = 0; virtual void onCommand(Ctx C, ExecuteCommandParams &Params)
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 124391. Nebiroth marked an inline comment as done. Nebiroth added a comment. Herald added a subscriber: klimek. Removed temporary test file Updated test to account for read-access symbol verification Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,42 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 479 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nint test1 = bonjour;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();\n}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Verify local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":12,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":20,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Verify struct highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":12,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":20,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Verify method highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":14,"line":2},"start":{"character":7,"line":2}}},{"kind":1,"range":{"end":{"character":23,"line":6},"start":{"character":15,"line":6}}},{"kind":1,"range":{"end":{"character":13,"line":21},"start":{"character":5,"line":21}}}]} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":14}}} +# Verify Read-access of a symbol (kind = 2) +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":12,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":20,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"}
[PATCH] D39571: [clangd] DidChangeConfiguration Notification
Nebiroth marked 12 inline comments as done. Nebiroth added inline comments. Comment at: test/clangd/did-change-configuration.test:33 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///compile_commands.json","languageId":"json","version":1,"text":"[\n{\n"directory":"/",\n"command":"/usr/bin/c++-DGTEST_HAS_RTTI=0-D_GNU_SOURCE-D__STDC_CONSTANT_MACROS-D__STDC_FORMAT_MACROS-D__STDC_LIMIT_MACROS-Ilib/Demangle-I../lib/Demangle-I/usr/include/libxml2-Iinclude-I../include-fPIC-fvisibility-inlines-hidden-Werror=date-time-std=c++11-Wall-W-Wno-unused-parameter-Wwrite-strings-Wcast-qual-Wno-missing-field-initializers-pedantic-Wno-long-long-Wno-maybe-uninitialized-Wdelete-non-virtual-dtor-Wno-comment-O0-g-fno-exceptions-fno-rtti-o/foo.c.o-c/foo.c",\n"file":"/foo.c"\n},"}}} + ilya-biryukov wrote: > clangd won't see this file. `didOpen` only sets contents for diagnostics, not > any other features. > You would rather want to add more `# RUN:` directives at the top of the file > to create `compile_commands.json`, etc. > > Writing it under root ('/') is obviously not an option. Lit tests allow you > to use temporary paths, this is probably an approach you could take. See [[ > https://llvm.org/docs/TestingGuide.html#substitutions | lit docs ]] for more > details. Are there examples available on how to use this? I have to use a # RUN: to create a file and then use it's path in a workspace/didChangeConfiguration notification? https://reviews.llvm.org/D39571 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 124458. Nebiroth marked 3 inline comments as done. Nebiroth added a comment. Minor code cleanup Fixed highlights sometimes obtaining one too many characters inside range Updated test Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,42 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 479 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nint test1 = bonjour;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();\n}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Verify local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Verify struct highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Verify method highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":14,"line":2},"start":{"character":7,"line":2}}},{"kind":1,"range":{"end":{"character":22,"line":6},"start":{"character":15,"line":6}}},{"kind":1,"range":{"end":{"character":12,"line":21},"start":{"character":5,"line":21}}}]} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":14}}} +# Verify Read-access of a symbol (kind = 2) +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} \ No newline at
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 124810. Nebiroth added a comment. Added verification for llvm::Expected in onDocumentHighlight Removed unused variable in ClangdUnit Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,42 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 479 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nint test1 = bonjour;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();\n}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Verify local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Verify struct highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Verify method highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":14,"line":2},"start":{"character":7,"line":2}}},{"kind":1,"range":{"end":{"character":22,"line":6},"start":{"character":15,"line":6}}},{"kind":1,"range":{"end":{"character":12,"line":21},"start":{"character":5,"line":21}}}]} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":14}}} +# Verify Read-access of a symbol (kind = 2) +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: clangd/ProtocolHandlers.h
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth updated this revision to Diff 124833. Nebiroth added a comment. Herald added a subscriber: klimek. Invalid FileEntries now return llvm:ErrorOr Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D35894 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/hover.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -30,6 +30,7 @@ # CHECK-NEXT: "clangd.applyFix" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "renameProvider": true, # CHECK-NEXT: "signatureHelpProvider": { # CHECK-NEXT:"triggerCharacters": [ Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -30,6 +30,7 @@ # CHECK-NEXT: "clangd.applyFix" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "renameProvider": true, # CHECK-NEXT: "signatureHelpProvider": { # CHECK-NEXT:"triggerCharacters": [ Index: test/clangd/hover.test === --- /dev/null +++ test/clangd/hover.test @@ -0,0 +1,56 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 611 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nint test = 5;\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};}\n//comments test\ntemplate\nT templateTest(T foo) {\nreturn foo;}\ntemplate\nclass classTemplateTest {\npublic: T test;};\nint main() {\nint a;\na;\nint b = ns1::test;\nns1::MyClass* Params;\nParams->anotherOperation();\nMACRO;\nint temp = 5;\ntemplateTest(temp);classTemplateTest test;}\n"}}} + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":0,"character":12}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"#define MACRO 1"}],"range":{"end":{"character":15,"line":0},"start":{"character":8,"line":0 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":1}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"int a"}],"range":{"end":{"character":5,"line":20},"start":{"character":0,"line":20 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":22,"character":15}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1"},{"language":"C++","value":"int test = 5"}],"range":{"end":{"character":12,"line":2},"start":{"character":0,"line":2 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":23,"character":10}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1"},{"language":"C++","value":"struct MyClass {"}],"range":{"end":{"character":16,"line":3},"start":{"character":0,"line":3 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":24,"character":13}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1::MyClass"},{"language":"C++","value":"void anotherOperation() {"}],"range":{"end":{"character":25,"line":5},"start":{"character":0,"line":5 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":25,"character":1}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"#define MACRO 1"}],"range":{"end":{"character":15,"line":0},"start":{"character":8,"line":0 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":26,"character":8}}} +# CHE
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 124834. Nebiroth added a comment. Fixed wrong content header making the test fail Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,42 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 479 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nint test1 = bonjour;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();\n}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Verify local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Verify struct highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Verify method highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":14,"line":2},"start":{"character":7,"line":2}}},{"kind":1,"range":{"end":{"character":22,"line":6},"start":{"character":15,"line":6}}},{"kind":1,"range":{"end":{"character":12,"line":21},"start":{"character":5,"line":21}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":14}}} +# Verify Read-access of a symbol (kind = 2) +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: clangd/ProtocolHandlers.h ===
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth updated this revision to Diff 124945. Nebiroth marked an inline comment as done. Nebiroth added a comment. Simplified getHover() function Proper usage of ErrorOr to return errors Given range for Hover struct now only applies to the open file Fixed crash on MacroExpansion Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D35894 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/hover.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -30,6 +30,7 @@ # CHECK-NEXT: "clangd.applyFix" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "renameProvider": true, # CHECK-NEXT: "signatureHelpProvider": { # CHECK-NEXT:"triggerCharacters": [ Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -30,6 +30,7 @@ # CHECK-NEXT: "clangd.applyFix" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "renameProvider": true, # CHECK-NEXT: "signatureHelpProvider": { # CHECK-NEXT:"triggerCharacters": [ Index: test/clangd/hover.test === --- /dev/null +++ test/clangd/hover.test @@ -0,0 +1,56 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 611 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nint test = 5;\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};}\n//comments test\ntemplate\nT templateTest(T foo) {\nreturn foo;}\ntemplate\nclass classTemplateTest {\npublic: T test;};\nint main() {\nint a;\na;\nint b = ns1::test;\nns1::MyClass* Params;\nParams->anotherOperation();\nMACRO;\nint temp = 5;\ntemplateTest(temp);classTemplateTest test;}\n"}}} + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":0,"character":12}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"#define MACRO 1"}],"range":{"end":{"character":15,"line":0},"start":{"character":8,"line":0 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":1}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"int a"}],"range":{"end":{"character":5,"line":20},"start":{"character":0,"line":20 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":22,"character":15}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1"},{"language":"C++","value":"int test = 5"}],"range":{"end":{"character":12,"line":2},"start":{"character":0,"line":2 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":23,"character":10}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1"},{"language":"C++","value":"struct MyClass {"}],"range":{"end":{"character":16,"line":3},"start":{"character":0,"line":3 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":24,"character":13}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1::MyClass"},{"language":"C++","value":"void anotherOperation() {"}],"range":{"end":{"character":25,"line":5},"start":{"character":0,"line":5 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":25,"character":1}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"#define MACRO 1"}],"range":{"end":{"character":15,"line":0},"start":{"character":8,"line":0 + +Content-Length: 144 + +{"jsonrpc":"2.
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 124951. Nebiroth marked 6 inline comments as done. Nebiroth added a comment. Minor code cleanup getDeclarationLocation now returns llvm::Optional operator< for DocumentHighlight struct now properly compares the kind field Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,42 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 479 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nint test1 = bonjour;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();\n}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Verify local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Verify struct highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Verify method highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":14,"line":2},"start":{"character":7,"line":2}}},{"kind":1,"range":{"end":{"character":22,"line":6},"start":{"character":15,"line":6}}},{"kind":1,"range":{"end":{"character":12,"line":21},"start":{"character":5,"line":21}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":14}}} +# Verify Read-access of a symbol (kind = 2) +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonr
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth marked 9 inline comments as done. Nebiroth added inline comments. Comment at: clangd/Protocol.h:26 #include "llvm/ADT/Optional.h" -#include +#include "llvm/Support/YAMLParser.h" #include malaperle wrote: > revert this change? #include is not needed. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D35894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth added inline comments. Comment at: clangd/Protocol.h:26 #include "llvm/ADT/Optional.h" -#include +#include "llvm/Support/YAMLParser.h" #include malaperle wrote: > Nebiroth wrote: > > malaperle wrote: > > > revert this change? > > #include is not needed. > I meant removing YAMLParser.h That's what I figured. I'll remove that. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D35894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth updated this revision to Diff 125224. Nebiroth added a comment. Minor code cleanup Merge with master Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D35894 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/hover.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -30,6 +30,7 @@ # CHECK-NEXT: "clangd.applyFix" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "renameProvider": true, # CHECK-NEXT: "signatureHelpProvider": { # CHECK-NEXT:"triggerCharacters": [ Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -30,6 +30,7 @@ # CHECK-NEXT: "clangd.applyFix" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "hoverProvider": true, # CHECK-NEXT: "renameProvider": true, # CHECK-NEXT: "signatureHelpProvider": { # CHECK-NEXT:"triggerCharacters": [ Index: test/clangd/hover.test === --- /dev/null +++ test/clangd/hover.test @@ -0,0 +1,56 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 611 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nint test = 5;\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};}\n//comments test\ntemplate\nT templateTest(T foo) {\nreturn foo;}\ntemplate\nclass classTemplateTest {\npublic: T test;};\nint main() {\nint a;\na;\nint b = ns1::test;\nns1::MyClass* Params;\nParams->anotherOperation();\nMACRO;\nint temp = 5;\ntemplateTest(temp);classTemplateTest test;}\n"}}} + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":0,"character":12}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"#define MACRO 1"}],"range":{"end":{"character":15,"line":0},"start":{"character":8,"line":0 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":1}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"int a"}],"range":{"end":{"character":5,"line":20},"start":{"character":0,"line":20 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":22,"character":15}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1"},{"language":"C++","value":"int test = 5"}],"range":{"end":{"character":12,"line":2},"start":{"character":0,"line":2 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":23,"character":10}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1"},{"language":"C++","value":"struct MyClass {"}],"range":{"end":{"character":16,"line":3},"start":{"character":0,"line":3 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":24,"character":13}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"In ns1::MyClass"},{"language":"C++","value":"void anotherOperation() {"}],"range":{"end":{"character":25,"line":5},"start":{"character":0,"line":5 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":25,"character":1}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"contents":[{"language":"C++","value":"#define MACRO 1"}],"range":{"end":{"character":15,"line":0},"start":{"character":8,"line":0 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":26,"character":8}}} +# CHECK: {"id":1,"jsonrpc":"2.0","result":{"con
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 125228. Nebiroth added a comment. Minor code cleanup unparse and parse methods for JSON are updated Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,42 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 479 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nint test1 = bonjour;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();\n}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Verify local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Verify struct highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Verify method highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":14,"line":2},"start":{"character":7,"line":2}}},{"kind":1,"range":{"end":{"character":22,"line":6},"start":{"character":15,"line":6}}},{"kind":1,"range":{"end":{"character":12,"line":21},"start":{"character":5,"line":21}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":14}}} +# Verify Read-access of a symbol (kind = 2) +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: clangd/ProtocolHandlers.h =
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 125346. Nebiroth added a comment. Minor code cleanup Refactored findDocumentHighlights() to make tests pass when assertions are enabled Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,42 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 479 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nint test1 = bonjour;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();\n}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Verify local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Verify struct highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Verify method highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":14,"line":2},"start":{"character":7,"line":2}}},{"kind":1,"range":{"end":{"character":22,"line":6},"start":{"character":15,"line":6}}},{"kind":1,"range":{"end":{"character":12,"line":21},"start":{"character":5,"line":21}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":14}}} +# Verify Read-access of a symbol (kind = 2) +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: clangd/ProtocolHandler
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 125522. Nebiroth added a comment. Added error returns in findDocumentHighlights Ran clang-format on ClangdUnit.h, .cpp and ClangdServer.cpp Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,42 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 479 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nint test1 = bonjour;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();\n}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Verify local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Verify struct highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Verify method highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":14,"line":2},"start":{"character":7,"line":2}}},{"kind":1,"range":{"end":{"character":22,"line":6},"start":{"character":15,"line":6}}},{"kind":1,"range":{"end":{"character":12,"line":21},"start":{"character":5,"line":21}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":14}}} +# Verify Read-access of a symbol (kind = 2) +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: clangd/ProtocolHand
[PATCH] D38639: [clangd] #include statements support for Open definition
Nebiroth marked an inline comment as done. Nebiroth added inline comments. Comment at: clangd/ClangdUnit.cpp:38 +class DelegatingPPCallbacks : public PPCallbacks { + ilya-biryukov wrote: > What's the purpose of this class? We need to be able to use a wrapper class to be able to make a unique_ptr to be sent to PrecompiledPreamble::Build in order to add the list of preprocessor Callbacks. https://reviews.llvm.org/D38639 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 125619. Nebiroth added a comment. Added static_cast when unparsing Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,42 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 479 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nint test1 = bonjour;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();\n}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Verify local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Verify struct highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Verify method highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":14,"line":2},"start":{"character":7,"line":2}}},{"kind":1,"range":{"end":{"character":22,"line":6},"start":{"character":15,"line":6}}},{"kind":1,"range":{"end":{"character":12,"line":21},"start":{"character":5,"line":21}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":14}}} +# Verify Read-access of a symbol (kind = 2) +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: clangd/ProtocolHandlers.h ==
[PATCH] D38639: [clangd] #include statements support for Open definition
Nebiroth updated this revision to Diff 125813. Nebiroth added a comment. Herald added a subscriber: klimek. Using PPCallbacks interface to find non-preamble includes Created inner class to store vectors in to find locations Refactored methods to remove some unnecessary parameters Refactored Unit tests Merge with most recent master branch + clang Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38639 Files: clangd/ClangdServer.cpp clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/GlobalCompilationDatabase.cpp clangd/Protocol.h unittests/clangd/ClangdTests.cpp Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -7,7 +7,6 @@ // //===--===// -#include "ClangdLSPServer.h" #include "ClangdServer.h" #include "Logger.h" #include "TestFS.h" @@ -620,7 +619,7 @@ AddDocument(FileIndex); Position Pos{LineDist(RandGen), ColumnDist(RandGen)}; - ASSERT_TRUE(!!Server.findDefinitions(FilePaths[FileIndex], Pos)); + Server.findDefinitions(FilePaths[FileIndex], Pos); }; std::vector> AsyncRequests = { @@ -749,6 +748,58 @@ EXPECT_FALSE(PathResult.hasValue()); } +TEST_F(ClangdVFSTest, CheckDefinitionIncludes) { + MockFSProvider FS; + ErrorCheckingDiagConsumer DiagConsumer; + MockCompilationDatabase CDB; + + ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), + /*StorePreamblesInMemory=*/true, + EmptyLogger::getInstance()); + + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + const auto SourceContents = R"cpp( + #include "foo.h" + #include "invalid.h" + int b = a; + )cpp"; + FS.Files[FooCpp] = SourceContents; + auto FooH = getVirtualTestFilePath("foo.h"); + const auto HeaderContents = "int a;"; + + FS.Files[FooCpp] = SourceContents; + FS.Files[FooH] = HeaderContents; + + Server.addDocument(FooH, HeaderContents); + Server.addDocument(FooCpp, SourceContents); + + Position P = Position{1, 11}; + + std::vector Locations = Server.findDefinitions(FooCpp, P).get().Value; + EXPECT_TRUE(!Locations.empty()); + std::string s("file:///"); + std::string check = Locations[0].uri.uri; + check = check.erase(0, s.size()); + check = check.substr(0, check.size() - 1); + ASSERT_EQ(check, FooH); + ASSERT_EQ(Locations[0].range.start.line, 0); + ASSERT_EQ(Locations[0].range.start.character, 0); + ASSERT_EQ(Locations[0].range.end.line, 0); + ASSERT_EQ(Locations[0].range.end.character, 0); + + // Test ctrl-clicking on the #include part on the statement + Position P3 = Position{1, 3}; + + Locations = Server.findDefinitions(FooCpp, P3).get().Value; + EXPECT_TRUE(!Locations.empty()); + + // Test invalid include + Position P2 = Position{2, 11}; + + Locations = Server.findDefinitions(FooCpp, P2).get().Value; + EXPECT_TRUE(Locations.empty()); +} + TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) { class NoConcurrentAccessDiagConsumer : public DiagnosticsConsumer { public: Index: clangd/Protocol.h === --- clangd/Protocol.h +++ clangd/Protocol.h @@ -108,6 +108,14 @@ bool fromJSON(const json::Expr &, Range &); json::Expr toJSON(const Range &); +class RangeHash { +public: + std::size_t operator()(const Range &R) const { +return ((R.start.line & 0x18) << 3) | ((R.start.character & 0x18) << 1) | + ((R.end.line & 0x18) >> 1) | ((R.end.character & 0x18) >> 3); + } +}; + struct Location { /// The text document's URI. URI uri; Index: clangd/GlobalCompilationDatabase.cpp === --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -9,6 +9,7 @@ #include "GlobalCompilationDatabase.h" #include "Logger.h" +#include "ProtocolHandlers.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" Index: clangd/ClangdUnit.h === --- clangd/ClangdUnit.h +++ clangd/ClangdUnit.h @@ -22,6 +22,7 @@ #include #include #include +#include namespace llvm { class raw_ostream; @@ -59,6 +60,15 @@ std::vector Diags; }; +class IncludeReferenceMap { + llvm::Optional findIncludeTargetAtLoc(Location Loc); + +public: + std::unordered_map IncludeLocationMap; + std::vector> DataVector; + std::vector RangeVector; +}; + /// Stores and provides access to parsed AST. class ParsedAST { public: @@ -69,7 +79,8 @@ std::shared_ptr Preamble, std::unique_ptr Buffer, std::shared_ptr PCHs, -IntrusiveRefCntPtr VFS, clangd::Logger &Logger); +IntrusiveRefCntPtr VFS, clangd::Logger &Logger, +IncludeReferenceMap IRM); ParsedAST(ParsedAST &&Other); ParsedAST &operator=(Parse
[PATCH] D38639: [clangd] #include statements support for Open definition
Nebiroth updated this revision to Diff 125814. Nebiroth added a comment. Fixed re-added include Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38639 Files: clangd/ClangdServer.cpp clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.h unittests/clangd/ClangdTests.cpp Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -7,7 +7,6 @@ // //===--===// -#include "ClangdLSPServer.h" #include "ClangdServer.h" #include "Logger.h" #include "TestFS.h" @@ -620,7 +619,7 @@ AddDocument(FileIndex); Position Pos{LineDist(RandGen), ColumnDist(RandGen)}; - ASSERT_TRUE(!!Server.findDefinitions(FilePaths[FileIndex], Pos)); + Server.findDefinitions(FilePaths[FileIndex], Pos); }; std::vector> AsyncRequests = { @@ -749,6 +748,58 @@ EXPECT_FALSE(PathResult.hasValue()); } +TEST_F(ClangdVFSTest, CheckDefinitionIncludes) { + MockFSProvider FS; + ErrorCheckingDiagConsumer DiagConsumer; + MockCompilationDatabase CDB; + + ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), + /*StorePreamblesInMemory=*/true, + EmptyLogger::getInstance()); + + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + const auto SourceContents = R"cpp( + #include "foo.h" + #include "invalid.h" + int b = a; + )cpp"; + FS.Files[FooCpp] = SourceContents; + auto FooH = getVirtualTestFilePath("foo.h"); + const auto HeaderContents = "int a;"; + + FS.Files[FooCpp] = SourceContents; + FS.Files[FooH] = HeaderContents; + + Server.addDocument(FooH, HeaderContents); + Server.addDocument(FooCpp, SourceContents); + + Position P = Position{1, 11}; + + std::vector Locations = Server.findDefinitions(FooCpp, P).get().Value; + EXPECT_TRUE(!Locations.empty()); + std::string s("file:///"); + std::string check = Locations[0].uri.uri; + check = check.erase(0, s.size()); + check = check.substr(0, check.size() - 1); + ASSERT_EQ(check, FooH); + ASSERT_EQ(Locations[0].range.start.line, 0); + ASSERT_EQ(Locations[0].range.start.character, 0); + ASSERT_EQ(Locations[0].range.end.line, 0); + ASSERT_EQ(Locations[0].range.end.character, 0); + + // Test ctrl-clicking on the #include part on the statement + Position P3 = Position{1, 3}; + + Locations = Server.findDefinitions(FooCpp, P3).get().Value; + EXPECT_TRUE(!Locations.empty()); + + // Test invalid include + Position P2 = Position{2, 11}; + + Locations = Server.findDefinitions(FooCpp, P2).get().Value; + EXPECT_TRUE(Locations.empty()); +} + TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) { class NoConcurrentAccessDiagConsumer : public DiagnosticsConsumer { public: Index: clangd/Protocol.h === --- clangd/Protocol.h +++ clangd/Protocol.h @@ -108,6 +108,14 @@ bool fromJSON(const json::Expr &, Range &); json::Expr toJSON(const Range &); +class RangeHash { +public: + std::size_t operator()(const Range &R) const { +return ((R.start.line & 0x18) << 3) | ((R.start.character & 0x18) << 1) | + ((R.end.line & 0x18) >> 1) | ((R.end.character & 0x18) >> 3); + } +}; + struct Location { /// The text document's URI. URI uri; Index: clangd/ClangdUnit.h === --- clangd/ClangdUnit.h +++ clangd/ClangdUnit.h @@ -22,6 +22,7 @@ #include #include #include +#include namespace llvm { class raw_ostream; @@ -59,6 +60,15 @@ std::vector Diags; }; +class IncludeReferenceMap { + llvm::Optional findIncludeTargetAtLoc(Location Loc); + +public: + std::unordered_map IncludeLocationMap; + std::vector> DataVector; + std::vector RangeVector; +}; + /// Stores and provides access to parsed AST. class ParsedAST { public: @@ -69,7 +79,8 @@ std::shared_ptr Preamble, std::unique_ptr Buffer, std::shared_ptr PCHs, -IntrusiveRefCntPtr VFS, clangd::Logger &Logger); +IntrusiveRefCntPtr VFS, clangd::Logger &Logger, +IncludeReferenceMap IRM); ParsedAST(ParsedAST &&Other); ParsedAST &operator=(ParsedAST &&Other); @@ -89,12 +100,14 @@ const std::vector &getDiagnostics() const; + IncludeReferenceMap takeIRM() { return IRM; }; + private: ParsedAST(std::shared_ptr Preamble, std::unique_ptr Clang, std::unique_ptr Action, std::vector TopLevelDecls, -std::vector Diags); +std::vector Diags, IncludeReferenceMap IRM); private: void ensurePreambleDeclsDeserialized(); @@ -114,6 +127,8 @@ std::vector Diags; std::vector TopLevelDecls; bool PreambleDeclsDeserialized; + std::vector PendingTopLevelDecls; + IncludeReferenceMap IRM; }; // Provides thread-safe access to ParsedAST. @@ -256,14 +271,14 @@ clangd::Logger &Lo
[PATCH] D39375: [clang] Add PPCallbacks list to preprocessor when building a preacompiled preamble.
Nebiroth updated this revision to Diff 125815. Nebiroth added a comment. Reverted formatting changes to ASTUnit Repository: rC Clang https://reviews.llvm.org/D39375 Files: include/clang/Frontend/PrecompiledPreamble.h lib/Frontend/ASTUnit.cpp lib/Frontend/PrecompiledPreamble.cpp Index: lib/Frontend/PrecompiledPreamble.cpp === --- lib/Frontend/PrecompiledPreamble.cpp +++ lib/Frontend/PrecompiledPreamble.cpp @@ -239,7 +239,7 @@ const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr VFS, std::shared_ptr PCHContainerOps, bool StoreInMemory, -PreambleCallbacks &Callbacks) { +PreambleCallbacks &Callbacks, std::unique_ptr PPCallbacks) { assert(VFS && "VFS is null"); if (!Bounds.Size) @@ -351,6 +351,7 @@ if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) return BuildPreambleError::BeginSourceFileFailed; + Clang->getPreprocessor().addPPCallbacks(std::move(PPCallbacks)); Act->Execute(); // Run the callbacks. Index: lib/Frontend/ASTUnit.cpp === --- lib/Frontend/ASTUnit.cpp +++ lib/Frontend/ASTUnit.cpp @@ -1293,7 +1293,7 @@ llvm::ErrorOr NewPreamble = PrecompiledPreamble::Build( PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS, -PCHContainerOps, /*StoreInMemory=*/false, Callbacks); +PCHContainerOps, /*StoreInMemory=*/false, Callbacks, nullptr); if (NewPreamble) { Preamble = std::move(*NewPreamble); PreambleRebuildCounter = 1; Index: include/clang/Frontend/PrecompiledPreamble.h === --- include/clang/Frontend/PrecompiledPreamble.h +++ include/clang/Frontend/PrecompiledPreamble.h @@ -81,7 +81,7 @@ const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr VFS, std::shared_ptr PCHContainerOps, -bool StoreInMemory, PreambleCallbacks &Callbacks); +bool StoreInMemory, PreambleCallbacks &Callbacks, std::unique_ptr PPCallbacks); PrecompiledPreamble(PrecompiledPreamble &&) = default; PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default; Index: lib/Frontend/PrecompiledPreamble.cpp === --- lib/Frontend/PrecompiledPreamble.cpp +++ lib/Frontend/PrecompiledPreamble.cpp @@ -239,7 +239,7 @@ const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr VFS, std::shared_ptr PCHContainerOps, bool StoreInMemory, -PreambleCallbacks &Callbacks) { +PreambleCallbacks &Callbacks, std::unique_ptr PPCallbacks) { assert(VFS && "VFS is null"); if (!Bounds.Size) @@ -351,6 +351,7 @@ if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) return BuildPreambleError::BeginSourceFileFailed; + Clang->getPreprocessor().addPPCallbacks(std::move(PPCallbacks)); Act->Execute(); // Run the callbacks. Index: lib/Frontend/ASTUnit.cpp === --- lib/Frontend/ASTUnit.cpp +++ lib/Frontend/ASTUnit.cpp @@ -1293,7 +1293,7 @@ llvm::ErrorOr NewPreamble = PrecompiledPreamble::Build( PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS, -PCHContainerOps, /*StoreInMemory=*/false, Callbacks); +PCHContainerOps, /*StoreInMemory=*/false, Callbacks, nullptr); if (NewPreamble) { Preamble = std::move(*NewPreamble); PreambleRebuildCounter = 1; Index: include/clang/Frontend/PrecompiledPreamble.h === --- include/clang/Frontend/PrecompiledPreamble.h +++ include/clang/Frontend/PrecompiledPreamble.h @@ -81,7 +81,7 @@ const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr VFS, std::shared_ptr PCHContainerOps, -bool StoreInMemory, PreambleCallbacks &Callbacks); +bool StoreInMemory, PreambleCallbacks &Callbacks, std::unique_ptr PPCallbacks); PrecompiledPreamble(PrecompiledPreamble &&) = default; PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default; ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D39375: [clang] Add PPCallbacks list to preprocessor when building a preacompiled preamble.
Nebiroth added inline comments. Comment at: lib/Frontend/PrecompiledPreamble.cpp:242 std::shared_ptr PCHContainerOps, bool StoreInMemory, -PreambleCallbacks &Callbacks) { +PreambleCallbacks &Callbacks, std::unique_ptr PPCallbacks) { assert(VFS && "VFS is null"); ilya-biryukov wrote: > Could we add a method to `PreambleCallbacks` to create `PPCallbacks` instead? > Otherwise we have both `MacroDefined` in `PreambleCallbacks` and a separate > set of PPCallbacks, so we have two ways of doing the same thing. > > ``` > class PreambleCallbacks { > public: > // ... > > /// Remove this. > virtual void HandleMacroDefined(...); > > // Add this instead. > virtual std::unique_ptr createPPCallbacks(); > > } > ``` > > Alternatively, follow the current pattern in `PreambleCallbacks` and add some > extra functions from the `PPCallbacks` interface to it. This would not > require changes to the existing usages of `PrecompiledPreamble` in `ASTUnit`. > Albeit, I'd prefer the first option. > ``` > class PreambleCallbacks { > public: > // ... > > // Keep this > virtual void HandleMacroDefined(...); > // Add the ones you need, e.g. > virtual void InclusionDirective(...); > virtual void FileChanged(...); > }; > ``` If we were to do that, one would then be required to define a wrapper class for PPCallbacks and create an instance of it inside createPPCallbacks() for the purpose of creating a unique_ptr? Then that unique_ptr would be sent from within the PreambleCallbacks parameter in the Build function? Repository: rC Clang https://reviews.llvm.org/D39375 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D39375: [clang] Add PPCallbacks list to preprocessor when building a preacompiled preamble.
Nebiroth added inline comments. Comment at: lib/Frontend/PrecompiledPreamble.cpp:242 std::shared_ptr PCHContainerOps, bool StoreInMemory, -PreambleCallbacks &Callbacks) { +PreambleCallbacks &Callbacks, std::unique_ptr PPCallbacks) { assert(VFS && "VFS is null"); ilya-biryukov wrote: > Nebiroth wrote: > > ilya-biryukov wrote: > > > Could we add a method to `PreambleCallbacks` to create `PPCallbacks` > > > instead? > > > Otherwise we have both `MacroDefined` in `PreambleCallbacks` and a > > > separate set of PPCallbacks, so we have two ways of doing the same thing. > > > > > > ``` > > > class PreambleCallbacks { > > > public: > > > // ... > > > > > > /// Remove this. > > > virtual void HandleMacroDefined(...); > > > > > > // Add this instead. > > > virtual std::unique_ptr createPPCallbacks(); > > > > > > } > > > ``` > > > > > > Alternatively, follow the current pattern in `PreambleCallbacks` and add > > > some extra functions from the `PPCallbacks` interface to it. This would > > > not require changes to the existing usages of `PrecompiledPreamble` in > > > `ASTUnit`. Albeit, I'd prefer the first option. > > > ``` > > > class PreambleCallbacks { > > > public: > > > // ... > > > > > > // Keep this > > > virtual void HandleMacroDefined(...); > > > // Add the ones you need, e.g. > > > virtual void InclusionDirective(...); > > > virtual void FileChanged(...); > > > }; > > > ``` > > If we were to do that, one would then be required to define a wrapper class > > for PPCallbacks and create an instance of it inside createPPCallbacks() for > > the purpose of creating a unique_ptr? Then that unique_ptr would be sent > > from within the PreambleCallbacks parameter in the Build function? > We're already passing our own wrapper around `PreambleCallbacks` anyway (see > `PreambleMacroCallbacks`), we'll pass the `unique_ptr` instead. > But, yes, the clients will have to write their own implementation of > `PPCallbacks` and pass it as `unique_ptr`. Is there something wrong with that? > > Or, have I misunderstood the question entirely? No this is fine. I was just making sure I understood correctly. Repository: rC Clang https://reviews.llvm.org/D39375 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 126371. Nebiroth marked 3 inline comments as done. Nebiroth added a comment. Herald added a subscriber: mgrang. Merged with latest llvm/clang Minor code cleanup Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,42 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 479 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nint test1 = bonjour;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();\n}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Verify local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Verify struct highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Verify method highlight +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":14,"line":2},"start":{"character":7,"line":2}}},{"kind":1,"range":{"end":{"character":22,"line":6},"start":{"character":15,"line":6}}},{"kind":1,"range":{"end":{"character":12,"line":21},"start":{"character":5,"line":21}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":14}}} +# Verify Read-access of a symbol (kind = 2) +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":11,"line":16},"start":{"character":4,"line":16}}},{"kind":3,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}},{"kind":2,"range":{"end":{"character":19,"line":18},"start":{"character":12,"line":18}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: c
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth added a comment. @ilya-biryukov Need someone to land this. Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38639: [clangd] #include statements support for Open definition
Nebiroth updated this revision to Diff 126429. Nebiroth added a comment. Creating unique_ptr for wrapper class now uses overriden method createPPCallbacks() from PrecompiledPreamble class Moved wrapper class to inline inside createPPCallbacks() Wrapper class now uses CppFilePreambleCallbacks as field Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D38639 Files: clangd/ClangdServer.cpp clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.h unittests/clangd/ClangdTests.cpp Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -7,7 +7,6 @@ // //===--===// -#include "ClangdLSPServer.h" #include "ClangdServer.h" #include "Logger.h" #include "TestFS.h" @@ -620,7 +619,7 @@ AddDocument(FileIndex); Position Pos{LineDist(RandGen), ColumnDist(RandGen)}; - ASSERT_TRUE(!!Server.findDefinitions(FilePaths[FileIndex], Pos)); + Server.findDefinitions(FilePaths[FileIndex], Pos); }; std::vector> AsyncRequests = { @@ -749,6 +748,58 @@ EXPECT_FALSE(PathResult.hasValue()); } +TEST_F(ClangdVFSTest, CheckDefinitionIncludes) { + MockFSProvider FS; + ErrorCheckingDiagConsumer DiagConsumer; + MockCompilationDatabase CDB; + + ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(), + /*StorePreamblesInMemory=*/true, + EmptyLogger::getInstance()); + + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + const auto SourceContents = R"cpp( + #include "foo.h" + #include "invalid.h" + int b = a; + )cpp"; + FS.Files[FooCpp] = SourceContents; + auto FooH = getVirtualTestFilePath("foo.h"); + const auto HeaderContents = "int a;"; + + FS.Files[FooCpp] = SourceContents; + FS.Files[FooH] = HeaderContents; + + Server.addDocument(FooH, HeaderContents); + Server.addDocument(FooCpp, SourceContents); + + Position P = Position{1, 11}; + + std::vector Locations = Server.findDefinitions(FooCpp, P).get().Value; + EXPECT_TRUE(!Locations.empty()); + std::string s("file:///"); + std::string check = Locations[0].uri.uri; + check = check.erase(0, s.size()); + check = check.substr(0, check.size() - 1); + ASSERT_EQ(check, FooH); + ASSERT_EQ(Locations[0].range.start.line, 0); + ASSERT_EQ(Locations[0].range.start.character, 0); + ASSERT_EQ(Locations[0].range.end.line, 0); + ASSERT_EQ(Locations[0].range.end.character, 0); + + // Test ctrl-clicking on the #include part on the statement + Position P3 = Position{1, 3}; + + Locations = Server.findDefinitions(FooCpp, P3).get().Value; + EXPECT_TRUE(!Locations.empty()); + + // Test invalid include + Position P2 = Position{2, 11}; + + Locations = Server.findDefinitions(FooCpp, P2).get().Value; + EXPECT_TRUE(Locations.empty()); +} + TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) { class NoConcurrentAccessDiagConsumer : public DiagnosticsConsumer { public: Index: clangd/Protocol.h === --- clangd/Protocol.h +++ clangd/Protocol.h @@ -108,6 +108,14 @@ bool fromJSON(const json::Expr &, Range &); json::Expr toJSON(const Range &); +class RangeHash { +public: + std::size_t operator()(const Range &R) const { +return ((R.start.line & 0x18) << 3) | ((R.start.character & 0x18) << 1) | + ((R.end.line & 0x18) >> 1) | ((R.end.character & 0x18) >> 3); + } +}; + struct Location { /// The text document's URI. URI uri; Index: clangd/ClangdUnit.h === --- clangd/ClangdUnit.h +++ clangd/ClangdUnit.h @@ -22,6 +22,7 @@ #include #include #include +#include namespace llvm { class raw_ostream; @@ -59,6 +60,15 @@ std::vector Diags; }; +class IncludeReferenceMap { + llvm::Optional findIncludeTargetAtLoc(Location Loc); + +public: + std::unordered_map IncludeLocationMap; + std::vector> DataVector; + std::vector RangeVector; +}; + /// Stores and provides access to parsed AST. class ParsedAST { public: @@ -69,7 +79,8 @@ std::shared_ptr Preamble, std::unique_ptr Buffer, std::shared_ptr PCHs, -IntrusiveRefCntPtr VFS, clangd::Logger &Logger); +IntrusiveRefCntPtr VFS, clangd::Logger &Logger, +IncludeReferenceMap IRM); ParsedAST(ParsedAST &&Other); ParsedAST &operator=(ParsedAST &&Other); @@ -89,12 +100,14 @@ const std::vector &getDiagnostics() const; + IncludeReferenceMap takeIRM() { return IRM; }; + private: ParsedAST(std::shared_ptr Preamble, std::unique_ptr Clang, std::unique_ptr Action, std::vector TopLevelDecls, -std::vector Diags); +std::vector Diags, IncludeReferenceMap IRM); private: void ensurePreambleDeclsDeserialized(); @@ -114,6 +127,8 @@ std::vector Diags; std::vect
[PATCH] D39375: [clang] Add PPCallbacks list to preprocessor when building a preacompiled preamble.
Nebiroth updated this revision to Diff 126430. Nebiroth added a comment. Removed unique_ptr parameter in PrecompiledPreamble::Build Added method createPPCallbacks() in PreambleCallback to be overriden Repository: rC Clang https://reviews.llvm.org/D39375 Files: include/clang/Frontend/PrecompiledPreamble.h lib/Frontend/PrecompiledPreamble.cpp Index: lib/Frontend/PrecompiledPreamble.cpp === --- lib/Frontend/PrecompiledPreamble.cpp +++ lib/Frontend/PrecompiledPreamble.cpp @@ -351,6 +351,8 @@ if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) return BuildPreambleError::BeginSourceFileFailed; + if (Callbacks.createPPCallbacks()) + Clang->getPreprocessor().addPPCallbacks(std::move(Callbacks.createPPCallbacks())); Act->Execute(); // Run the callbacks. @@ -709,6 +711,7 @@ void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {} void PreambleCallbacks::HandleMacroDefined(const Token &MacroNameTok, const MacroDirective *MD) {} +std::unique_ptr PreambleCallbacks::createPPCallbacks() {return nullptr;} std::error_code clang::make_error_code(BuildPreambleError Error) { return std::error_code(static_cast(Error), BuildPreambleErrorCategory()); Index: include/clang/Frontend/PrecompiledPreamble.h === --- include/clang/Frontend/PrecompiledPreamble.h +++ include/clang/Frontend/PrecompiledPreamble.h @@ -260,6 +260,9 @@ /// used instead, but having only this method allows a simpler API. virtual void HandleMacroDefined(const Token &MacroNameTok, const MacroDirective *MD); + /// Adds list of Preprocessor callbacks so we can also process information + /// about includes that are outside of a preamble i.e in the middle of a file + virtual std::unique_ptr createPPCallbacks(); }; enum class BuildPreambleError { Index: lib/Frontend/PrecompiledPreamble.cpp === --- lib/Frontend/PrecompiledPreamble.cpp +++ lib/Frontend/PrecompiledPreamble.cpp @@ -351,6 +351,8 @@ if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) return BuildPreambleError::BeginSourceFileFailed; + if (Callbacks.createPPCallbacks()) +Clang->getPreprocessor().addPPCallbacks(std::move(Callbacks.createPPCallbacks())); Act->Execute(); // Run the callbacks. @@ -709,6 +711,7 @@ void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {} void PreambleCallbacks::HandleMacroDefined(const Token &MacroNameTok, const MacroDirective *MD) {} +std::unique_ptr PreambleCallbacks::createPPCallbacks() {return nullptr;} std::error_code clang::make_error_code(BuildPreambleError Error) { return std::error_code(static_cast(Error), BuildPreambleErrorCategory()); Index: include/clang/Frontend/PrecompiledPreamble.h === --- include/clang/Frontend/PrecompiledPreamble.h +++ include/clang/Frontend/PrecompiledPreamble.h @@ -260,6 +260,9 @@ /// used instead, but having only this method allows a simpler API. virtual void HandleMacroDefined(const Token &MacroNameTok, const MacroDirective *MD); + /// Adds list of Preprocessor callbacks so we can also process information + /// about includes that are outside of a preamble i.e in the middle of a file + virtual std::unique_ptr createPPCallbacks(); }; enum class BuildPreambleError { ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D39571: [clangd] DidChangeConfiguration Notification
Nebiroth updated this revision to Diff 126447. Nebiroth added a comment. Herald added a subscriber: klimek. Merged with latest llvm + clang Minor code cleanup Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D39571 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/DraftStore.cpp clangd/DraftStore.h clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/did-change-configuration.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -18,6 +18,7 @@ # CHECK-NEXT: ":" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "configurationChangeProvider": true, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -18,6 +18,7 @@ # CHECK-NEXT: ":" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "configurationChangeProvider": true, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { Index: test/clangd/did-change-configuration.test === --- /dev/null +++ test/clangd/did-change-configuration.test @@ -0,0 +1,46 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 150 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///foo.c","languageId":"c","version":1,"text":"voidmain(){}"}}} + +Content-Length: 86 + +{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":""}} +#Failed to decode workspace/didChangeConfiguration request. +#Incorrect mapping node + +Content-Length: 114 + +{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabasePath":{ +#Failed to decode workspace/didChangeConfiguration request. +#compilationDatabasePath is not a scalar node + +Content-Length: 140 + +{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabasePath":"/","testBadValue":"foo1234"}}} +#Ignored unknown field "testBadValue" +#Failed to find compilation database for / in overriden directory / +#Bad field, bad compilation database + +Content-Length: 722 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///compile_commands.json","languageId":"json","version":1,"text":"[\n{\n"directory":"/",\n"command":"/usr/bin/c++-DGTEST_HAS_RTTI=0-D_GNU_SOURCE-D__STDC_CONSTANT_MACROS-D__STDC_FORMAT_MACROS-D__STDC_LIMIT_MACROS-Ilib/Demangle-I../lib/Demangle-I/usr/include/libxml2-Iinclude-I../include-fPIC-fvisibility-inlines-hidden-Werror=date-time-std=c++11-Wall-W-Wno-unused-parameter-Wwrite-strings-Wcast-qual-Wno-missing-field-initializers-pedantic-Wno-long-long-Wno-maybe-uninitialized-Wdelete-non-virtual-dtor-Wno-comment-O0-g-fno-exceptions-fno-rtti-o/foo.c.o-c/foo.c",\n"file":"/foo.c"\n},"}}} + +Content-Length: 115 + +{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabasePath":"/"}}} +#CHECK:{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"diagnostics":[{"message":"type specifier missing, defaults to 'int'","range":{"end":{"character":1,"line":0},"start":{"character":1,"line":0}},"severity":2},{"message":"control reaches end of non-void function","range":{"end":{"character":12,"line":0},"start":{"character":12,"line":0}},"severity":2}],"uri":"file:///foo.c"}} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -54,6 +54,8 @@ virtual void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) = 0; virtual void onCommand(Ctx C, ExecuteCommandParams &Params) = 0; virtual void onRename(Ctx C, RenameParams &Parames) = 0; + virtual void onChangeConfiguration(Ctx C, + DidChangeConfigurationParams &
[PATCH] D39571: [clangd] DidChangeConfiguration Notification
Nebiroth updated this revision to Diff 126449. Nebiroth added a comment. Removed some more empty lines Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D39571 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/DraftStore.cpp clangd/DraftStore.h clangd/GlobalCompilationDatabase.cpp clangd/GlobalCompilationDatabase.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/did-change-configuration.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -18,6 +18,7 @@ # CHECK-NEXT: ":" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "configurationChangeProvider": true, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -18,6 +18,7 @@ # CHECK-NEXT: ":" # CHECK-NEXT:] # CHECK-NEXT: }, +# CHECK-NEXT: "configurationChangeProvider": true, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { Index: test/clangd/did-change-configuration.test === --- /dev/null +++ test/clangd/did-change-configuration.test @@ -0,0 +1,46 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 150 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///foo.c","languageId":"c","version":1,"text":"voidmain(){}"}}} + +Content-Length: 86 + +{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":""}} +#Failed to decode workspace/didChangeConfiguration request. +#Incorrect mapping node + +Content-Length: 114 + +{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabasePath":{ +#Failed to decode workspace/didChangeConfiguration request. +#compilationDatabasePath is not a scalar node + +Content-Length: 140 + +{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabasePath":"/","testBadValue":"foo1234"}}} +#Ignored unknown field "testBadValue" +#Failed to find compilation database for / in overriden directory / +#Bad field, bad compilation database + +Content-Length: 722 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///compile_commands.json","languageId":"json","version":1,"text":"[\n{\n"directory":"/",\n"command":"/usr/bin/c++-DGTEST_HAS_RTTI=0-D_GNU_SOURCE-D__STDC_CONSTANT_MACROS-D__STDC_FORMAT_MACROS-D__STDC_LIMIT_MACROS-Ilib/Demangle-I../lib/Demangle-I/usr/include/libxml2-Iinclude-I../include-fPIC-fvisibility-inlines-hidden-Werror=date-time-std=c++11-Wall-W-Wno-unused-parameter-Wwrite-strings-Wcast-qual-Wno-missing-field-initializers-pedantic-Wno-long-long-Wno-maybe-uninitialized-Wdelete-non-virtual-dtor-Wno-comment-O0-g-fno-exceptions-fno-rtti-o/foo.c.o-c/foo.c",\n"file":"/foo.c"\n},"}}} + +Content-Length: 115 + +{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabasePath":"/"}}} +#CHECK:{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"diagnostics":[{"message":"type specifier missing, defaults to 'int'","range":{"end":{"character":1,"line":0},"start":{"character":1,"line":0}},"severity":2},{"message":"control reaches end of non-void function","range":{"end":{"character":12,"line":0},"start":{"character":12,"line":0}},"severity":2}],"uri":"file:///foo.c"}} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -54,6 +54,8 @@ virtual void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) = 0; virtual void onCommand(Ctx C, ExecuteCommandParams &Params) = 0; virtual void onRename(Ctx C, RenameParams &Parames) = 0; + virtual void onChangeConfiguration(Ctx C, + DidChangeConfigurationParams &Params) = 0; }; void registerCallbackHandlers(JSONRP
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth updated this revision to Diff 108979. Nebiroth marked 19 inline comments as done. Nebiroth added a comment. Implemention of Code Hover as described in LSP definition. Removed unintentional changes to formatting. Removed file id field in Location struct. https://reviews.llvm.org/D35894 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h clangd/clients/clangd-vscode/src/extension.ts test/clangd/hover.test Index: test/clangd/hover.test === --- /dev/null +++ test/clangd/hover.test @@ -0,0 +1,26 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 172 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"int main() {\nint a;\na;\n}\n"}}} + +Content-Length: 143 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":0,"character":5}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":{"contents": {"language": "C++", "value": "int main() {\nint a;\na;\n}"}, "range": {"start": {"line": 0, "character": 0}, "end": {"line": 3, "character": 1 + +Content-Length: 143 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":1,"character":5}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":{"contents": {"language": "C++", "value": "int a"}, "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 5 + +Content-Length: 44 + +{"jsonrpc":"2.0","id":3,"method":"shutdown"} Index: clangd/clients/clangd-vscode/src/extension.ts === --- clangd/clients/clangd-vscode/src/extension.ts +++ clangd/clients/clangd-vscode/src/extension.ts @@ -1,5 +1,6 @@ import * as vscode from 'vscode'; import * as vscodelc from 'vscode-languageclient'; +import * as vscodejsonrpc from 'vscode-jsonrpc'; /** * Method to get workspace configuration option Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -48,6 +48,8 @@ JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; + virtual void onCodeHover(TextDocumentPositionParams Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,24 @@ ProtocolCallbacks &Callbacks; }; +struct CodeHoverHandler : Handler { + CodeHoverHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentPositionParams::parse(Params); +if (!TDPP) { + Output.log("Failed to decode TextDocumentPositionParams!\n"); + return; +} + +Callbacks.onCodeHover(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -239,4 +257,7 @@ llvm::make_unique(Out, Callbacks)); Dispatcher.registerHandler("textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/hover", + llvm::make_unique(Out, Callbacks)); } Index: clangd/Protocol.h === --- clangd/Protocol.h +++ clangd/Protocol.h @@ -23,6 +23,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/Support/YAMLParser.h" +#include "clang/Basic/SourceLocation.h" #include #include @@ -304,7 +305,59 @@ parse(llvm::yaml::MappingNode *Params); }; -/// The kind of a completion entry. +struct MarkedString { + /** + * MarkedString can be used to render human readable text. It is either a + * markdown string + * or a code-block that provides a language and a code snippet. The language + * identifier + * is sematically equal to the optional language identifier in fenced code + * blocks in GitHub + * issues. See + * https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting + * + * The pair of a la
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth added a comment. I had missed a typo in the code, should be fixed and compiling properly now. https://reviews.llvm.org/D35894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth updated this revision to Diff 108997. Nebiroth added a comment. Implemention of Code Hover as described in LSP definition. Removed unintentional changes to formatting. Removed file id field in Location struct. https://reviews.llvm.org/D35894 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h clangd/clients/clangd-vscode/src/extension.ts test/clangd/hover.test Index: test/clangd/hover.test === --- /dev/null +++ test/clangd/hover.test @@ -0,0 +1,26 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 172 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"int main() {\nint a;\na;\n}\n"}}} + +Content-Length: 143 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":0,"character":5}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":{"contents": {"language": "C++", "value": "int main() {\nint a;\na;\n}"}, "range": {"start": {"line": 0, "character": 0}, "end": {"line": 3, "character": 1 + +Content-Length: 143 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":1,"character":5}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":{"contents": {"language": "C++", "value": "int a"}, "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 5 + +Content-Length: 44 + +{"jsonrpc":"2.0","id":3,"method":"shutdown"} Index: clangd/clients/clangd-vscode/src/extension.ts === --- clangd/clients/clangd-vscode/src/extension.ts +++ clangd/clients/clangd-vscode/src/extension.ts @@ -1,5 +1,6 @@ import * as vscode from 'vscode'; import * as vscodelc from 'vscode-languageclient'; +import * as vscodejsonrpc from 'vscode-jsonrpc'; /** * Method to get workspace configuration option Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -48,6 +48,8 @@ JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; + virtual void onCodeHover(TextDocumentPositionParams Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,24 @@ ProtocolCallbacks &Callbacks; }; +struct CodeHoverHandler : Handler { + CodeHoverHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentPositionParams::parse(Params); +if (!TDPP) { + Output.log("Failed to decode TextDocumentPositionParams!\n"); + return; +} + +Callbacks.onCodeHover(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -239,4 +257,7 @@ llvm::make_unique(Out, Callbacks)); Dispatcher.registerHandler("textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/hover", + llvm::make_unique(Out, Callbacks)); } Index: clangd/Protocol.h === --- clangd/Protocol.h +++ clangd/Protocol.h @@ -23,6 +23,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/Support/YAMLParser.h" +#include "clang/Basic/SourceLocation.h" #include #include @@ -304,7 +305,59 @@ parse(llvm::yaml::MappingNode *Params); }; -/// The kind of a completion entry. +struct MarkedString { + /** + * MarkedString can be used to render human readable text. It is either a + * markdown string + * or a code-block that provides a language and a code snippet. The language + * identifier + * is sematically equal to the optional language identifier in fenced code + * blocks in GitHub + * issues. See + * https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting + * + * The pair of a language and a value is an equivalent to markd
[PATCH] D36150: [clangd] LSP extension to switch between source/header file
Nebiroth created this revision. Small extension to LSP to allow clients to use clangd to switch between C header files and source files. Final version will use the completed clangd indexer. https://reviews.llvm.org/D36150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/hover.test Index: test/clangd/hover.test === --- /dev/null +++ test/clangd/hover.test @@ -0,0 +1,26 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 172 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"int main() {\nint a;\na;\n}\n"}}} + +Content-Length: 143 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":0,"character":5}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":{"contents": {"language": "C++", "value": "int main() {\nint a;\na;\n}"}, "range": {"start": {"line": 0, "character": 0}, "end": {"line": 3, "character": 1 + +Content-Length: 143 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":1,"character":5}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":{"contents": {"language": "C++", "value": "int a"}, "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 5 + +Content-Length: 44 + +{"jsonrpc":"2.0","id":3,"method":"shutdown"} Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -48,6 +48,8 @@ JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; + virtual void onSwitchSourceHeader(TextDocumentIdentifier Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,23 @@ ProtocolCallbacks &Callbacks; }; +struct SwitchSourceHeaderHandler : Handler { + SwitchSourceHeaderHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentIdentifier::parse(Params); +if (!TDPP) { + return; +} + +Callbacks.onSwitchSourceHeader(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -239,4 +256,7 @@ llvm::make_unique(Out, Callbacks)); Dispatcher.registerHandler("textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/switchSourceHeader", + llvm::make_unique(Out, Callbacks)); } Index: clangd/ClangdServer.h === --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -182,6 +182,8 @@ /// Get definition of symbol at a specified \p Line and \p Column in \p File. Tagged> findDefinitions(PathRef File, Position Pos); + std::string switchSourceHeader(std::string path); + /// Run formatting for \p Rng inside \p File. std::vector formatRange(PathRef File, Range Rng); /// Run formatting for the whole \p File. Index: clangd/ClangdServer.cpp === --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -286,3 +286,18 @@ }); return make_tagged(std::move(Result), TaggedFS.Tag); } + +std::string ClangdServer::switchSourceHeader(std::string path) { + + if (path.compare(path.length() - 4, 4, ".cpp") == 0) { +path = path.substr(0, (path.length() - 4)); +path.append(".h"); +return "\"" + path + "\""; + } else if (path.compare(path.length() - 2, 2, ".h") == 0) { +path = path.substr(0, (path.length() - 2)); +path.append(".cpp"); +return "\"" + path + "\""; + } else { +return ""; + } +} Index: clangd/ClangdLSPServer.cpp === --- clangd/ClangdLSPServer.cpp +++ clangd/ClangdLSPServer.cpp @@ -71,6 +71,8 @@ JSONOutput &Out) override; void onGoToDefinition(TextDocumentPositionParams Params, StringR
[PATCH] D36150: [clangd] LSP extension to switch between source/header file
Nebiroth updated this revision to Diff 109566. Nebiroth marked 7 inline comments as done. Nebiroth added a comment. [clangd] LSP extension to switch between source/header file https://reviews.llvm.org/D36150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -48,6 +48,8 @@ JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; + virtual void onSwitchSourceHeader(TextDocumentIdentifier Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,23 @@ ProtocolCallbacks &Callbacks; }; +struct SwitchSourceHeaderHandler : Handler { + SwitchSourceHeaderHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentIdentifier::parse(Params); +if (!TDPP) { + return; +} + +Callbacks.onSwitchSourceHeader(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -239,4 +256,7 @@ llvm::make_unique(Out, Callbacks)); Dispatcher.registerHandler("textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/switchSourceHeader", + llvm::make_unique(Out, Callbacks)); } Index: clangd/ClangdServer.h === --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -182,6 +182,9 @@ /// Get definition of symbol at a specified \p Line and \p Column in \p File. Tagged> findDefinitions(PathRef File, Position Pos); + // Helper function to change from one header file to it's corresponding source file and vice versa + Path switchSourceHeader(PathRef path); + /// Run formatting for \p Rng inside \p File. std::vector formatRange(PathRef File, Range Rng); /// Run formatting for the whole \p File. Index: clangd/ClangdServer.cpp === --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -16,13 +16,15 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Path.h" #include using namespace clang; using namespace clang::clangd; namespace { + std::vector formatCode(StringRef Code, StringRef Filename, ArrayRef Ranges) { // Call clang-format. @@ -286,3 +288,86 @@ }); return make_tagged(std::move(Result), TaggedFS.Tag); } + +Path ClangdServer::switchSourceHeader(PathRef path) { + + std::string DEFAULT_SOURCE_EXTENSIONS[] = { ".cpp", ".c", ".cc", ".cxx", +".c++", ".C", ".m", ".mm" }; + std::string DEFAULT_HEADER_EXTENSIONS[] = { ".h", ".hh", ".hpp", ".hxx", +".inc" }; + + const int sourceSize = sizeof(DEFAULT_SOURCE_EXTENSIONS)/sizeof(DEFAULT_SOURCE_EXTENSIONS[0]); + const int headerSize = sizeof(DEFAULT_HEADER_EXTENSIONS)/sizeof(DEFAULT_HEADER_EXTENSIONS[0]); + + std::string pathDataRef = std::string(path.data()); + bool isSourceFile = false, foundExtension = false; + SmallString<128> NewPath; + int i = 0; + + while (!foundExtension && i < sourceSize) + { +if (llvm::sys::path::extension(pathDataRef) == DEFAULT_SOURCE_EXTENSIONS[i]) +{ + std::string fileExtension = std::string(DEFAULT_SOURCE_EXTENSIONS[i]); + NewPath = pathDataRef; + pathDataRef = pathDataRef.substr(0, (pathDataRef.length() - fileExtension.size())); + isSourceFile = true; + foundExtension = true; +} +i++; + } + i = 0; + + if (!foundExtension) + { +while (!foundExtension && i < headerSize) +{ + if (llvm::sys::path::extension(pathDataRef) == DEFAULT_HEADER_EXTENSIONS[i]) + { +std::string fileExtension = std::string(DEFAULT_HEADER_EXTENSIONS[i]); +NewPath = pathDataRef; +pathDataRef = pathDataRef.substr(0, (pathDataRef.length() - fileExtension.size())); +isSourceFile = false; +foundExtension = true; + } +i++; +} + } + + std::string temp = std::string(pathDataRef); + SmallString<128> CurrentPath; + CurrentPath = temp; + bool done = false; + std::vector EXTENSIONS_ARRAY; + + if (!isSourceFile) +EXTENSIONS_ARRAY.assign(DEFAULT
[PATCH] D36150: [clangd] LSP extension to switch between source/header file
Nebiroth updated this revision to Diff 111368. Nebiroth marked 8 inline comments as done. Nebiroth added a comment. Fixed diff comments. https://reviews.llvm.org/D36150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -48,6 +48,8 @@ JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; + virtual void onSwitchSourceHeader(TextDocumentIdentifier Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,23 @@ ProtocolCallbacks &Callbacks; }; +struct SwitchSourceHeaderHandler : Handler { + SwitchSourceHeaderHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentIdentifier::parse(Params); +if (!TDPP) { + return; +} + +Callbacks.onSwitchSourceHeader(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -239,4 +256,7 @@ llvm::make_unique(Out, Callbacks)); Dispatcher.registerHandler("textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/switchSourceHeader", + llvm::make_unique(Out, Callbacks)); } Index: clangd/ClangdServer.h === --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -182,6 +182,9 @@ /// Get definition of symbol at a specified \p Line and \p Column in \p File. Tagged> findDefinitions(PathRef File, Position Pos); + /// Helper function that returns a path to the corresponding source file when given a header file and vice versa. + Path switchSourceHeader(PathRef path); + /// Run formatting for \p Rng inside \p File. std::vector formatRange(PathRef File, Range Rng); /// Run formatting for the whole \p File. Index: clangd/ClangdServer.cpp === --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -15,6 +15,7 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include @@ -286,3 +287,82 @@ }); return make_tagged(std::move(Result), TaggedFS.Tag); } + +Path ClangdServer::switchSourceHeader(PathRef path) { + + std::string DEFAULT_SOURCE_EXTENSIONS[] = { + ".cpp", ".c", ".cc", ".cxx", ".c++", ".m", ".mm", + ".CPP", ".C", ".CC", ".CXX", ".C++", ".M", ".MM"}; + std::string DEFAULT_HEADER_EXTENSIONS[] = { + ".h", ".hh", ".hpp", ".hxx", ".inc", ".H", ".HH", ".HPP", ".HXX", ".INC"}; + + const int sourceSize = + sizeof(DEFAULT_SOURCE_EXTENSIONS) / sizeof(DEFAULT_SOURCE_EXTENSIONS[0]); + const int headerSize = + sizeof(DEFAULT_HEADER_EXTENSIONS) / sizeof(DEFAULT_HEADER_EXTENSIONS[0]); + + std::string pathDataRef = std::string(path); + bool isSourceFile = false, foundExtension = false; + SmallString<128> NewPath; + std::string *p; + p = std::find(DEFAULT_SOURCE_EXTENSIONS, +DEFAULT_SOURCE_EXTENSIONS + sourceSize, +llvm::sys::path::extension(path)); + if (p != DEFAULT_SOURCE_EXTENSIONS + sourceSize) + { +std::string fileExtension = *p; +NewPath = pathDataRef; +pathDataRef = +pathDataRef.substr(0, (pathDataRef.size() - fileExtension.size())); +isSourceFile = true; +foundExtension = true; + } + + if (!foundExtension) { +p = std::find(DEFAULT_HEADER_EXTENSIONS, + DEFAULT_HEADER_EXTENSIONS + headerSize, + llvm::sys::path::extension(path)); +if (p != DEFAULT_HEADER_EXTENSIONS + headerSize) { + std::string fileExtension = *p; + NewPath = pathDataRef; + pathDataRef = + pathDataRef.substr(0, (pathDataRef.size() - fileExtension.size())); + isSourceFile = false; + foundExtension = true; +} + } + + SmallString<128> CurrentPath; + CurrentPath = std::string(pathDataRef); + bool done = false; + ArrayRef ExtensionsArray; + + if (!isSourceFile) +ExtensionsArray = DEFAULT_SOURCE_EXTENSIONS; + else +ExtensionsArray = DEFAULT_HEADER_EXTENSIONS; + + int i = 0; + while (!done && i < ExtensionsArray.size()) {
[PATCH] D36150: [clangd] LSP extension to switch between source/header file
Nebiroth updated this revision to Diff 111675. Nebiroth added a comment. Fixed more diff comments. https://reviews.llvm.org/D36150 Files: clangd/ClangdLSPServer.cpp clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -48,6 +48,8 @@ JSONOutput &Out) = 0; virtual void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) = 0; + virtual void onSwitchSourceHeader(TextDocumentIdentifier Params, StringRef ID, +JSONOutput &Out) = 0; }; void regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -204,6 +204,23 @@ ProtocolCallbacks &Callbacks; }; +struct SwitchSourceHeaderHandler : Handler { + SwitchSourceHeaderHandler(JSONOutput &Output, ProtocolCallbacks &Callbacks) + : Handler(Output), Callbacks(Callbacks) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override { +auto TDPP = TextDocumentIdentifier::parse(Params); +if (!TDPP) { + return; +} + +Callbacks.onSwitchSourceHeader(*TDPP, ID, Output); + } + +private: + ProtocolCallbacks &Callbacks; +}; + } // namespace void clangd::regiterCallbackHandlers(JSONRPCDispatcher &Dispatcher, @@ -239,4 +256,7 @@ llvm::make_unique(Out, Callbacks)); Dispatcher.registerHandler("textDocument/definition", llvm::make_unique(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/switchSourceHeader", + llvm::make_unique(Out, Callbacks)); } Index: clangd/ClangdServer.h === --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -182,6 +182,9 @@ /// Get definition of symbol at a specified \p Line and \p Column in \p File. Tagged> findDefinitions(PathRef File, Position Pos); + /// Helper function that returns a path to the corresponding source file when given a header file and vice versa. + Path switchSourceHeader(PathRef path); + /// Run formatting for \p Rng inside \p File. std::vector formatRange(PathRef File, Range Rng); /// Run formatting for the whole \p File. Index: clangd/ClangdServer.cpp === --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -15,6 +15,7 @@ #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include @@ -286,3 +287,127 @@ }); return make_tagged(std::move(Result), TaggedFS.Tag); } + +Path ClangdServer::switchSourceHeader(PathRef path) { + + std::string DEFAULT_SOURCE_EXTENSIONS[] = {".cpp", ".c", ".cc", ".cxx", ".c++", ".m", ".mm"}; + std::string DEFAULT_HEADER_EXTENSIONS[] = {".h", ".hh", ".hpp", ".hxx", ".inc"}; + + const int sourceSize = sizeof(DEFAULT_SOURCE_EXTENSIONS) / sizeof(DEFAULT_SOURCE_EXTENSIONS[0]); + const int headerSize = sizeof(DEFAULT_HEADER_EXTENSIONS) / sizeof(DEFAULT_HEADER_EXTENSIONS[0]); + + bool isSourceFile = false, foundExtension = false; + SmallString<128> NewPath; + std::string *p; + p = std::find(DEFAULT_SOURCE_EXTENSIONS, +DEFAULT_SOURCE_EXTENSIONS + sourceSize, +llvm::sys::path::extension(path)); + if (p != DEFAULT_SOURCE_EXTENSIONS + sourceSize) + { +std::string fileExtension = *p; +NewPath = path; +path = path.substr(0, (path.size() - fileExtension.size())); +isSourceFile = true; +foundExtension = true; + } + else + { +std::string cpy[sourceSize]; +std::copy(DEFAULT_SOURCE_EXTENSIONS, DEFAULT_SOURCE_EXTENSIONS + sourceSize, cpy); +for (std::string & s : cpy) +std::transform(s.begin(), s.end(), s.begin(), + [](unsigned char c) { return std::toupper(c); }); + +p = std::find(cpy, cpy + sourceSize, llvm::sys::path::extension(path)); +if (p != cpy + sourceSize) +{ +std::string fileExtension = *p; +NewPath = path; +path = path.substr(0, (path.size() - fileExtension.size())); +isSourceFile = true; +foundExtension = true; +} + } + + if (!foundExtension) { +p = std::find(DEFAULT_HEADER_EXTENSIONS, + DEFAULT_HEADER_EXTENSIONS + headerSize, + llvm::sys::path::extension(path)); +if (p != DEFAULT_HEADER_EXTENSIONS + headerSize) +{ + std::string fileExtension = *p; + NewPath = path; + path = path.substr(0, (path.size() - fileExtension.size())); + isSourceFile = false; + foundExtension = true; +} +else +
[PATCH] D38639: [clangd] #include statements support for Open definition
Nebiroth updated this revision to Diff 120482. Nebiroth added a comment. - Now overriding InclusionDirective as a callback to get proper includes information. - Fixed tests. https://reviews.llvm.org/D38639 Files: clangd/ClangdServer.cpp clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/GlobalCompilationDatabase.cpp clangd/Protocol.h test/clangd/documenthighlight.test unittests/clangd/ClangdTests.cpp Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -7,7 +7,6 @@ // //===--===// -#include "ClangdLSPServer.h" #include "ClangdServer.h" #include "Logger.h" #include "clang/Basic/VirtualFileSystem.h" @@ -1056,7 +1055,7 @@ AddDocument(FileIndex); Position Pos{LineDist(RandGen), ColumnDist(RandGen)}; - ASSERT_TRUE(!!Server.findDefinitions(FilePaths[FileIndex], Pos)); + Server.findDefinitions(FilePaths[FileIndex], Pos); }; std::vector> AsyncRequests = { @@ -1185,6 +1184,57 @@ EXPECT_FALSE(PathResult.hasValue()); } +TEST_F(ClangdVFSTest, CheckDefinitionIncludes) { + MockFSProvider FS; + ErrorCheckingDiagConsumer DiagConsumer; + MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true); + + ClangdServer Server(CDB, DiagConsumer, FS, 0, clangd::CodeCompleteOptions(), + EmptyLogger::getInstance()); + + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + const auto SourceContents = R"cpp( + #include "foo.h" + #include "invalid.h" + int b = a; + )cpp"; + FS.Files[FooCpp] = SourceContents; + auto FooH = getVirtualTestFilePath("foo.h"); + const auto HeaderContents = "int a;"; + + FS.Files[FooCpp] = SourceContents; + FS.Files[FooH] = HeaderContents; + + Server.addDocument(FooH, HeaderContents); + Server.addDocument(FooCpp, SourceContents); + + Position P = Position{1, 11}; + + std::vector Locations = Server.findDefinitions(FooCpp, P).get().Value; + EXPECT_TRUE(!Locations.empty()); + std::string s("file:///"); + std::string check = URI::unparse(Locations[0].uri); + check = check.erase(0, s.size()); + check = check.substr(0, check.size() - 1); + ASSERT_EQ(check, FooH); + ASSERT_EQ(Locations[0].range.start.line, 0); + ASSERT_EQ(Locations[0].range.start.character, 0); + ASSERT_EQ(Locations[0].range.end.line, 0); + ASSERT_EQ(Locations[0].range.end.character, 0); + + // Test ctrl-clicking on the #include part on the statement + Position P3 = Position{1, 3}; + + Locations = Server.findDefinitions(FooCpp, P3).get().Value; + EXPECT_TRUE(!Locations.empty()); + + // Test invalid include + Position P2 = Position{2, 11}; + + Locations = Server.findDefinitions(FooCpp, P2).get().Value; + EXPECT_TRUE(Locations.empty()); +} + TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) { class NoConcurrentAccessDiagConsumer : public DiagnosticsConsumer { public: Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,42 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} +# CHECK: Content-Length: 580 +# CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{ +# CHECK: "textDocumentSync": 1, +# CHECK: "documentFormattingProvider": true, +# CHECK: "documentRangeFormattingProvider": true, +# CHECK: "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]}, +# CHECK: "codeActionProvider": true, +# CHECK: "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]}, +# CHECK: "signatureHelpProvider": {"triggerCharacters": ["(",","]}, +# CHECK: "definitionProvider": true, +# CHECK: "documentHighlightProvider": true +# CHECK: }}} +# + +Content-Length: 455 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":[{"range": {"start": {"line": 16, "character": 4}, "end": {"line": 16, "character": 12}}, "kind": 1},{"range": {"start": {"line": 17, "character": 0}, "end": {"line":
[PATCH] D38639: [clangd] #include statements support for Open definition
Nebiroth updated this revision to Diff 120485. Nebiroth added a comment. - Fixed adding incorrect test file. https://reviews.llvm.org/D38639 Files: clangd/ClangdServer.cpp clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/GlobalCompilationDatabase.cpp clangd/Protocol.h unittests/clangd/ClangdTests.cpp Index: unittests/clangd/ClangdTests.cpp === --- unittests/clangd/ClangdTests.cpp +++ unittests/clangd/ClangdTests.cpp @@ -7,7 +7,6 @@ // //===--===// -#include "ClangdLSPServer.h" #include "ClangdServer.h" #include "Logger.h" #include "clang/Basic/VirtualFileSystem.h" @@ -1056,7 +1055,7 @@ AddDocument(FileIndex); Position Pos{LineDist(RandGen), ColumnDist(RandGen)}; - ASSERT_TRUE(!!Server.findDefinitions(FilePaths[FileIndex], Pos)); + Server.findDefinitions(FilePaths[FileIndex], Pos); }; std::vector> AsyncRequests = { @@ -1185,6 +1184,57 @@ EXPECT_FALSE(PathResult.hasValue()); } +TEST_F(ClangdVFSTest, CheckDefinitionIncludes) { + MockFSProvider FS; + ErrorCheckingDiagConsumer DiagConsumer; + MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true); + + ClangdServer Server(CDB, DiagConsumer, FS, 0, clangd::CodeCompleteOptions(), + EmptyLogger::getInstance()); + + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + const auto SourceContents = R"cpp( + #include "foo.h" + #include "invalid.h" + int b = a; + )cpp"; + FS.Files[FooCpp] = SourceContents; + auto FooH = getVirtualTestFilePath("foo.h"); + const auto HeaderContents = "int a;"; + + FS.Files[FooCpp] = SourceContents; + FS.Files[FooH] = HeaderContents; + + Server.addDocument(FooH, HeaderContents); + Server.addDocument(FooCpp, SourceContents); + + Position P = Position{1, 11}; + + std::vector Locations = Server.findDefinitions(FooCpp, P).get().Value; + EXPECT_TRUE(!Locations.empty()); + std::string s("file:///"); + std::string check = URI::unparse(Locations[0].uri); + check = check.erase(0, s.size()); + check = check.substr(0, check.size() - 1); + ASSERT_EQ(check, FooH); + ASSERT_EQ(Locations[0].range.start.line, 0); + ASSERT_EQ(Locations[0].range.start.character, 0); + ASSERT_EQ(Locations[0].range.end.line, 0); + ASSERT_EQ(Locations[0].range.end.character, 0); + + // Test ctrl-clicking on the #include part on the statement + Position P3 = Position{1, 3}; + + Locations = Server.findDefinitions(FooCpp, P3).get().Value; + EXPECT_TRUE(!Locations.empty()); + + // Test invalid include + Position P2 = Position{2, 11}; + + Locations = Server.findDefinitions(FooCpp, P2).get().Value; + EXPECT_TRUE(Locations.empty()); +} + TEST_F(ClangdThreadingTest, NoConcurrentDiagnostics) { class NoConcurrentAccessDiagConsumer : public DiagnosticsConsumer { public: Index: clangd/Protocol.h === --- clangd/Protocol.h +++ clangd/Protocol.h @@ -96,12 +96,21 @@ friend bool operator<(const Range &LHS, const Range &RHS) { return std::tie(LHS.start, LHS.end) < std::tie(RHS.start, RHS.end); } - static llvm::Optional parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); static std::string unparse(const Range &P); + +}; + +class RangeHash { +public: + std::size_t operator()(const Range &R) const + { +return ((R.start.line & 0x18) << 3) | ((R.start.character & 0x18) << 1) | ((R.end.line & 0x18) >> 1) | ((R.end.character & 0x18) >> 3); + } }; + struct Location { /// The text document's URI. URI uri; Index: clangd/GlobalCompilationDatabase.cpp === --- clangd/GlobalCompilationDatabase.cpp +++ clangd/GlobalCompilationDatabase.cpp @@ -9,6 +9,7 @@ #include "GlobalCompilationDatabase.h" #include "Logger.h" +#include "ProtocolHandlers.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -30,6 +31,8 @@ Command.CommandLine.insert(It, ExtraFlags.begin(), ExtraFlags.end()); } + + tooling::CompileCommand getDefaultCompileCommand(PathRef File) { std::vector CommandLine{"clang", "-fsyntax-only", File.str()}; return tooling::CompileCommand(llvm::sys::path::parent_path(File), Index: clangd/ClangdUnit.h === --- clangd/ClangdUnit.h +++ clangd/ClangdUnit.h @@ -22,6 +22,7 @@ #include #include #include +#include namespace llvm { class raw_ostream; @@ -128,11 +129,17 @@ struct PreambleData { PreambleData(PrecompiledPreamble Preamble, std::vector TopLevelDeclIDs, - std::vector Diags); + std::vector Diags, + std::unordered_map IncludeMap, + std::vector> DataVector, + std::vector RangeVector); Preco
[PATCH] D39375: [clang] Add PPCallbacks list to preprocessor when building a preacompiled preamble.
Nebiroth created this revision. Revision https://reviews.llvm.org/D38639 needs this commit in order to properly make open definition calls on include statements work. Since this modifies clang and not clangd, I decided to include it in a different patch. https://reviews.llvm.org/D39375 Files: include/clang/Frontend/PrecompiledPreamble.h lib/Frontend/ASTUnit.cpp lib/Frontend/PrecompiledPreamble.cpp Index: lib/Frontend/PrecompiledPreamble.cpp === --- lib/Frontend/PrecompiledPreamble.cpp +++ lib/Frontend/PrecompiledPreamble.cpp @@ -203,7 +203,7 @@ const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr VFS, std::shared_ptr PCHContainerOps, -PreambleCallbacks &Callbacks) { +PreambleCallbacks &Callbacks, std::unique_ptr PPCallbacks) { assert(VFS && "VFS is null"); if (!Bounds.Size) @@ -307,6 +307,7 @@ if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) return BuildPreambleError::BeginSourceFileFailed; + Clang->getPreprocessor().addPPCallbacks(std::move(PPCallbacks)); Act->Execute(); // Run the callbacks. Index: lib/Frontend/ASTUnit.cpp === --- lib/Frontend/ASTUnit.cpp +++ lib/Frontend/ASTUnit.cpp @@ -53,54 +53,52 @@ using llvm::TimeRecord; namespace { - class SimpleTimer { -bool WantTiming; -TimeRecord Start; -std::string Output; - - public: -explicit SimpleTimer(bool WantTiming) : WantTiming(WantTiming) { - if (WantTiming) -Start = TimeRecord::getCurrentTime(); -} - -void setOutput(const Twine &Output) { - if (WantTiming) -this->Output = Output.str(); -} - -~SimpleTimer() { - if (WantTiming) { -TimeRecord Elapsed = TimeRecord::getCurrentTime(); -Elapsed -= Start; -llvm::errs() << Output << ':'; -Elapsed.print(Elapsed, llvm::errs()); -llvm::errs() << '\n'; - } -} - }; +class SimpleTimer { + bool WantTiming; + TimeRecord Start; + std::string Output; - template - std::unique_ptr valueOrNull(llvm::ErrorOr> Val) { -if (!Val) - return nullptr; -return std::move(*Val); +public: + explicit SimpleTimer(bool WantTiming) : WantTiming(WantTiming) { +if (WantTiming) + Start = TimeRecord::getCurrentTime(); + } + + void setOutput(const Twine &Output) { +if (WantTiming) + this->Output = Output.str(); + } + + ~SimpleTimer() { +if (WantTiming) { + TimeRecord Elapsed = TimeRecord::getCurrentTime(); + Elapsed -= Start; + llvm::errs() << Output << ':'; + Elapsed.print(Elapsed, llvm::errs()); + llvm::errs() << '\n'; +} } +}; - template - bool moveOnNoError(llvm::ErrorOr Val, T &Output) { -if (!Val) - return false; -Output = std::move(*Val); -return true; - } +template +std::unique_ptr valueOrNull(llvm::ErrorOr> Val) { + if (!Val) +return nullptr; + return std::move(*Val); +} + +template bool moveOnNoError(llvm::ErrorOr Val, T &Output) { + if (!Val) +return false; + Output = std::move(*Val); + return true; +} /// \brief Get a source buffer for \p MainFilePath, handling all file-to-file /// and file-to-buffer remappings inside \p Invocation. static std::unique_ptr getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation, - vfs::FileSystem *VFS, - StringRef FilePath) { + vfs::FileSystem *VFS, StringRef FilePath) { const auto &PreprocessorOpts = Invocation.getPreprocessorOpts(); // Try to determine if the main file has been remapped, either from the @@ -156,7 +154,7 @@ return nullptr; return llvm::MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), FilePath); } -} +} // namespace struct ASTUnit::ASTWriterData { SmallString<128> Buffer; @@ -167,9 +165,7 @@ : Stream(Buffer), Writer(Stream, Buffer, PCMCache, {}) {} }; -void ASTUnit::clearFileLevelDecls() { - llvm::DeleteContainerSeconds(FileDecls); -} +void ASTUnit::clearFileLevelDecls() { llvm::DeleteContainerSeconds(FileDecls); } /// \brief After failing to build a precompiled preamble (due to /// errors in the source that occurs in the preamble), the number of @@ -183,20 +179,15 @@ static std::atomic ActiveASTUnitObjects; ASTUnit::ASTUnit(bool _MainFileIsAST) - : Reader(nullptr), HadModuleLoaderFatalFailure(false), -OnlyLocalDecls(false), CaptureDiagnostics(false), -MainFileIsAST(_MainFileIsAST), -TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")), -OwnsRemappedFileBuffers(true), -NumStoredDiagnosticsFromDriver(0), -PreambleRebuildCounter(0), -NumWarningsInPreamble(0), -ShouldCacheCodeCompletionResults(false), -IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(fal
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth updated this revision to Diff 120894. Nebiroth added a comment. Code hover now displays declaration of symbol instead of source code by default. Code hover now displays context information such as namespace and class name. Array of MarkedString objects is now sent as response in JSON. https://reviews.llvm.org/D35894 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/hover.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -5,16 +5,17 @@ Content-Length: 143 {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootUri":"file:///path/to/workspace","capabilities":{},"trace":"off"}} -# CHECK: Content-Length: 535 +# CHECK: Content-Length: 568 # CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{ # CHECK: "textDocumentSync": 1, # CHECK: "documentFormattingProvider": true, # CHECK: "documentRangeFormattingProvider": true, # CHECK: "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]}, # CHECK: "codeActionProvider": true, # CHECK: "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]}, # CHECK: "signatureHelpProvider": {"triggerCharacters": ["(",","]}, -# CHECK: "definitionProvider": true +# CHECK: "definitionProvider": true, +# CHECK: "hoverProvider": true # CHECK: }}} # Content-Length: 44 Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -5,16 +5,17 @@ Content-Length: 142 {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":"","rootUri":"file:///path/to/workspace","capabilities":{},"trace":"off"}} -# CHECK: Content-Length: 535 +# CHECK: Content-Length: 568 # CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{ # CHECK: "textDocumentSync": 1, # CHECK: "documentFormattingProvider": true, # CHECK: "documentRangeFormattingProvider": true, # CHECK: "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]}, # CHECK: "codeActionProvider": true, # CHECK: "completionProvider": {"resolveProvider": false, "triggerCharacters": [".",">",":"]}, # CHECK: "signatureHelpProvider": {"triggerCharacters": ["(",","]}, -# CHECK: "definitionProvider": true +# CHECK: "definitionProvider": true, +# CHECK: "hoverProvider": true # CHECK: }}} # Content-Length: 44 Index: test/clangd/hover.test === --- /dev/null +++ test/clangd/hover.test @@ -0,0 +1,52 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 407 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nint test = 5;\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};}\nint main() {\nint a;\na;\nint b = ns1::test;\nns1::MyClass* Params;\nParams->anotherOperation();\nMACRO;}\n"}}} + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":0,"character":12}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":{"contents": ["#define statement",{"language": "C++", "value": "MACRO 1"}], "range": {"start": {"line": 0, "character": 8}, "end": {"line": 0, "character": 15 + +Content-Length: 144 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":14,"character":1}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":{"contents": [{"language": "C++", "value": "int a"}], "range": {"start": {"line": 13, "character": 0}, "end": {"line": 13, "character": 5 + +Content-Length: 145 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":15,"character":15}}} +# Go to local variable +# CHECK: {"jsonrpc":"2.0","id":1,"result":{"contents": ["In namespace named ns1",{"language": "C++", "value": "int test = 5"}], "range": {"start": {"line": 2, "character": 0}, "end": {"line": 2, "character": 12 + +Content-Length: 145 + +{"jsonrp
[PATCH] D35894: [clangd] Code hover for Clangd
Nebiroth added a comment. I also have a quick patch that supports displaying comments preceding the declaration of a function. Once the review comments have been addressed for this revision I will submit it. https://reviews.llvm.org/D35894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D39571: [clangd] DidChangeConfiguration Notification
Nebiroth created this revision. Implementation of DidChangeConfiguration notification handling in clangd. This currently only supports changing one setting: the path of the compilation database to be used for the current project In other words, it is no longer necessary to restart clangd with a different command line argument in order to change the compilation database. https://reviews.llvm.org/D39571 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/GlobalCompilationDatabase.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -52,6 +52,8 @@ virtual void onGoToDefinition(Ctx C, TextDocumentPositionParams &Params) = 0; virtual void onSwitchSourceHeader(Ctx C, TextDocumentIdentifier &Params) = 0; virtual void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) = 0; + virtual void onChangeConfiguration(Ctx C, + DidChangeConfigurationParams &Params) = 0; }; void registerCallbackHandlers(JSONRPCDispatcher &Dispatcher, JSONOutput &Out, Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -72,4 +72,6 @@ Register("textDocument/switchSourceHeader", &ProtocolCallbacks::onSwitchSourceHeader); Register("workspace/didChangeWatchedFiles", &ProtocolCallbacks::onFileEvent); + Register("workspace/didChangeConfiguration", + &ProtocolCallbacks::onChangeConfiguration); } Index: clangd/Protocol.h === --- clangd/Protocol.h +++ clangd/Protocol.h @@ -273,6 +273,27 @@ parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); }; +struct ClangdConfigurationParams { + + llvm::Optional compilationDatabasePath; + static llvm::Optional + parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); +}; + +struct DidChangeConfigurationParams { + + DidChangeConfigurationParams() {} + + DidChangeConfigurationParams(ClangdConfigurationParams settings) + : settings(settings) {} + + ClangdConfigurationParams settings; + + static llvm::Optional + parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger); + static std::string unparse(const DidChangeConfigurationParams &P); +}; + struct FormattingOptions { /// Size of a tab in spaces. int tabSize; Index: clangd/Protocol.cpp === --- clangd/Protocol.cpp +++ clangd/Protocol.cpp @@ -531,6 +531,59 @@ return Result; } +llvm::Optional +DidChangeConfigurationParams::parse(llvm::yaml::MappingNode *Params, +clangd::Logger &Logger) { + DidChangeConfigurationParams Result; + for (auto &NextKeyValue : *Params) { +auto *KeyString = dyn_cast(NextKeyValue.getKey()); +if (!KeyString) + return llvm::None; + +llvm::SmallString<10> KeyStorage; +StringRef KeyValue = KeyString->getValue(KeyStorage); +auto *Value = +dyn_cast_or_null(NextKeyValue.getValue()); +if (!Value) + return llvm::None; + +llvm::SmallString<10> Storage; +if (KeyValue == "settings") { + auto Parsed = ClangdConfigurationParams::parse(Value, Logger); + if (!Parsed) +return llvm::None; + Result.settings = Parsed.getValue(); +} else { + logIgnoredField(KeyValue, Logger); +} + } + + return Result; +} + +llvm::Optional +ClangdConfigurationParams::parse(llvm::yaml::MappingNode *Params, + clangd::Logger &Logger) { + ClangdConfigurationParams Result; + for (auto &NextKeyValue : *Params) { +auto *KeyString = dyn_cast(NextKeyValue.getKey()); +if (!KeyString) + return llvm::None; + +llvm::SmallString<10> KeyStorage; +StringRef KeyValue = KeyString->getValue(KeyStorage); +auto *Value = +dyn_cast_or_null(NextKeyValue.getValue()); +if (!Value) + return llvm::None; + +if (KeyValue == "compilationDatabasePath") { + Result.compilationDatabasePath = Value->getValue(KeyStorage); +} + } + return Result; +} + llvm::Optional TextDocumentContentChangeEvent::parse(llvm::yaml::MappingNode *Params, clangd::Logger &Logger) { Index: clangd/GlobalCompilationDatabase.h === --- clangd/GlobalCompilationDatabase.h +++ clangd/GlobalCompilationDatabase.h @@ -52,11 +52,14 @@ std::vector getCompileCommands(PathRef File) override; + llvm::Optional getCompileCommandsDir() { return CompileCommandsDir; } + void setCompileCommandsDir(Path P) { CompileCommandsDir = P; } + + tooling::CompilationDatabase *getCo
[PATCH] D39571: [clangd] DidChangeConfiguration Notification
Nebiroth added inline comments. Comment at: clangd/ClangdLSPServer.cpp:51 + "definitionProvider": true, + "configurationChangeProvider": true }})"); malaperle wrote: > Are you sure the existing tests don't fail? usually when we change this, some > tests have to be adjusted. I'll verify this when I will have the time. Comment at: clangd/ClangdServer.h:289 + /// ChangedSettings + void changeConfiguration(std::map ChangedSettings); + ilya-biryukov wrote: > This function is way too general for `ClangdServer`'s interface, can we have > more fine-grained settings here (i.e. `setCompletionParameters` etc?) and > handle the "general" case in `ClangdLSPServer` (i.e., unknown setting names, > invalid setting parameters, json parsing, etc.)? > > I suggest we remove this function altogether. So if I understand correctly, we would have the most generic workspace/didChangeConfiguration handler located in ClangdLSPServer with a name perhaps similar to changeConfiguration that would pass valid settings to more specific functions inside ClangdServer ? Comment at: clangd/Protocol.cpp:534 +llvm::Optional +DidChangeConfigurationParams::parse(llvm::yaml::MappingNode *Params, malaperle wrote: > I think this needs a test, perhaps create did-change-configuration.test? It > can also test the ClangdConfigurationParams::parse code > If you do, I think it's a good idea to test a few failing cases: > - "settings" is not a mapping node. You can test this with a scalar node like > "settings": "" > - Something else than "settings" is present, so that it goes through > logIgnoredField > - "settings" is not set at all. In this case, because it's mandatory in the > protocol, return llvm::None. This can be checked after the loop after all > key/values were read. > > There are similar tests in execute-command.test if you'd like an example. > And of course also add a "successful" case as well :) Yes, I was planning on adding a simple test in the coming days. I imagine this test will be greatly expanded on once more settings become available to change on the server side. https://reviews.llvm.org/D39571 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 122528. Nebiroth added a comment. - Decls and MacroInfos vectors are now private and passed by reference instead of copied. https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] @@ -40,6 +41,7 @@ # CHECK-NEXT: "textDocumentSync": 1 # CHECK-NEXT:} # CHECK-NEXT: } + Content-Length: 44 {"jsonrpc":"2.0","id":3,"method":"shutdown"} Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,37 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 455 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":12,"line":16},"start":{"character":4,"line":16}}},{"kind":0,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}}]} + + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":9,"line":12},"start":{"character":4,"line":12}}},{"kind":1,"range":{"end":{"character":21,"line":18},"start":{"character":17,"line":18}}},{"kind":216,"range":{"end":{"character":21,"line":18},"start":{"character":17,"line":18}}},{"kind":220,"range":{"end":{"character":8,"line":19},"start":{"character":4,"line":19}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":22,"line":4},"start":{"character":5,"line":4}}},{"kind":0,"range":{"end":{"character":25,"line":21},"start":{"character":8,"line":21}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -31,7 +31,6 @@ public: using Ctx = RequestContext; virtual ~ProtocolCallbacks() = default; - virtual void onInitialize(Ctx C, InitializeParams &Params) = 0; virtual void onShutdown(Ctx C, ShutdownParams &Params) = 0; virtual void onExit(Ctx C, ExitParams &Params) = 0; @@ -54,6 +53,8 @@ virtual void onFileEvent(Ctx C, DidChangeWatchedFilesParams &Params) = 0; virtual void onCommand
[PATCH] D38425: [clangd] Document highlights for clangd
Nebiroth updated this revision to Diff 122529. Nebiroth added a comment. Decls and MacroInfos vectors are now private and passed by reference instead of copied. DeclarationLocationsFinder does not store Locations anymore, instead the vector is filled in their respective methods in ClangdUnit.cpp Refactored if condition Removed redundant newlines at end of test file. https://reviews.llvm.org/D38425 Files: clangd/ClangdLSPServer.cpp clangd/ClangdLSPServer.h clangd/ClangdServer.cpp clangd/ClangdServer.h clangd/ClangdUnit.cpp clangd/ClangdUnit.h clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/documenthighlight.test test/clangd/initialize-params-invalid.test test/clangd/initialize-params.test Index: test/clangd/initialize-params.test === --- test/clangd/initialize-params.test +++ test/clangd/initialize-params.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] Index: test/clangd/initialize-params-invalid.test === --- test/clangd/initialize-params-invalid.test +++ test/clangd/initialize-params-invalid.test @@ -20,6 +20,7 @@ # CHECK-NEXT: }, # CHECK-NEXT: "definitionProvider": true, # CHECK-NEXT: "documentFormattingProvider": true, +# CHECK-NEXT: "documentHighlightProvider": true, # CHECK-NEXT: "documentOnTypeFormattingProvider": { # CHECK-NEXT:"firstTriggerCharacter": "}", # CHECK-NEXT:"moreTriggerCharacter": [] @@ -40,6 +41,7 @@ # CHECK-NEXT: "textDocumentSync": 1 # CHECK-NEXT:} # CHECK-NEXT: } + Content-Length: 44 {"jsonrpc":"2.0","id":3,"method":"shutdown"} Index: test/clangd/documenthighlight.test === --- /dev/null +++ test/clangd/documenthighlight.test @@ -0,0 +1,37 @@ +# RUN: clangd -run-synchronously < %s | FileCheck %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} + +Content-Length: 455 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"#define MACRO 1\nnamespace ns1 {\nstruct MyClass {\nint xasd;\nvoid anotherOperation() {\n}\nstatic int foo(MyClass*) {\nreturn 0;\n}\n\n};\nstruct Foo {\nint xasd;\n};\n}\nint main() {\nint bonjour;\nbonjour = 2;\nns1::Foo bar = { xasd : 1};\nbar.xasd = 3;\nns1::MyClass* Params;\nParams->anotherOperation();}\n"}}} + +Content-Length: 156 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":2}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":12,"line":16},"start":{"character":4,"line":16}}},{"kind":0,"range":{"end":{"character":7,"line":17},"start":{"character":0,"line":17}}}]} + + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":18,"character":17}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":9,"line":12},"start":{"character":4,"line":12}}},{"kind":1,"range":{"end":{"character":21,"line":18},"start":{"character":17,"line":18}}},{"kind":216,"range":{"end":{"character":21,"line":18},"start":{"character":17,"line":18}}},{"kind":220,"range":{"end":{"character":8,"line":19},"start":{"character":4,"line":19}}}]} + +Content-Length: 157 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/documentHighlight","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":21,"character":10}}} +# Go to local variable +# CHECK: {"id":1,"jsonrpc":"2.0","result":[{"kind":1,"range":{"end":{"character":22,"line":4},"start":{"character":5,"line":4}}},{"kind":0,"range":{"end":{"character":25,"line":21},"start":{"character":8,"line":21}}}]} + +Content-Length: 48 + +{"jsonrpc":"2.0","id":1,"method":"shutdown"} + +Content-Length: 33 + +{"jsonrpc":"2.0":"method":"exit"} \ No newline at end of file Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -31,7 +31,6 @@ public: using Ctx = RequestContext; virtual ~ProtocolCallbacks() = default; - virtual void onInitialize(Ctx C, InitializeParams &Params) = 0; virtual void onShutdown(Ctx