Better definition/references on #include lines

This commit is contained in:
Fangrui Song 2018-04-08 10:03:50 -07:00
parent 75638b5387
commit 2a06fb55dd
8 changed files with 56 additions and 70 deletions

View File

@ -8,22 +8,6 @@
#include <iosfwd> #include <iosfwd>
#include <unordered_map> #include <unordered_map>
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
///////////////////////////// OUTGOING MESSAGES /////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
///////////////////////////// INCOMING MESSAGES /////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
#define REGISTER_IN_MESSAGE(type) \ #define REGISTER_IN_MESSAGE(type) \
static MessageRegistryRegister<type> type##message_handler_instance_; static MessageRegistryRegister<type> type##message_handler_instance_;

View File

@ -182,7 +182,7 @@ struct Handler_CclsCallHierarchy
} }
void Run(In_CclsCallHierarchy* request) override { void Run(In_CclsCallHierarchy* request) override {
const auto& params = request->params; auto& params = request->params;
Out_CclsCallHierarchy out; Out_CclsCallHierarchy out;
out.id = request->id; out.id = request->id;

View File

@ -139,7 +139,7 @@ struct Handler_CclsInheritanceHierarchy
} }
void Run(In_CclsInheritanceHierarchy* request) override { void Run(In_CclsInheritanceHierarchy* request) override {
const auto& params = request->params; auto& params = request->params;
Out_CclsInheritanceHierarchy out; Out_CclsInheritanceHierarchy out;
out.id = request->id; out.id = request->id;
@ -158,11 +158,11 @@ struct Handler_CclsInheritanceHierarchy
if (!FindFileOrFail(db, project, request->id, if (!FindFileOrFail(db, project, request->id,
params.textDocument.uri.GetPath(), &file)) params.textDocument.uri.GetPath(), &file))
return; return;
WorkingFile* working_file = WorkingFile* wfile =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
for (SymbolRef sym : FindSymbolsAtLocation(working_file, file, for (SymbolRef sym :
request->params.position)) { FindSymbolsAtLocation(wfile, file, params.position)) {
if (sym.kind == SymbolKind::Func || sym.kind == SymbolKind::Type) { if (sym.kind == SymbolKind::Func || sym.kind == SymbolKind::Type) {
out.result = BuildInitial(sym, params.derived, params.qualified, out.result = BuildInitial(sym, params.derived, params.qualified,
params.levels); params.levels);

View File

@ -202,7 +202,7 @@ struct Handler_CclsMemberHierarchy
} }
void Run(In_CclsMemberHierarchy* request) override { void Run(In_CclsMemberHierarchy* request) override {
const auto& params = request->params; auto& params = request->params;
Out_CclsMemberHierarchy out; Out_CclsMemberHierarchy out;
out.id = request->id; out.id = request->id;
@ -218,10 +218,10 @@ struct Handler_CclsMemberHierarchy
if (!FindFileOrFail(db, project, request->id, if (!FindFileOrFail(db, project, request->id,
params.textDocument.uri.GetPath(), &file)) params.textDocument.uri.GetPath(), &file))
return; return;
WorkingFile* working_file = WorkingFile* wfile =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
for (SymbolRef sym : for (SymbolRef sym :
FindSymbolsAtLocation(working_file, file, params.position)) { FindSymbolsAtLocation(wfile, file, params.position)) {
switch (sym.kind) { switch (sym.kind) {
case SymbolKind::Func: case SymbolKind::Func:
out.result = BuildInitial(QueryFuncId(sym.id), params.qualified, out.result = BuildInitial(QueryFuncId(sym.id), params.qualified,

View File

@ -50,27 +50,23 @@ struct Handler_TextDocumentDefinition
: BaseMessageHandler<In_TextDocumentDefinition> { : BaseMessageHandler<In_TextDocumentDefinition> {
MethodType GetMethodType() const override { return kMethodType; } MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentDefinition* request) override { void Run(In_TextDocumentDefinition* request) override {
auto& params = request->params;
QueryFileId file_id; QueryFileId file_id;
QueryFile* file; QueryFile* file;
if (!FindFileOrFail(db, project, request->id, if (!FindFileOrFail(db, project, request->id,
request->params.textDocument.uri.GetPath(), &file, params.textDocument.uri.GetPath(), &file, &file_id))
&file_id)) {
return; return;
}
WorkingFile* working_file =
working_files->GetFileByFilename(file->def->path);
Out_TextDocumentDefinition out; Out_TextDocumentDefinition out;
out.id = request->id; out.id = request->id;
Maybe<Use> on_def; Maybe<Use> on_def;
bool has_symbol = false; bool has_symbol = false;
int target_line = request->params.position.line; WorkingFile* wfile =
int target_column = request->params.position.character; working_files->GetFileByFilename(file->def->path);
lsPosition& ls_pos = params.position;
for (SymbolRef sym : for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, ls_pos)) {
FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return definition. // Found symbol. Return definition.
has_symbol = true; has_symbol = true;
@ -84,7 +80,7 @@ struct Handler_TextDocumentDefinition
Use spell = *def.spell; Use spell = *def.spell;
// If on a definition, clear |uses| to find declarations below. // If on a definition, clear |uses| to find declarations below.
if (spell.file == file_id && if (spell.file == file_id &&
spell.range.Contains(target_line, target_column)) { spell.range.Contains(ls_pos.line, ls_pos.character)) {
on_def = spell; on_def = spell;
uses.clear(); uses.clear();
return false; return false;
@ -114,7 +110,7 @@ struct Handler_TextDocumentDefinition
// No symbols - check for includes. // No symbols - check for includes.
if (out.result.empty()) { if (out.result.empty()) {
for (const IndexInclude& include : file->def->includes) { for (const IndexInclude& include : file->def->includes) {
if (include.line == target_line) { if (include.line == ls_pos.line) {
lsLocationEx result; lsLocationEx result;
result.uri = lsDocumentUri::FromPath(include.resolved_path); result.uri = lsDocumentUri::FromPath(include.resolved_path);
out.result.push_back(result); out.result.push_back(result);
@ -125,7 +121,7 @@ struct Handler_TextDocumentDefinition
// Find the best match of the identifier at point. // Find the best match of the identifier at point.
if (!has_symbol) { if (!has_symbol) {
lsPosition position = request->params.position; lsPosition position = request->params.position;
const std::string& buffer = working_file->buffer_content; const std::string& buffer = wfile->buffer_content;
std::string_view query = LexIdentifierAroundPos(position, buffer); std::string_view query = LexIdentifierAroundPos(position, buffer);
std::string_view short_query = query; std::string_view short_query = query;
{ {

View File

@ -45,26 +45,25 @@ struct Handler_TextDocumentReferences
MethodType GetMethodType() const override { return kMethodType; } MethodType GetMethodType() const override { return kMethodType; }
void Run(In_TextDocumentReferences* request) override { void Run(In_TextDocumentReferences* request) override {
auto& params = request->params;
QueryFile* file; QueryFile* file;
if (!FindFileOrFail(db, project, request->id, if (!FindFileOrFail(db, project, request->id,
request->params.textDocument.uri.GetPath(), &file)) { params.textDocument.uri.GetPath(), &file))
return; return;
}
WorkingFile* working_file = WorkingFile* wfile =
working_files->GetFileByFilename(file->def->path); working_files->GetFileByFilename(file->def->path);
Out_TextDocumentReferences out; Out_TextDocumentReferences out;
out.id = request->id; out.id = request->id;
bool container = g_config->xref.container; bool container = g_config->xref.container;
for (const SymbolRef& sym : for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, params.position)) {
FindSymbolsAtLocation(working_file, file, request->params.position)) {
// Found symbol. Return references. // Found symbol. Return references.
EachOccurrenceWithParent( EachOccurrenceWithParent(
db, sym, request->params.context.includeDeclaration, db, sym, params.context.includeDeclaration,
[&](Use use, lsSymbolKind parent_kind) { [&](Use use, lsSymbolKind parent_kind) {
if (use.role & request->params.context.role) if (use.role & params.context.role)
if (std::optional<lsLocationEx> ls_loc = if (std::optional<lsLocationEx> ls_loc =
GetLsLocationEx(db, working_files, use, container)) { GetLsLocationEx(db, working_files, use, container)) {
if (container) if (container)
@ -75,24 +74,32 @@ struct Handler_TextDocumentReferences
break; break;
} }
if (out.result.empty()) if (out.result.empty()) {
// |path| is the #include line. If the cursor is not on such line but line
// = 0,
// use the current filename.
std::string path;
if (params.position.line == 0)
path = file->def->path;
for (const IndexInclude& include : file->def->includes) for (const IndexInclude& include : file->def->includes)
if (include.line == request->params.position.line) { if (include.line == params.position.line) {
// |include| is the line the cursor is on. path = include.resolved_path;
for (QueryFile& file1 : db->files)
if (file1.def)
for (const IndexInclude& include1 : file1.def->includes)
if (include1.resolved_path == include.resolved_path) {
// Another file |file1| has the same include line.
lsLocationEx result;
result.uri = lsDocumentUri::FromPath(file1.def->path);
result.range.start.line = result.range.end.line =
include1.line;
out.result.push_back(std::move(result));
break;
}
break; break;
} }
if (path.size())
for (QueryFile& file1 : db->files)
if (file1.def)
for (const IndexInclude& include : file1.def->includes)
if (include.resolved_path == path) {
// Another file |file1| has the same include line.
lsLocationEx result;
result.uri = lsDocumentUri::FromPath(file1.def->path);
result.range.start.line = result.range.end.line =
include.line;
out.result.push_back(std::move(result));
break;
}
}
if ((int)out.result.size() >= g_config->xref.maxNum) if ((int)out.result.size() >= g_config->xref.maxNum)
out.result.resize(g_config->xref.maxNum); out.result.resize(g_config->xref.maxNum);

View File

@ -318,21 +318,20 @@ std::optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file, std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
QueryFile* file, QueryFile* file,
lsPosition position) { lsPosition& ls_pos) {
std::vector<SymbolRef> symbols; std::vector<SymbolRef> symbols;
symbols.reserve(1);
int target_line = position.line;
int target_column = position.character;
if (working_file) { if (working_file) {
std::optional<int> index_line = working_file->GetIndexPosFromBufferPos( if (auto line = working_file->GetIndexPosFromBufferPos(
target_line, &target_column, false); ls_pos.line, &ls_pos.character, false)) {
if (index_line) ls_pos.line = *line;
target_line = *index_line; } else {
ls_pos.line = -1;
return {};
}
} }
for (const SymbolRef& sym : file->def->all_symbols) { for (const SymbolRef& sym : file->def->all_symbols) {
if (sym.range.Contains(target_line, target_column)) if (sym.range.Contains(ls_pos.line, ls_pos.character))
symbols.push_back(sym); symbols.push_back(sym);
} }

View File

@ -50,7 +50,7 @@ std::optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file, std::vector<SymbolRef> FindSymbolsAtLocation(WorkingFile* working_file,
QueryFile* file, QueryFile* file,
lsPosition position); lsPosition& ls_pos);
template <typename Fn> template <typename Fn>
void WithEntity(QueryDatabase* db, SymbolIdx sym, Fn&& fn) { void WithEntity(QueryDatabase* db, SymbolIdx sym, Fn&& fn) {