From fa384c817118fc61d2ccbfbd27a1c4bc8ba2d378 Mon Sep 17 00:00:00 2001 From: Itamar Date: Sun, 27 Feb 2022 19:02:39 +0200 Subject: [PATCH] LanguageServers/Cpp: Make go to declaration of a namespace work The CppComprehensionEngine can now find the declaration of a reference to a namespace. --- .../Cpp/CppComprehensionEngine.cpp | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp index 107b6f40f3..32ac408db1 100644 --- a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp +++ b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp @@ -198,6 +198,9 @@ Vector CppComprehensionEngine::scope_of_reference_to_symbol(const AS Vector scope_parts; for (auto& scope_part : name->scope()) { + // If the target node is part of a scope reference, we want to end the scope chain before it. + if (&scope_part == &node) + break; scope_parts.append(scope_part.name()); } return scope_parts; @@ -444,7 +447,8 @@ struct TargetDeclaration { Variable, Type, Function, - Property + Property, + Scope } type; String name; }; @@ -470,6 +474,13 @@ static Optional get_target_declaration(const ASTNode& node) static Optional get_target_declaration(const ASTNode& node, String name) { + + if (node.parent() && node.parent()->is_name()) { + if (&node != verify_cast(node.parent())->name()) { + return TargetDeclaration { TargetDeclaration::Type::Scope, name }; + } + } + if ((node.parent() && node.parent()->is_function_call()) || (node.parent()->is_name() && node.parent()->parent() && node.parent()->parent()->is_function_call())) { return TargetDeclaration { TargetDeclaration::Type::Function, name }; } @@ -499,6 +510,7 @@ RefPtr CppComprehensionEngine::find_declaration_of(const DocumentDa bool match_type = target_decl.value().type == TargetDeclaration::Type && symbol.declaration->is_struct_or_class(); bool match_property = target_decl.value().type == TargetDeclaration::Property && symbol.declaration->parent()->is_declaration() && verify_cast(symbol.declaration->parent())->is_struct_or_class(); bool match_parameter = target_decl.value().type == TargetDeclaration::Variable && symbol.declaration->is_parameter(); + bool match_scope = target_decl.value().type == TargetDeclaration::Scope && (symbol.declaration->is_namespace() || symbol.declaration->is_struct_or_class()); if (match_property) { // FIXME: This is not really correct, we also need to check that the type of the struct/class matches (not just the property name) @@ -511,7 +523,7 @@ RefPtr CppComprehensionEngine::find_declaration_of(const DocumentDa return false; } - if (match_function || match_type) { + if (match_function || match_type || match_scope) { if (symbol.name.name == target_decl->name) return true; } @@ -771,19 +783,22 @@ String CppComprehensionEngine::SymbolName::to_string() const bool CppComprehensionEngine::is_symbol_available(const Symbol& symbol, const Vector& current_scope, const Vector& reference_scope) { + if (!reference_scope.is_empty()) { return reference_scope == symbol.name.scope; } - // FIXME: Consider "using namespace ..." + // FIXME: Take "using namespace ..." into consideration // Check if current_scope starts with symbol's scope if (symbol.name.scope.size() > current_scope.size()) return false; + for (size_t i = 0; i < symbol.name.scope.size(); ++i) { if (current_scope[i] != symbol.name.scope[i]) return false; } + return true; }