Refactor out FindSymbolsAtLocation

This commit is contained in:
Jacob Dufault 2017-04-14 22:14:05 -07:00
parent c946fd1b8e
commit 1791f4c3b7

View File

@ -468,6 +468,20 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryableDatabase* db, WorkingFiles* working_
return edit; return edit;
} }
std::vector<SymbolRef> FindSymbolsAtLocation(QueryableFile* file, lsPosition position) {
std::vector<SymbolRef> symbols;
symbols.reserve(1);
int target_line = position.line + 1;
int target_column = position.character + 1;
for (const SymbolRef& ref : file->def.all_symbols) {
if (ref.loc.range.Contains(target_line, target_column))
symbols.push_back(ref);
}
return symbols;
}
} // namespace } // namespace
@ -489,6 +503,34 @@ lsWorkspaceEdit BuildWorkspaceEdit(QueryableDatabase* db, WorkingFiles* working_
@ -889,18 +931,11 @@ void QueryDbMainLoop(
Out_TextDocumentRename response; Out_TextDocumentRename response;
response.id = msg->id; response.id = msg->id;
// TODO: consider refactoring into FindSymbolsAtLocation(file); for (const SymbolRef& ref : FindSymbolsAtLocation(file, msg->params.position)) {
int target_line = msg->params.position.line + 1; // Found symbol. Return references to rename.
int target_column = msg->params.position.character + 1; std::vector<QueryableLocation> uses = GetUsesOfSymbol(db, ref.idx);
for (const SymbolRef& ref : file->def.all_symbols) { response.result = BuildWorkspaceEdit(db, working_files, uses, msg->params.newName);
if (ref.loc.range.start.line >= target_line && ref.loc.range.end.line <= target_line && break;
ref.loc.range.start.column <= target_column && ref.loc.range.end.column >= target_column) {
// Found symbol. Return references to rename.
std::vector<QueryableLocation> uses = GetUsesOfSymbol(db, ref.idx);
response.result = BuildWorkspaceEdit(db, working_files, uses, msg->params.newName);
break;
}
} }
response.Write(std::cerr); response.Write(std::cerr);
@ -939,49 +974,47 @@ void QueryDbMainLoop(
int target_line = msg->params.position.line + 1; int target_line = msg->params.position.line + 1;
int target_column = msg->params.position.character + 1; int target_column = msg->params.position.character + 1;
for (const SymbolRef& ref : file->def.all_symbols) { for (const SymbolRef& ref : FindSymbolsAtLocation(file, msg->params.position)) {
if (ref.loc.range.Contains(target_line, target_column)) { // Found symbol. Return definition.
// Found symbol. Return definition.
// Special cases which are handled: // Special cases which are handled:
// - symbol has declaration but no definition (ie, pure virtual) // - symbol has declaration but no definition (ie, pure virtual)
// - start at spelling but end at extent for better mouse tooltip // - start at spelling but end at extent for better mouse tooltip
// - goto declaration while in definition of recursive type // - goto declaration while in definition of recursive type
optional<QueryableLocation> def_loc = GetDefinitionSpellingOfSymbol(db, ref.idx); optional<QueryableLocation> def_loc = GetDefinitionSpellingOfSymbol(db, ref.idx);
// We use spelling start and extent end because this causes vscode to // We use spelling start and extent end because this causes vscode to
// highlight the entire definition when previewing / hoving with the // highlight the entire definition when previewing / hoving with the
// mouse. // mouse.
optional<QueryableLocation> def_extent = GetDefinitionExtentOfSymbol(db, ref.idx); optional<QueryableLocation> def_extent = GetDefinitionExtentOfSymbol(db, ref.idx);
if (def_loc && def_extent) if (def_loc && def_extent)
def_loc->range.end = def_extent->range.end; def_loc->range.end = def_extent->range.end;
// If the cursor is currently at or in the definition we should goto // If the cursor is currently at or in the definition we should goto
// the declaration if possible. We also want to use declarations if // the declaration if possible. We also want to use declarations if
// we're pointing to, ie, a pure virtual function which has no // we're pointing to, ie, a pure virtual function which has no
// definition. // definition.
if (!def_loc || (def_loc->path == file_id && if (!def_loc || (def_loc->path == file_id &&
def_loc->range.Contains(target_line, target_column))) { def_loc->range.Contains(target_line, target_column))) {
// Goto declaration. // Goto declaration.
std::vector<QueryableLocation> declarations = GetDeclarationsOfSymbolForGotoDefinition(db, ref.idx); std::vector<QueryableLocation> declarations = GetDeclarationsOfSymbolForGotoDefinition(db, ref.idx);
for (auto declaration : declarations) { for (auto declaration : declarations) {
optional<lsLocation> ls_declaration = GetLsLocation(db, working_files, declaration); optional<lsLocation> ls_declaration = GetLsLocation(db, working_files, declaration);
if (ls_declaration) if (ls_declaration)
response.result.push_back(*ls_declaration); response.result.push_back(*ls_declaration);
}
// We found some declarations. Break so we don't add the definition location.
if (!response.result.empty())
break;
} }
// We found some declarations. Break so we don't add the definition location.
if (def_loc)
PushBack(&response.result, GetLsLocation(db, working_files, *def_loc));
if (!response.result.empty()) if (!response.result.empty())
break; break;
} }
if (def_loc)
PushBack(&response.result, GetLsLocation(db, working_files, *def_loc));
if (!response.result.empty())
break;
} }
SendOutMessageToClient(language_client, response); SendOutMessageToClient(language_client, response);
@ -1000,31 +1033,24 @@ void QueryDbMainLoop(
Out_TextDocumentDocumentHighlight response; Out_TextDocumentDocumentHighlight response;
response.id = msg->id; response.id = msg->id;
// TODO: consider refactoring into FindSymbolsAtLocation(file); for (const SymbolRef& ref : FindSymbolsAtLocation(file, msg->params.position)) {
int target_line = msg->params.position.line + 1; // Found symbol. Return references to highlight.
int target_column = msg->params.position.character + 1; std::vector<QueryableLocation> uses = GetUsesOfSymbol(db, ref.idx);
for (const SymbolRef& ref : file->def.all_symbols) { response.result.reserve(uses.size());
if (ref.loc.range.start.line >= target_line && ref.loc.range.end.line <= target_line && for (const QueryableLocation& use : uses) {
ref.loc.range.start.column <= target_column && ref.loc.range.end.column >= target_column) { if (use.path != file_id)
continue;
// Found symbol. Return references to highlight. optional<lsLocation> ls_location = GetLsLocation(db, working_files, use);
std::vector<QueryableLocation> uses = GetUsesOfSymbol(db, ref.idx); if (!ls_location)
response.result.reserve(uses.size()); continue;
for (const QueryableLocation& use : uses) {
if (use.path != file_id)
continue;
optional<lsLocation> ls_location = GetLsLocation(db, working_files, use); lsDocumentHighlight highlight;
if (!ls_location) highlight.kind = lsDocumentHighlightKind::Text;
continue; highlight.range = ls_location->range;
response.result.push_back(highlight);
lsDocumentHighlight highlight;
highlight.kind = lsDocumentHighlightKind::Text;
highlight.range = ls_location->range;
response.result.push_back(highlight);
}
break;
} }
break;
} }
SendOutMessageToClient(language_client, response); SendOutMessageToClient(language_client, response);
@ -1042,22 +1068,15 @@ void QueryDbMainLoop(
Out_TextDocumentHover response; Out_TextDocumentHover response;
response.id = msg->id; response.id = msg->id;
// TODO: consider refactoring into FindSymbolsAtLocation(file); for (const SymbolRef& ref : FindSymbolsAtLocation(file, msg->params.position)) {
int target_line = msg->params.position.line + 1; // Found symbol. Return hover.
int target_column = msg->params.position.character + 1; optional<lsRange> ls_range = GetLsRange(working_files->GetFileByFilename(file->def.usr), ref.loc.range);
for (const SymbolRef& ref : file->def.all_symbols) { if (!ls_range)
if (ref.loc.range.start.line >= target_line && ref.loc.range.end.line <= target_line && continue;
ref.loc.range.start.column <= target_column && ref.loc.range.end.column >= target_column) {
// Found symbol. Return hover. response.result.contents = GetHoverForSymbol(db, ref.idx);
optional<lsRange> ls_range = GetLsRange(working_files->GetFileByFilename(file->def.usr), ref.loc.range); response.result.range = *ls_range;
if (!ls_range) break;
continue;
response.result.contents = GetHoverForSymbol(db, ref.idx);
response.result.range = *ls_range;
break;
}
} }
SendOutMessageToClient(language_client, response); SendOutMessageToClient(language_client, response);
@ -1076,32 +1095,25 @@ void QueryDbMainLoop(
Out_TextDocumentReferences response; Out_TextDocumentReferences response;
response.id = msg->id; response.id = msg->id;
// TODO: consider refactoring into FindSymbolsAtLocation(file); for (const SymbolRef& ref : FindSymbolsAtLocation(file, msg->params.position)) {
int target_line = msg->params.position.line + 1; optional<QueryableLocation> excluded_declaration;
int target_column = msg->params.position.character + 1; if (!msg->params.context.includeDeclaration) {
for (const SymbolRef& ref : file->def.all_symbols) { std::cerr << "Excluding declaration in references" << std::endl;
if (ref.loc.range.start.line >= target_line && ref.loc.range.end.line <= target_line && excluded_declaration = GetDefinitionSpellingOfSymbol(db, ref.idx);
ref.loc.range.start.column <= target_column && ref.loc.range.end.column >= target_column) {
optional<QueryableLocation> excluded_declaration;
if (!msg->params.context.includeDeclaration) {
std::cerr << "Excluding declaration in references" << std::endl;
excluded_declaration = GetDefinitionSpellingOfSymbol(db, ref.idx);
}
// Found symbol. Return references.
std::vector<QueryableLocation> uses = GetUsesOfSymbol(db, ref.idx);
response.result.reserve(uses.size());
for (const QueryableLocation& use : uses) {
if (excluded_declaration.has_value() && use == *excluded_declaration)
continue;
optional<lsLocation> ls_location = GetLsLocation(db, working_files, use);
if (ls_location)
response.result.push_back(*ls_location);
}
break;
} }
// Found symbol. Return references.
std::vector<QueryableLocation> uses = GetUsesOfSymbol(db, ref.idx);
response.result.reserve(uses.size());
for (const QueryableLocation& use : uses) {
if (excluded_declaration.has_value() && use == *excluded_declaration)
continue;
optional<lsLocation> ls_location = GetLsLocation(db, working_files, use);
if (ls_location)
response.result.push_back(*ls_location);
}
break;
} }
SendOutMessageToClient(language_client, response); SendOutMessageToClient(language_client, response);