From 9ee26d4d8d1445421bfe33083cf66962eeee6acd Mon Sep 17 00:00:00 2001 From: Julien FAUCHER Date: Sun, 12 Jan 2025 14:17:41 +0100 Subject: [PATCH] Add scope lookup and restore _h_list_symbols `_h_list_symbols` used as `diplomat-server.list-symbols` to get symbols in a given file. Fixes #17 --- CHANGELOG.md | 2 + indexer/include/index_core.hpp | 8 +++ indexer/include/index_scope.hpp | 10 ++++ indexer/index_core.cpp | 5 ++ indexer/index_scope.cpp | 20 +++++++ .../diplomat/src/diplomat_lsp_binds.cpp | 54 ++++--------------- 6 files changed, 55 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3db228d..4935f54 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Added - Added scope-aware completion. + - Added scope lookup by path method in the indexer. - Added `--version` management for sv-indexer (same version as LSP) ## Changed @@ -14,6 +15,7 @@ ## Fixed - Avoid spurious errors in log due to unknown command `textDocument/didClose` + - Fixed `diplomat-server.list-symbols` to handle design path as an input (#17) # 0.2.1 diff --git a/indexer/include/index_core.hpp b/indexer/include/index_core.hpp index 586f7d8..2472211 100644 --- a/indexer/include/index_core.hpp +++ b/indexer/include/index_core.hpp @@ -52,6 +52,14 @@ namespace diplomat::index const IndexSymbol* get_symbol_by_position(const IndexLocation& pos) ; + /** + * @brief Get a scope by its fully qualified path (starting from the root) + * + * @param path to evaluate + * @return IndexScope* if found, nullptr otherwise. + */ + IndexScope* lookup_scope(const std::string_view& path); + IndexCore() = default; ~IndexCore() = default; }; diff --git a/indexer/include/index_scope.hpp b/indexer/include/index_scope.hpp index 6070fcd..14ec1c9 100644 --- a/indexer/include/index_scope.hpp +++ b/indexer/include/index_scope.hpp @@ -153,6 +153,16 @@ namespace diplomat::index */ IndexSymbol* resolve_symbol(const std::string_view& path); + /** + * @brief Retrieve a sub scope based upon its fully qualified name, relative to the + * current scope. + * + * @param path relative to the current scope + * @return IndexScope* if found, nullptr otherwise. + */ + IndexScope* resolve_scope(const std::string_view& path); + + /** * @brief Get the visible symbols object from the current scope. * This represent all symbols declared here and all symbols declared in parents. diff --git a/indexer/index_core.cpp b/indexer/index_core.cpp index 50b64a8..97cc8ea 100644 --- a/indexer/index_core.cpp +++ b/indexer/index_core.cpp @@ -65,6 +65,11 @@ namespace diplomat::index { return ref_file->lookup_symbol_by_location(pos); } + IndexScope* IndexCore::lookup_scope(const std::string_view& path) + { + return _root->resolve_scope(path); + } + void to_json(nlohmann::json &j, const IndexCore &s) { diff --git a/indexer/index_scope.cpp b/indexer/index_scope.cpp index 5b9d63b..1bc750c 100644 --- a/indexer/index_scope.cpp +++ b/indexer/index_scope.cpp @@ -110,6 +110,26 @@ namespace diplomat::index { } + IndexScope* IndexScope::resolve_scope(const std::string_view& path) + { + std::size_t dot_pos = path.find('.'); + if(std::string::npos == dot_pos) + return get_scope_by_name(std::string(path)); + else + { + std::string_view direct_lu = path.substr(0,dot_pos); + IndexScope* next_scope; + if((next_scope = get_scope_by_name(direct_lu)) != nullptr) + { + std::string_view remaining_path = path.substr(dot_pos+1); + return next_scope->resolve_scope(remaining_path); + } + else + return nullptr; + } + return nullptr; + } + std::vector IndexScope::get_visible_symbols() const { const IndexScope* lu_scope = this; diff --git a/lsp-server/diplomat/src/diplomat_lsp_binds.cpp b/lsp-server/diplomat/src/diplomat_lsp_binds.cpp index 6b56e53..b8b2429 100755 --- a/lsp-server/diplomat/src/diplomat_lsp_binds.cpp +++ b/lsp-server/diplomat/src/diplomat_lsp_binds.cpp @@ -683,12 +683,20 @@ void DiplomatLSP::_h_update_configuration(json ¶ms) send_request("workspace/configuration",LSP_MEMBER_BIND(DiplomatLSP,_h_get_configuration),conf_request); } + json DiplomatLSP::_h_list_symbols(json& params) { std::string path = params.at(0); std::map> ret; - const di::IndexFile* lu_file = _index->get_file(path); + const di::IndexScope* lu_scope = _index->lookup_scope(path); + + if(! lu_scope) + { + spdlog::warn("Unable to list symbols for scope {}: Scope not found.",path); + return ret; + } + const di::IndexFile* lu_file = _index->get_file(lu_scope->get_source_range().value_or(di::IndexRange()).start.file);// _index->get_file(path); if(! lu_file) { @@ -709,49 +717,7 @@ json DiplomatLSP::_h_list_symbols(json& params) ret.at(refrec.key->get_name()).push_back(_index_range_to_lsp(ref_range).range); } - - - // auto* compilation = get_compilation(); - // const slang::ast::Symbol* lookup_result = compilation->getRoot().lookupName(path); - // const slang::ast::Scope* scope; - - // if( lookup_result->kind == slang::ast::SymbolKind::Instance ) - // lookup_result = &(lookup_result->as().body); - - // if(! lookup_result->isScope()) - // scope = lookup_result->getParentScope(); - // else - // scope = &(lookup_result->as()); - - // spdlog::info("Request design list of symbol for path {}", path); - // const slang::ast::InstanceBodySymbol* target_instance_body = scope->getContainingInstance(); - - // if (!target_instance_body) - // throw slsp::lsp_request_failed_exception("Failed to lookup the required instance"); - - // std::filesystem::path file_for_index_lookup = _module_to_file.at(std::string(target_instance_body->name)); - - // std::unordered_map> ret; - // for (const slang::syntax::ConstTokenOrSyntax& tok : _index->get_symbols_tok_from_file(file_for_index_lookup)) - // { - // std::string name = std::string(tok.isNode() ? tok.node()->getFirstToken().valueText() : tok.token().valueText()); - // trim(name); - - // if (!name.empty()) - // { - // slsp::types::Range tok_range = _slang_to_lsp_location(tok.range()).range; - - // if (!ret.contains(name)) - // ret[name] = { tok_range }; - // else - // ret[name].push_back(tok_range); - - - // spdlog::debug(" Return {}", name); - // } - // } - - spdlog::debug("{}",json(ret).dump(4)); + // spdlog::debug("{}",json(ret).dump(4)); return ret; }