From f89f4af0b3e5735307a0c201e8e05267f90cdd72 Mon Sep 17 00:00:00 2001 From: Itamar Date: Sun, 9 May 2021 20:51:52 +0300 Subject: [PATCH] CppLanguageServer: Don't suggest inaccessible declarations Previously, declarations that are not available in the global namespace, such as member functions of a class, would also appear in the autocomplete suggestions list. To fix this, we now only recurse into scopes of namespaces and classes when fetching declarations if we want to retrieve all the available declarations in the document (For the use of Locator & ClassView). --- .../Cpp/ParserAutoComplete.cpp | 29 ++++++++++++------- .../LanguageServers/Cpp/ParserAutoComplete.h | 12 ++++++-- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/Userland/DevTools/HackStudio/LanguageServers/Cpp/ParserAutoComplete.cpp b/Userland/DevTools/HackStudio/LanguageServers/Cpp/ParserAutoComplete.cpp index cee25de4af..ff294b717f 100644 --- a/Userland/DevTools/HackStudio/LanguageServers/Cpp/ParserAutoComplete.cpp +++ b/Userland/DevTools/HackStudio/LanguageServers/Cpp/ParserAutoComplete.cpp @@ -91,7 +91,7 @@ Vector ParserAutoComplete::get_suggestions(con return autocomplete_name(document, *node, partial_text.view()); } -NonnullRefPtrVector ParserAutoComplete::get_available_declarations(const DocumentData& document, const ASTNode& node) const +NonnullRefPtrVector ParserAutoComplete::get_available_declarations(const DocumentData& document, const ASTNode& node, RecurseIntoScopes recurse_into_scopes) const { const Cpp::ASTNode* current = &node; NonnullRefPtrVector available_declarations; @@ -100,13 +100,13 @@ NonnullRefPtrVector ParserAutoComplete::get_available_declarations( current = current->parent(); } - available_declarations.append(get_global_declarations_including_headers(document)); + available_declarations.append(get_global_declarations_including_headers(document, recurse_into_scopes)); return available_declarations; } Vector ParserAutoComplete::autocomplete_name(const DocumentData& document, const ASTNode& node, const String& partial_text) const { - auto available_declarations = get_available_declarations(document, node); + auto available_declarations = get_available_declarations(document, node, RecurseIntoScopes::No); Vector available_names; auto add_name = [&available_names](auto& name) { if (name.is_null() || name.is_empty()) @@ -237,7 +237,7 @@ String ParserAutoComplete::type_of(const DocumentData& document, const Expressio Vector ParserAutoComplete::properties_of_type(const DocumentData& document, const String& type) const { - auto declarations = get_global_declarations_including_headers(document); + auto declarations = get_global_declarations_including_headers(document, RecurseIntoScopes::Yes); Vector properties; for (auto& decl : declarations) { if (!decl.is_struct_or_class()) @@ -252,25 +252,32 @@ Vector ParserAutoComplete::properties_of_type( return properties; } -NonnullRefPtrVector ParserAutoComplete::get_global_declarations_including_headers(const DocumentData& document) const +NonnullRefPtrVector ParserAutoComplete::get_global_declarations_including_headers(const DocumentData& document, RecurseIntoScopes recurse_into_scopes) const { NonnullRefPtrVector declarations; for (auto& decl : document.m_declarations_from_headers) declarations.append(*decl); - declarations.append(get_global_declarations(*document.parser().root_node())); + declarations.append(get_global_declarations(document, recurse_into_scopes)); return declarations; } -NonnullRefPtrVector ParserAutoComplete::get_global_declarations(const ASTNode& node) const +NonnullRefPtrVector ParserAutoComplete::get_global_declarations(const DocumentData& document, RecurseIntoScopes recurse_into_scopes) const +{ + if (recurse_into_scopes == RecurseIntoScopes::Yes) + return get_declarations_recursive(*document.parser().root_node()); + return document.parser().root_node()->declarations(); +} + +NonnullRefPtrVector ParserAutoComplete::get_declarations_recursive(const ASTNode& node) const { NonnullRefPtrVector declarations; for (auto& decl : node.declarations()) { declarations.append(decl); if (decl.is_namespace()) { - declarations.append(get_global_declarations(decl)); + declarations.append(get_declarations_recursive(decl)); } if (decl.is_struct_or_class()) { for (auto& member_decl : static_cast(decl).declarations()) { @@ -395,7 +402,7 @@ RefPtr ParserAutoComplete::find_declaration_of(const DocumentData& if (!target_decl.has_value()) return {}; - auto declarations = get_available_declarations(document_data, node); + auto declarations = get_available_declarations(document_data, node, RecurseIntoScopes::Yes); for (auto& decl : declarations) { if (decl.is_function() && target_decl.value().type == TargetDeclaration::Function) { if (((Cpp::FunctionDeclaration&)decl).m_name == target_decl.value().name) @@ -430,13 +437,13 @@ void ParserAutoComplete::update_declared_symbols(DocumentData& document) auto included_document = get_or_create_document_data(document_path_from_include_path(include)); if (!included_document) continue; - for (auto&& decl : get_global_declarations_including_headers(*included_document)) + for (auto&& decl : get_global_declarations_including_headers(*included_document, RecurseIntoScopes::Yes)) document.m_declarations_from_headers.set(move(decl)); } Vector declarations; - for (auto& decl : get_global_declarations(*document.parser().root_node())) { + for (auto& decl : get_declarations_recursive(*document.parser().root_node())) { declarations.append({ decl.name(), { document.filename(), decl.start().line, decl.start().column }, type_of_declaration(decl), scope_of_declaration(decl) }); } diff --git a/Userland/DevTools/HackStudio/LanguageServers/Cpp/ParserAutoComplete.h b/Userland/DevTools/HackStudio/LanguageServers/Cpp/ParserAutoComplete.h index 6ea99fc66a..c8742e0d51 100644 --- a/Userland/DevTools/HackStudio/LanguageServers/Cpp/ParserAutoComplete.h +++ b/Userland/DevTools/HackStudio/LanguageServers/Cpp/ParserAutoComplete.h @@ -72,15 +72,21 @@ private: bool is_property(const ASTNode&) const; bool is_empty_property(const DocumentData&, const ASTNode&, const Position& autocomplete_position) const; RefPtr find_declaration_of(const DocumentData&, const ASTNode&) const; - NonnullRefPtrVector get_available_declarations(const DocumentData&, const ASTNode&) const; + + enum class RecurseIntoScopes { + No, + Yes + }; + NonnullRefPtrVector get_available_declarations(const DocumentData&, const ASTNode&, RecurseIntoScopes) const; struct PropertyInfo { StringView name; RefPtr type; }; Vector properties_of_type(const DocumentData& document, const String& type) const; - NonnullRefPtrVector get_global_declarations_including_headers(const DocumentData& document) const; - NonnullRefPtrVector get_global_declarations(const ASTNode& node) const; + NonnullRefPtrVector get_global_declarations_including_headers(const DocumentData&, RecurseIntoScopes) const; + NonnullRefPtrVector get_global_declarations(const DocumentData&, RecurseIntoScopes) const; + NonnullRefPtrVector get_declarations_recursive(const ASTNode&) const; const DocumentData* get_document_data(const String& file) const; const DocumentData* get_or_create_document_data(const String& file);