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 <iostream>
#include <memory>
#include <string>
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<CompletionHandler>(Out, Callbacks));
- Dispatcher.registerHandler("textDocument/definition",
+ 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.
+ llvm::Optional<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,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 <future>
+using namespace llvm;
using namespace clang;
using namespace clang::clangd;
@@ -273,16 +275,76 @@
return DumpFuture.get();
}
-Tagged<std::vector<Location>>
-ClangdServer::findDefinitions(PathRef File, Position Pos) {
+Tagged<std::vector<Location>> 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<Location> 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<Path> 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_if(std::begin(SourceExtensions), std::end(SourceExtensions),
+ [&PathExt](PathRef SourceExt) {
+ return SourceExt.equals_lower(PathExt);
+ });
+ bool IsSource = SourceIter != std::end(SourceExtensions);
+
+ auto HeaderIter =
+ std::find_if(std::begin(HeaderExtensions), std::end(HeaderExtensions),
+ [&PathExt](PathRef HeaderExt) {
+ return HeaderExt.equals_lower(PathExt);
+ });
+
+ bool IsHeader = HeaderIter != std::end(HeaderExtensions);
+
+ // We can only switch between extensions known extensions.
+ if (!IsSource && !IsHeader)
+ return llvm::None;
+
+ // Array to lookup extensions for the switch. An opposite of where original
+ // extension was found.
+ ArrayRef<StringRef> NewExts;
+ if (IsSource)
+ NewExts = HeaderExtensions;
+ else
+ NewExts = SourceExtensions;
+
+ // Storage for the new path.
+ SmallString<128> NewPath = StringRef(Path);
+
+ // Instance of vfs::FileSystem, used for file existence checks.
+ auto FS = FSProvider.getTaggedFileSystem(Path).Value;
+
+ // Loop through switched extension candidates.
+ for (StringRef NewExt : NewExts) {
+ llvm::sys::path::replace_extension(NewPath, NewExt);
+ if (FS->exists(NewPath)) {
+ return NewPath.str().str(); // First str() to convert from SmallString to
+ // StringRef, second to convert from StringRef
+ // to std::string
+ }
+ // Also check NewExt in upper-case, just in case.
+ llvm::sys::path::replace_extension(NewPath, NewExt.upper());
+ if (FS->exists(NewPath)) {
+ return NewPath.str().str();
+ }
+ }
+
+ return llvm::None;
+}
Index: clangd/ClangdLSPServer.cpp
===================================================================
--- clangd/ClangdLSPServer.cpp
+++ clangd/ClangdLSPServer.cpp
@@ -70,6 +70,8 @@
void onCompletion(TextDocumentPositionParams Params, StringRef ID,
JSONOutput &Out) override;
void onGoToDefinition(TextDocumentPositionParams Params, StringRef ID,
+ JSONOutput &Out) override;
+ void onSwitchSourceHeader(TextDocumentIdentifier Params, StringRef ID,
JSONOutput &Out) override;
private:
@@ -181,9 +183,11 @@
void ClangdLSPServer::LSPProtocolCallbacks::onCompletion(
TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) {
- auto Items = LangServer.Server.codeComplete(
- Params.textDocument.uri.file,
- Position{Params.position.line, Params.position.character}).Value;
+ auto Items = LangServer.Server
+ .codeComplete(Params.textDocument.uri.file,
+ Position{Params.position.line,
+ Params.position.character})
+ .Value;
std::string Completions;
for (const auto &Item : Items) {
@@ -200,9 +204,11 @@
void ClangdLSPServer::LSPProtocolCallbacks::onGoToDefinition(
TextDocumentPositionParams Params, StringRef ID, JSONOutput &Out) {
- auto Items = LangServer.Server.findDefinitions(
- Params.textDocument.uri.file,
- Position{Params.position.line, Params.position.character}).Value;
+ auto Items = LangServer.Server
+ .findDefinitions(Params.textDocument.uri.file,
+ Position{Params.position.line,
+ Params.position.character})
+ .Value;
std::string Locations;
for (const auto &Item : Items) {
@@ -216,6 +222,22 @@
R"(,"result":[)" + Locations + R"(]})");
}
+void ClangdLSPServer::LSPProtocolCallbacks::onSwitchSourceHeader(
+ TextDocumentIdentifier Params, StringRef ID, JSONOutput &Out) {
+
+ llvm::Optional<Path> Result =
+ LangServer.Server.switchSourceHeader(Params.uri.file);
+ URI ResultUri;
+ if (Result != llvm::None)
+ ResultUri = URI::fromFile(*Result);
+ else
+ ResultUri = URI::fromFile("");
+
+ Out.writeMessage(
+ R"({"jsonrpc":"2.0","id":)" + ID.str() +
+ R"(,"result":)" + URI::unparse(ResultUri) + 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