Skip to content

Commit

Permalink
Add $ccls/navigate and improve textDocument/definition
Browse files Browse the repository at this point in the history
  • Loading branch information
MaskRay committed Nov 10, 2019
1 parent d22e640 commit d864f96
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 4 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ target_sources(ccls PRIVATE
src/messages/ccls_freshenIndex.cc
src/messages/ccls_inheritanceHierarchy.cc
src/messages/ccls_memberHierarchy.cc
src/messages/ccls_navigate.cc
src/messages/ccls_vars.cc
src/messages/exit.cc
src/messages/initialize.cc
Expand Down
103 changes: 103 additions & 0 deletions src/messages/ccls_navigate.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2017-2018 ccls Authors
// SPDX-License-Identifier: Apache-2.0

#include "message_handler.h"
#include "pipeline.hh"
#include "query_utils.h"
using namespace ccls;

namespace {
MethodType kMethodType = "$ccls/navigate";

struct In_CclsNavigate : public RequestInMessage {
MethodType GetMethodType() const override { return kMethodType; }
struct Params {
lsTextDocumentIdentifier textDocument;
lsPosition position;
std::string direction;
} params;
};
MAKE_REFLECT_STRUCT(In_CclsNavigate::Params, textDocument, position, direction);
MAKE_REFLECT_STRUCT(In_CclsNavigate, id, params);
REGISTER_IN_MESSAGE(In_CclsNavigate);

struct Handler_CclsNavigate : BaseMessageHandler<In_CclsNavigate> {
MethodType GetMethodType() const override { return kMethodType; }
void Run(In_CclsNavigate *request) override {
auto &params = request->params;
QueryFile *file;
if (!FindFileOrFail(db, project, request->id,
params.textDocument.uri.GetPath(), &file))
return;

WorkingFile *wfile =
working_files->GetFileByFilename(file->def->path);
lsPosition ls_pos = request->params.position;
if (wfile && wfile->index_lines.size())
if (auto line = wfile->GetIndexPosFromBufferPos(
ls_pos.line, &ls_pos.character, false))
ls_pos.line = *line;
Position pos{(int16_t)ls_pos.line, (int16_t)ls_pos.character};

Maybe<Range> res;
switch (params.direction[0]) {
case 'D': {
Maybe<Range> parent;
for (auto [sym, refcnt] : file->outline2refcnt)
if (refcnt > 0 && sym.range.start <= pos && pos < sym.range.end &&
(!parent || parent->start < sym.range.start))
parent = sym.range;
for (auto [sym, refcnt] : file->outline2refcnt)
if (refcnt > 0 && pos < sym.range.start &&
(!parent || sym.range.end <= parent->end) &&
(!res || sym.range.start < res->start))
res = sym.range;
break;
}
case 'L':
for (auto [sym, refcnt] : file->outline2refcnt)
if (refcnt > 0 && sym.range.end <= pos &&
(!res || (res->end == sym.range.end ? sym.range.start < res->start
: res->end < sym.range.end)))
res = sym.range;
break;
case 'R': {
Maybe<Range> parent;
for (auto [sym, refcnt] : file->outline2refcnt)
if (refcnt > 0 && sym.range.start <= pos && pos < sym.range.end &&
(!parent || parent->start < sym.range.start))
parent = sym.range;
if (parent && parent->start.line == pos.line && pos < parent->end) {
pos = parent->end;
if (pos.column)
pos.column--;
}
for (auto [sym, refcnt] : file->outline2refcnt)
if (refcnt > 0 && pos < sym.range.start &&
(!res ||
(sym.range.start == res->start ? res->end < sym.range.end
: sym.range.start < res->start)))
res = sym.range;
break;
}
case 'U':
default:
for (auto [sym, refcnt] : file->outline2refcnt)
if (refcnt > 0 && sym.range.start < pos && pos < sym.range.end &&
(!res || res->start < sym.range.start))
res = sym.range;
break;
}
Out_LocationList out;
out.id = request->id;
if (res)
if (auto ls_range = GetLsRange(wfile, *res)) {
lsLocationEx &ls_loc = out.result.emplace_back();
ls_loc.uri = params.textDocument.uri;
ls_loc.range = *ls_range;
}
pipeline::WriteStdout(kMethodType, out);
}
};
REGISTER_MESSAGE_HANDLER(Handler_CclsNavigate);
} // namespace
11 changes: 7 additions & 4 deletions src/messages/textDocument_definition.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,17 @@ struct Handler_TextDocumentDefinition
Out_TextDocumentDefinition out;
out.id = request->id;

Maybe<Range> range;
Maybe<Use> on_def;
bool has_symbol = false;
WorkingFile *wfile = working_files->GetFileByFilename(file->def->path);
lsPosition &ls_pos = params.position;

for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, ls_pos)) {
if (!range)
range = sym.range;
else if (!(*range == sym.range))
break;
// Found symbol. Return definition.
has_symbol = true;

// Special cases which are handled:
// - symbol has declaration but no definition (ie, pure virtual)
Expand Down Expand Up @@ -118,12 +121,12 @@ struct Handler_TextDocumentDefinition
lsLocationEx result;
result.uri = lsDocumentUri::FromPath(include.resolved_path);
out.result.push_back(result);
has_symbol = true;
range = {{0, 0}, {0, 0}};
break;
}
}
// Find the best match of the identifier at point.
if (!has_symbol) {
if (!range) {
lsPosition position = request->params.position;
const std::string &buffer = wfile->buffer_content;
std::string_view query = LexIdentifierAroundPos(position, buffer);
Expand Down
1 change: 1 addition & 0 deletions src/position.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct Position {
return line < o.line;
return column < o.column;
}
bool operator<=(const Position &o) const { return !(o < *this); }
};
MAKE_HASHABLE(Position, t.line, t.column);

Expand Down

0 comments on commit d864f96

Please sign in to comment.