From 91febd7343a4d7b272142bd9444feb5ec072724c Mon Sep 17 00:00:00 2001 From: Jacob Dufault Date: Mon, 10 Apr 2017 23:02:53 -0700 Subject: [PATCH] Make goto declaration work from on a recursively defined type when used inside the type definition --- src/command_line.cc | 66 +++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/src/command_line.cc b/src/command_line.cc index f151a346..fda8c634 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -161,8 +161,18 @@ optional GetDefinitionExtentOfSymbol(QueryableDatabase* db, c return nullopt; } -std::vector GetDeclarationsOfSymbol(QueryableDatabase* db, const SymbolIdx& symbol) { +std::vector GetDeclarationsOfSymbolForGotoDefinition(QueryableDatabase* db, const SymbolIdx& symbol) { 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 declaration = db->types[symbol.idx].def.definition_spelling; + if (declaration) + return { *declaration }; + break; + } case SymbolKind::Func: return db->funcs[symbol.idx].declarations; case SymbolKind::Var: { @@ -781,38 +791,42 @@ void QueryDbMainLoop( for (const SymbolRef& ref : file->def.all_symbols) { if (ref.loc.range.Contains(target_line, target_column)) { // Found symbol. Return definition. + + optional definition_spelling = GetDefinitionSpellingOfSymbol(db, ref.idx); - if (definition_spelling) { + if (!definition_spelling) + break; - // If the cursor is currently at the definition we should goto the declaration if possible. - if (definition_spelling->path == file_id && definition_spelling->range.Contains(target_line, target_column)) { - // Goto declaration. + // We use spelling start and extent end because this causes vscode + // to highlight the entire definition when previewing / hoving with + // the mouse. + optional extent = GetDefinitionExtentOfSymbol(db, ref.idx); + if (extent) + definition_spelling->range.end = extent->range.end; - std::vector declarations = GetDeclarationsOfSymbol(db, ref.idx); - for (auto declaration : declarations) { - optional ls_declaration = GetLsLocation(db, working_files, declaration); - if (ls_declaration) - response.result.push_back(*ls_declaration); - } - if (!response.result.empty()) - break; + // 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)) { + // Goto declaration. + + std::vector declarations = GetDeclarationsOfSymbolForGotoDefinition(db, ref.idx); + for (auto declaration : declarations) { + optional ls_declaration = GetLsLocation(db, working_files, declaration); + if (ls_declaration) + response.result.push_back(*ls_declaration); } - - // 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 extent = GetDefinitionExtentOfSymbol(db, ref.idx); - if (extent) - definition_spelling->range.end = extent->range.end; - - optional ls_location = GetLsLocation(db, working_files, definition_spelling.value()); - if (ls_location) - response.result.push_back(*ls_location); + if (!response.result.empty()) + break; } + + + // Goto definition. + + + optional ls_location = GetLsLocation(db, working_files, definition_spelling.value()); + if (ls_location) + response.result.push_back(*ls_location); break; } }