From b5a02b180c5ec7e0dabc4d7d9b79e0c462ef35da Mon Sep 17 00:00:00 2001 From: Itamar Date: Sat, 10 Jul 2021 15:17:08 +0300 Subject: [PATCH] LibCpp: Use fast_is and verify_cast to replace C-style casts Thanks to @alimpfard for suggesting this :) --- .../Cpp/CppComprehensionEngine.cpp | 36 ++++++++--------- Userland/Libraries/LibCpp/AST.h | 39 ++++++++++++++++++- 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp index e391e42919..e00cc853c0 100644 --- a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp +++ b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp @@ -220,13 +220,13 @@ bool CppComprehensionEngine::is_property(const ASTNode& node) const if (!node.parent()->is_member_expression()) return false; - auto& parent = (MemberExpression&)(*node.parent()); + auto& parent = verify_cast(*node.parent()); return parent.property() == &node; } String CppComprehensionEngine::type_of_property(const DocumentData& document, const Identifier& identifier) const { - auto& parent = (const MemberExpression&)(*identifier.parent()); + auto& parent = verify_cast(*identifier.parent()); VERIFY(parent.object()); auto properties = properties_of_type(document, type_of(document, *parent.object())); for (auto& prop : properties) { @@ -234,15 +234,15 @@ String CppComprehensionEngine::type_of_property(const DocumentData& document, co continue; const Type* type { nullptr }; if (prop.declaration->is_variable_declaration()) { - type = ((VariableDeclaration&)*prop.declaration).type(); + type = verify_cast(*prop.declaration).type(); } if (!type) continue; if (!type->is_named_type()) continue; - VERIFY(((NamedType const&)*type).name()); - return ((NamedType const&)*type).name()->full_name(); + VERIFY(verify_cast(*type).name()); + return verify_cast(*type).name()->full_name(); } return {}; } @@ -253,10 +253,10 @@ String CppComprehensionEngine::type_of_variable(const Identifier& identifier) co while (current) { for (auto& decl : current->declarations()) { if (decl.is_variable_or_parameter_declaration()) { - auto& var_or_param = (VariableOrParameterDeclaration&)decl; + auto& var_or_param = verify_cast(decl); if (var_or_param.name() == identifier.name() && var_or_param.type()->is_named_type()) { - VERIFY(((NamedType const&)(*var_or_param.type())).name()); - return ((NamedType const&)(*var_or_param.type())).name()->full_name(); + VERIFY(verify_cast(*var_or_param.type()).name()); + return verify_cast(*var_or_param.type()).name()->full_name(); } } } @@ -268,7 +268,7 @@ String CppComprehensionEngine::type_of_variable(const Identifier& identifier) co String CppComprehensionEngine::type_of(const DocumentData& document, const Expression& expression) const { if (expression.is_member_expression()) { - auto& member_expression = (const MemberExpression&)expression; + auto& member_expression = verify_cast(expression); VERIFY(member_expression.property()); if (member_expression.property()->is_identifier()) return type_of_property(document, static_cast(*member_expression.property())); @@ -305,7 +305,7 @@ Vector CppComprehensionEngine::properties_of_typ return {}; } - auto& struct_or_class = (StructOrClassDeclaration&)*decl; + auto& struct_or_class = verify_cast(*decl); VERIFY(struct_or_class.name() == type_symbol.name); Vector properties; @@ -474,7 +474,7 @@ RefPtr CppComprehensionEngine::find_declaration_of(const DocumentDa bool match_function = target_decl.value().type == TargetDeclaration::Function && symbol.declaration->is_function(); bool match_variable = target_decl.value().type == TargetDeclaration::Variable && symbol.declaration->is_variable_declaration(); 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() && ((Declaration*)symbol.declaration->parent())->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(); if (match_property) { @@ -752,7 +752,7 @@ Optional CppComprehensionEngine::ge FunctionCall* call_node { nullptr }; if (node->is_function_call()) { - call_node = ((FunctionCall*)node.ptr()); + call_node = verify_cast(node.ptr()); auto token = document.parser().token_at(cpp_position); @@ -766,7 +766,7 @@ Optional CppComprehensionEngine::ge while (!call_node && node) { auto parent_is_call = node->parent() && node->parent()->is_function_call(); if (parent_is_call) { - call_node = (FunctionCall*)node->parent(); + call_node = verify_cast(node->parent()); break; } node = node->parent(); @@ -801,14 +801,14 @@ Optional CppComprehensionEngine::get const Identifier* callee = nullptr; VERIFY(call_node.callee()); if (call_node.callee()->is_identifier()) { - callee = (const Identifier*)call_node.callee(); + callee = verify_cast(call_node.callee()); } else if (call_node.callee()->is_name()) { - callee = ((Name const&)*call_node.callee()).name(); + callee = verify_cast(*call_node.callee()).name(); } else if (call_node.callee()->is_member_expression()) { - auto& member_exp = ((MemberExpression const&)*call_node.callee()); + auto& member_exp = verify_cast(*call_node.callee()); VERIFY(member_exp.property()); if (member_exp.property()->is_identifier()) { - callee = (const Identifier*)member_exp.property(); + callee = verify_cast(member_exp.property()); } } @@ -828,7 +828,7 @@ Optional CppComprehensionEngine::get return {}; } - auto& func_decl = (FunctionDeclaration&)*decl; + auto& func_decl = verify_cast(*decl); auto document_of_declaration = get_document_data(func_decl.filename()); FunctionParamsHint hint {}; diff --git a/Userland/Libraries/LibCpp/AST.h b/Userland/Libraries/LibCpp/AST.h index 8b1edda722..2120599e8b 100644 --- a/Userland/Libraries/LibCpp/AST.h +++ b/Userland/Libraries/LibCpp/AST.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,9 @@ public: virtual const char* class_name() const = 0; virtual void dump(FILE* = stdout, size_t indent = 0) const; + template + bool fast_is() const = delete; + ASTNode* parent() const { return m_parent; } Position start() const { @@ -547,7 +551,6 @@ public: virtual const char* class_name() const override { return "FunctionCall"; } virtual void dump(FILE* = stdout, size_t indent = 0) const override; virtual bool is_function_call() const override { return true; } - virtual bool is_templatized() const { return false; } const Expression* callee() const { return m_callee.ptr(); } void set_callee(RefPtr&& callee) { m_callee = move(callee); } @@ -911,4 +914,38 @@ public: } }; +template<> +inline bool ASTNode::fast_is() const { return is_identifier(); } +template<> +inline bool ASTNode::fast_is() const { return is_member_expression(); } +template<> +inline bool ASTNode::fast_is() const { return is_variable_or_parameter_declaration(); } +template<> +inline bool ASTNode::fast_is() const { return is_function_call(); } +template<> +inline bool ASTNode::fast_is() const { return is_type(); } +template<> +inline bool ASTNode::fast_is() const { return is_declaration(); } +template<> +inline bool ASTNode::fast_is() const { return is_name(); } +template<> +inline bool ASTNode::fast_is() const { return is_dummy_node(); } + +template<> +inline bool ASTNode::fast_is() const { return is_declaration() && verify_cast(*this).is_variable_declaration(); } +template<> +inline bool ASTNode::fast_is() const { return is_declaration() && verify_cast(*this).is_struct_or_class(); } +template<> +inline bool ASTNode::fast_is() const { return is_declaration() && verify_cast(*this).is_function(); } +template<> +inline bool ASTNode::fast_is() const { return is_declaration() && verify_cast(*this).is_namespace(); } +template<> +inline bool ASTNode::fast_is() const { return is_declaration() && verify_cast(*this).is_function() && verify_cast(*this).is_constructor(); } +template<> +inline bool ASTNode::fast_is() const { return is_declaration() && verify_cast(*this).is_function() && verify_cast(*this).is_destructor(); } +template<> +inline bool ASTNode::fast_is() const { return is_type() && verify_cast(*this).is_named_type(); } +template<> +inline bool ASTNode::fast_is() const { return is_name() && verify_cast(*this).is_templatized(); } + }