Explorar o código

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).
Itamar %!s(int64=4) %!d(string=hai) anos
pai
achega
d7aa831a43

+ 4 - 4
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();
                 }
             }
         }

+ 1 - 1
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())

+ 20 - 4
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<StringView> m_qualifiers;
 
+protected:
     Type(ASTNode* parent, Optional<Position> start, Optional<Position> 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<Position> start, Optional<Position> end, const String& filename)
+        : Type(parent, start, end, filename)
+    {
+    }
 
-    bool m_is_auto { false };
     RefPtr<Name> m_name;
-    Vector<StringView> m_qualifiers;
 };
 
 class Pointer : public Type {

+ 26 - 18
Userland/Libraries/LibCpp/Parser.cpp

@@ -229,6 +229,11 @@ NonnullRefPtr<BlockStatement> 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<Type> Parser::parse_type(ASTNode& parent)
 {
-    ScopeLogger<CPP_DEBUG> logger;
+    LOG_SCOPE();
 
-    if (!match_type()) {
+    if (!match_named_type()) {
+        error("expected named named_type");
         auto token = consume();
-        return create_ast_node<Type>(parent, token.start(), token.end());
+        return create_ast_node<NamedType>(parent, token.start(), token.end());
     }
 
-    auto type = create_ast_node<Type>(parent, position(), {});
+    auto named_type = create_ast_node<NamedType>(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 {
+        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_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);
+    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> type = named_type;
     while (!eof() && peek().type() == Token::Type::Asterisk) {
         type->set_end(position());
         auto asterisk = consume();
@@ -1184,7 +1192,7 @@ NonnullRefPtr<Type> 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());

+ 2 - 0
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<UnaryExpression> parse_unary_expression(ASTNode& parent);
     NonnullRefPtr<BooleanLiteral> parse_boolean_literal(ASTNode& parent);
     NonnullRefPtr<Type> parse_type(ASTNode& parent);
+    NonnullRefPtr<NamedType> parse_named_type(ASTNode& parent);
     NonnullRefPtr<BinaryExpression> parse_binary_expression(ASTNode& parent, NonnullRefPtr<Expression> lhs, BinaryOp);
     NonnullRefPtr<AssignmentExpression> parse_assignment_expression(ASTNode& parent, NonnullRefPtr<Expression> lhs, AssignmentOp);
     NonnullRefPtr<ForStatement> parse_for_statement(ASTNode& parent);