From d7aa831a430800ed5ce16b00a0cdcc72e434eeba Mon Sep 17 00:00:00 2001 From: Itamar Date: Sat, 26 Jun 2021 15:34:23 +0300 Subject: [PATCH] LibCpp: Differentiate between Type and NamedType This adds a new ASTNode type called 'NamedType' which inherits from the Type node. Previously every Type node had a name field, but it was not logically accurate. For example, pointer types do not have a name (the pointed-to type may have one). --- .../Cpp/CppComprehensionEngine.cpp | 8 ++-- Userland/Libraries/LibCpp/AST.cpp | 2 +- Userland/Libraries/LibCpp/AST.h | 24 ++++++++-- Userland/Libraries/LibCpp/Parser.cpp | 48 +++++++++++-------- Userland/Libraries/LibCpp/Parser.h | 2 + 5 files changed, 55 insertions(+), 29 deletions(-) diff --git a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp index 4f1a05296d..8f5628bb17 100644 --- a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp +++ b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp @@ -227,8 +227,8 @@ String CppComprehensionEngine::type_of_property(const DocumentData& document, co auto& parent = (const MemberExpression&)(*identifier.parent()); auto properties = properties_of_type(document, type_of(document, *parent.m_object)); for (auto& prop : properties) { - if (prop.name == identifier.m_name) - return prop.type->m_name->full_name(); + if (prop.name == identifier.m_name && prop.type->is_named_type()) + return ((NamedType&)prop.type).m_name->full_name(); } return {}; } @@ -240,8 +240,8 @@ String CppComprehensionEngine::type_of_variable(const Identifier& identifier) co for (auto& decl : current->declarations()) { if (decl.is_variable_or_parameter_declaration()) { auto& var_or_param = (VariableOrParameterDeclaration&)decl; - if (var_or_param.m_name == identifier.m_name) { - return var_or_param.m_type->m_name->full_name(); + if (var_or_param.m_name == identifier.m_name && var_or_param.m_type->is_named_type()) { + return ((NamedType&)(*var_or_param.m_type)).m_name->full_name(); } } } diff --git a/Userland/Libraries/LibCpp/AST.cpp b/Userland/Libraries/LibCpp/AST.cpp index 69fc15a0e4..07ede080e8 100644 --- a/Userland/Libraries/LibCpp/AST.cpp +++ b/Userland/Libraries/LibCpp/AST.cpp @@ -75,7 +75,7 @@ void Type::dump(FILE* output, size_t indent) const outln(output, "{}", to_string()); } -String Type::to_string() const +String NamedType::to_string() const { String qualifiers_string; if (!m_qualifiers.is_empty()) diff --git a/Userland/Libraries/LibCpp/AST.h b/Userland/Libraries/LibCpp/AST.h index c882cda55b..c89f3388f3 100644 --- a/Userland/Libraries/LibCpp/AST.h +++ b/Userland/Libraries/LibCpp/AST.h @@ -198,19 +198,35 @@ class Type : public ASTNode { public: virtual ~Type() override = default; virtual const char* class_name() const override { return "Type"; } - virtual void dump(FILE* = stdout, size_t indent = 0) const override; virtual bool is_type() const override { return true; } virtual bool is_templatized() const { return false; } - virtual String to_string() const; + virtual bool is_named_type() const { return false; } + virtual String to_string() const = 0; + virtual void dump(FILE* = stdout, size_t indent = 0) const override; + bool m_is_auto { false }; + Vector m_qualifiers; + +protected: Type(ASTNode* parent, Optional start, Optional end, const String& filename) : ASTNode(parent, start, end, filename) { } +}; + +class NamedType : public Type { +public: + virtual ~NamedType() override = default; + virtual const char* class_name() const override { return "NamedType"; } + virtual String to_string() const override; + virtual bool is_named_type() const override { return true; } + + NamedType(ASTNode* parent, Optional start, Optional end, const String& filename) + : Type(parent, start, end, filename) + { + } - bool m_is_auto { false }; RefPtr m_name; - Vector m_qualifiers; }; class Pointer : public Type { diff --git a/Userland/Libraries/LibCpp/Parser.cpp b/Userland/Libraries/LibCpp/Parser.cpp index 6e5f825a32..4ef1c3ea2b 100644 --- a/Userland/Libraries/LibCpp/Parser.cpp +++ b/Userland/Libraries/LibCpp/Parser.cpp @@ -229,6 +229,11 @@ NonnullRefPtr Parser::parse_block_statement(ASTNode& parent) } bool Parser::match_type() +{ + return match_named_type(); +} + +bool Parser::match_named_type() { save_state(); ScopeGuard state_guard = [this] { load_state(); }; @@ -258,7 +263,7 @@ bool Parser::match_template_arguments() consume(); while (!eof() && peek().type() != Token::Type::Greater) { - if (!match_type()) + if (!match_named_type()) return false; parse_type(get_dummy_node()); } @@ -1148,35 +1153,38 @@ bool Parser::match_boolean_literal() NonnullRefPtr Parser::parse_type(ASTNode& parent) { - ScopeLogger logger; + LOG_SCOPE(); - if (!match_type()) { + if (!match_named_type()) { + error("expected named named_type"); auto token = consume(); - return create_ast_node(parent, token.start(), token.end()); + return create_ast_node(parent, token.start(), token.end()); } - auto type = create_ast_node(parent, position(), {}); + auto named_type = create_ast_node(parent, position(), {}); auto qualifiers = parse_type_qualifiers(); - type->m_qualifiers = move(qualifiers); + named_type->m_qualifiers = move(qualifiers); if (match_keyword("auto")) { consume(Token::Type::Keyword); - type->m_is_auto = true; - } else { - - if (match_keyword("struct")) { - consume(Token::Type::Keyword); // Consume struct prefix - } - - if (!match_name()) { - type->set_end(position()); - error(String::formatted("expected name instead of: {}", peek().text())); - return type; - } - type->m_name = parse_name(*type); + named_type->m_is_auto = true; + named_type->set_end(position()); + return named_type; } + if (match_keyword("struct")) { + consume(Token::Type::Keyword); // Consume struct prefix + } + + if (!match_name()) { + named_type->set_end(position()); + error(String::formatted("expected name instead of: {}", peek().text())); + return named_type; + } + named_type->m_name = parse_name(*named_type); + + NonnullRefPtr type = named_type; while (!eof() && peek().type() == Token::Type::Asterisk) { type->set_end(position()); auto asterisk = consume(); @@ -1184,7 +1192,7 @@ NonnullRefPtr Parser::parse_type(ASTNode& parent) type->set_parent(*ptr); ptr->m_pointee = type; ptr->set_end(position()); - return ptr; + type = ptr; } type->set_end(position()); diff --git a/Userland/Libraries/LibCpp/Parser.h b/Userland/Libraries/LibCpp/Parser.h index 8409144241..63b8e5278c 100644 --- a/Userland/Libraries/LibCpp/Parser.h +++ b/Userland/Libraries/LibCpp/Parser.h @@ -86,6 +86,7 @@ private: bool match_sizeof_expression(); bool match_braced_init_list(); bool match_type(); + bool match_named_type(); bool match_access_specifier(); bool match_constructor(const StringView& class_name); bool match_destructor(const StringView& class_name); @@ -111,6 +112,7 @@ private: NonnullRefPtr parse_unary_expression(ASTNode& parent); NonnullRefPtr parse_boolean_literal(ASTNode& parent); NonnullRefPtr parse_type(ASTNode& parent); + NonnullRefPtr parse_named_type(ASTNode& parent); NonnullRefPtr parse_binary_expression(ASTNode& parent, NonnullRefPtr lhs, BinaryOp); NonnullRefPtr parse_assignment_expression(ASTNode& parent, NonnullRefPtr lhs, AssignmentOp); NonnullRefPtr parse_for_statement(ASTNode& parent);