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<CompletionHandler>(Out, Callbacks)); Dispatcher.registerHandler("textDocument/definition", llvm::make_unique<GotoDefinitionHandler>(Out, Callbacks)); + Dispatcher.registerHandler( + "textDocument/switchSourceHeader", + llvm::make_unique<SwitchSourceHeaderHandler>(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<std::vector<Location>> 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<tooling::Replacement> 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 <future> using namespace clang; using namespace clang::clangd; namespace { + std::vector<tooling::Replacement> formatCode(StringRef Code, StringRef Filename, ArrayRef<tooling::Range> 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<std::string> EXTENSIONS_ARRAY; + + if (!isSourceFile) + EXTENSIONS_ARRAY.assign(DEFAULT_SOURCE_EXTENSIONS, DEFAULT_SOURCE_EXTENSIONS + sourceSize); + else + EXTENSIONS_ARRAY.assign(DEFAULT_HEADER_EXTENSIONS, DEFAULT_HEADER_EXTENSIONS + headerSize); + + i = 0; + while (!done && i < EXTENSIONS_ARRAY.size()) + { + std::string CurrentPathString = CurrentPath.str(); + std::string NewPathString = NewPath.str(); + if (i == 0) + CurrentPathString = pathDataRef.append(std::string(EXTENSIONS_ARRAY[i])); + else + CurrentPathString = CurrentPathString.append(std::string(EXTENSIONS_ARRAY[i])); + + std::string temp = CurrentPathString.substr(7, CurrentPathString.size()); + FILE * file; + file = fopen(temp.c_str(), "r"); + if (file) + { + done = true; + fclose(file); + llvm::sys::path::replace_extension(NewPath, EXTENSIONS_ARRAY[i]); + std::string returnValue = std::string(NewPath.str()); + return Path("\"" + returnValue + "\""); + } + llvm::sys::path::replace_extension(CurrentPath, ""); + CurrentPathString = CurrentPath.str(); + i++; + } +} Index: clangd/ClangdLSPServer.cpp =================================================================== --- clangd/ClangdLSPServer.cpp +++ clangd/ClangdLSPServer.cpp @@ -71,6 +71,8 @@ JSONOutput &Out) override; void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) override; + void onSwitchSourceHeader(TextDocumentIdentifier Params, StringRef ID, + JSONOutput &Out) override; private: ClangdLSPServer &LangServer; @@ -216,6 +218,17 @@ R"(,"result":[)" + Locations + R"(]})"); } +void ClangdLSPServer::LSPProtocolCallbacks::onSwitchSourceHeader( + TextDocumentIdentifier Params, StringRef ID, JSONOutput &Out) { + + PathRef ref = PathRef((Params.uri.uri).c_str()); + Path result = LangServer.Server.switchSourceHeader(ref); + + Out.writeMessage( + R"({"jsonrpc":"2.0","id":)" + ID.str() + + R"(,"result":)" + result + R"(})"); +} + ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, bool RunSynchronously) : Out(Out), DiagConsumer(*this), Server(CDB, DiagConsumer, FSProvider, RunSynchronously) {}
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits