Make goto declaration work from on a recursively defined type when used inside the type definition

This commit is contained in:
Jacob Dufault 2017-04-10 23:02:53 -07:00
parent c9a251b7ab
commit 91febd7343

View File

@ -161,8 +161,18 @@ optional<QueryableLocation> GetDefinitionExtentOfSymbol(QueryableDatabase* db, c
return nullopt; return nullopt;
} }
std::vector<QueryableLocation> GetDeclarationsOfSymbol(QueryableDatabase* db, const SymbolIdx& symbol) { std::vector<QueryableLocation> GetDeclarationsOfSymbolForGotoDefinition(QueryableDatabase* db, const SymbolIdx& symbol) {
switch (symbol.kind) { switch (symbol.kind) {
case SymbolKind::Type: {
// Returning the definition spelling of a type is a hack (and is why the
// function has the postfix `ForGotoDefintion`, but it lets the user
// jump to the start of a type if clicking goto-definition on the same
// type from within the type definition.
optional<QueryableLocation> declaration = db->types[symbol.idx].def.definition_spelling;
if (declaration)
return { *declaration };
break;
}
case SymbolKind::Func: case SymbolKind::Func:
return db->funcs[symbol.idx].declarations; return db->funcs[symbol.idx].declarations;
case SymbolKind::Var: { case SymbolKind::Var: {
@ -781,14 +791,25 @@ void QueryDbMainLoop(
for (const SymbolRef& ref : file->def.all_symbols) { for (const SymbolRef& ref : file->def.all_symbols) {
if (ref.loc.range.Contains(target_line, target_column)) { if (ref.loc.range.Contains(target_line, target_column)) {
// Found symbol. Return definition. // Found symbol. Return definition.
optional<QueryableLocation> definition_spelling = GetDefinitionSpellingOfSymbol(db, ref.idx);
if (definition_spelling) {
// If the cursor is currently at the definition we should goto the declaration if possible.
optional<QueryableLocation> definition_spelling = GetDefinitionSpellingOfSymbol(db, ref.idx);
if (!definition_spelling)
break;
// We use spelling start and extent end because this causes vscode
// to highlight the entire definition when previewing / hoving with
// the mouse.
optional<QueryableLocation> extent = GetDefinitionExtentOfSymbol(db, ref.idx);
if (extent)
definition_spelling->range.end = extent->range.end;
// If the cursor is currently at or in the definition we should goto the declaration if possible.
if (definition_spelling->path == file_id && definition_spelling->range.Contains(target_line, target_column)) { if (definition_spelling->path == file_id && definition_spelling->range.Contains(target_line, target_column)) {
// Goto declaration. // Goto declaration.
std::vector<QueryableLocation> declarations = GetDeclarationsOfSymbol(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)
@ -802,17 +823,10 @@ void QueryDbMainLoop(
// Goto definition. // Goto definition.
// We use spelling start and extent end because this causes vscode
// to highlight the entire definition when previewing / hoving with
// the mouse.
optional<QueryableLocation> extent = GetDefinitionExtentOfSymbol(db, ref.idx);
if (extent)
definition_spelling->range.end = extent->range.end;
optional<lsLocation> ls_location = GetLsLocation(db, working_files, definition_spelling.value()); optional<lsLocation> ls_location = GetLsLocation(db, working_files, definition_spelling.value());
if (ls_location) if (ls_location)
response.result.push_back(*ls_location); response.result.push_back(*ls_location);
}
break; break;
} }
} }