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<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 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<tooling::Replacement> 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 <future>
@@ -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<std::string> ExtensionsArray;
+
+ if (!isSourceFile)
+ ExtensionsArray = DEFAULT_SOURCE_EXTENSIONS;
+ else
+ ExtensionsArray = DEFAULT_HEADER_EXTENSIONS;
+
+ int i = 0;
+ while (!done && i < ExtensionsArray.size()) {
+ std::string CurrentPathString = CurrentPath.str();
+ std::string NewPathString = NewPath.str();
+ if (i == 0)
+ CurrentPathString = std::string(pathDataRef).append(std::string(ExtensionsArray[i]));
+ else
+ CurrentPathString = CurrentPathString.append(std::string(ExtensionsArray[i]));
+
+ FILE *file;
+ auto test = FSProvider.getTaggedFileSystem(std::string(CurrentPathString));
+ bool fileExists = test.Value.get()->exists(std::string(CurrentPathString));
+ if (fileExists) {
+ done = true;
+ llvm::sys::path::replace_extension(NewPath, ExtensionsArray[i]);
+ std::string returnValue = "file://" + std::string(NewPath.str());
+ returnValue = URI::unparse(URI::fromUri(returnValue));
+ 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,16 @@
R"(,"result":[)" + Locations + R"(]})");
}
+void ClangdLSPServer::LSPProtocolCallbacks::onSwitchSourceHeader(
+ TextDocumentIdentifier Params, StringRef ID, JSONOutput &Out) {
+
+ Path Result = LangServer.Server.switchSourceHeader(Params.uri.file);
+
+ 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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits