diff options
author | Itamar <itamar8910@gmail.com> | 2022-02-22 07:59:39 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-02-23 00:48:44 +0000 |
commit | 7b42abccf29a4be57a38cc17025757fa00e8ac5e (patch) | |
tree | 365db66927a89b426ab7d3dd8c3c60c5f0d5e48c /Userland | |
parent | 604309327ea06837f1d33d54571e7671b9f4b584 (diff) | |
download | serenity-7b42abccf29a4be57a38cc17025757fa00e8ac5e.zip |
LibCpp: Allow qualified names in AST Declaration nodes
Previously, the names of declarations where stored as a simple
StringView.
Because of that, we couldn't parse out-of-line function definitions,
which have qualified names.
For example, we couldn't parse the following snippet:
```
void MyClass::foo(){}
```
To fix this, we now store the name of a declaration with a
ASTNode::Name node, which represents a qualified named.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp | 28 | ||||
-rw-r--r-- | Userland/Libraries/LibCpp/AST.cpp | 44 | ||||
-rw-r--r-- | Userland/Libraries/LibCpp/AST.h | 16 | ||||
-rw-r--r-- | Userland/Libraries/LibCpp/Parser.cpp | 48 |
4 files changed, 79 insertions, 57 deletions
diff --git a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp index 3aac93136f..83dc968cbc 100644 --- a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp +++ b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp @@ -248,7 +248,9 @@ String CppComprehensionEngine::type_of_property(const DocumentData& document, co continue; VERIFY(verify_cast<NamedType>(*type).name()); - return verify_cast<NamedType>(*type).name()->full_name(); + if (verify_cast<NamedType>(*type).name()) + return verify_cast<NamedType>(*type).name()->full_name(); + return String::empty(); } return {}; } @@ -260,9 +262,11 @@ 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 = verify_cast<VariableOrParameterDeclaration>(decl); - if (var_or_param.name() == identifier.name() && var_or_param.type()->is_named_type()) { + if (var_or_param.full_name() == identifier.name() && var_or_param.type()->is_named_type()) { VERIFY(verify_cast<NamedType>(*var_or_param.type()).name()); - return verify_cast<NamedType>(*var_or_param.type()).name()->full_name(); + if (verify_cast<NamedType>(*var_or_param.type()).name()) + return verify_cast<NamedType>(*var_or_param.type()).name()->full_name(); + return String::empty(); } } } @@ -312,14 +316,14 @@ Vector<CppComprehensionEngine::Symbol> CppComprehensionEngine::properties_of_typ } auto& struct_or_class = verify_cast<StructOrClassDeclaration>(*decl); - VERIFY(struct_or_class.name() == type_symbol.name); + VERIFY(struct_or_class.full_name() == type_symbol.name); Vector<Symbol> properties; for (auto& member : struct_or_class.members()) { Vector<StringView> scope(type_symbol.scope); scope.append(type_symbol.name); // FIXME: We don't have to create the Symbol here, it should already exist in the 'm_symbol' table of some DocumentData we already parsed. - properties.append(Symbol::create(member.name(), scope, member, Symbol::IsLocal::No)); + properties.append(Symbol::create(member.full_name(), scope, member, Symbol::IsLocal::No)); } return properties; } @@ -339,7 +343,7 @@ Vector<CppComprehensionEngine::Symbol> CppComprehensionEngine::get_child_symbols Vector<Symbol> symbols; for (auto& decl : node.declarations()) { - symbols.append(Symbol::create(decl.name(), scope, decl, is_local)); + symbols.append(Symbol::create(decl.full_name(), scope, decl, is_local)); bool should_recurse = decl.is_namespace() || decl.is_struct_or_class() || decl.is_function(); bool are_child_symbols_local = decl.is_function(); @@ -348,7 +352,7 @@ Vector<CppComprehensionEngine::Symbol> CppComprehensionEngine::get_child_symbols continue; auto new_scope = scope; - new_scope.append(decl.name()); + new_scope.append(decl.full_name()); symbols.extend(get_child_symbols(decl, new_scope, are_child_symbols_local ? Symbol::IsLocal::Yes : is_local)); } @@ -453,11 +457,11 @@ static Optional<TargetDeclaration> get_target_declaration(const ASTNode& node) } if (node.is_declaration()) { - return get_target_declaration(node, verify_cast<Declaration>(node).name()); + return get_target_declaration(node, verify_cast<Declaration>(node).full_name()); } if (node.is_type() && node.parent() && node.parent()->is_declaration()) { - return get_target_declaration(*node.parent(), verify_cast<Declaration>(node.parent())->name()); + return get_target_declaration(*node.parent(), verify_cast<Declaration>(node.parent())->full_name()); } dbgln("get_target_declaration: Invalid argument node of type: {}", node.class_name()); @@ -641,11 +645,11 @@ Vector<StringView> CppComprehensionEngine::scope_of_node(const ASTNode& node) co StringView containing_scope; if (parent_decl.is_namespace()) - containing_scope = static_cast<NamespaceDeclaration&>(parent_decl).name(); + containing_scope = static_cast<NamespaceDeclaration&>(parent_decl).full_name(); if (parent_decl.is_struct_or_class()) - containing_scope = static_cast<StructOrClassDeclaration&>(parent_decl).name(); + containing_scope = static_cast<StructOrClassDeclaration&>(parent_decl).full_name(); if (parent_decl.is_function()) - containing_scope = static_cast<FunctionDeclaration&>(parent_decl).name(); + containing_scope = static_cast<FunctionDeclaration&>(parent_decl).full_name(); parent_scope.append(containing_scope); return parent_scope; diff --git a/Userland/Libraries/LibCpp/AST.cpp b/Userland/Libraries/LibCpp/AST.cpp index ad0bf407b4..30087afd09 100644 --- a/Userland/Libraries/LibCpp/AST.cpp +++ b/Userland/Libraries/LibCpp/AST.cpp @@ -41,7 +41,7 @@ void FunctionDeclaration::dump(FILE* output, size_t indent) const m_return_type->dump(output, indent + 1); if (!m_name.is_null()) { print_indent(output, indent + 1); - outln(output, "{}", m_name); + outln(output, "{}", m_name->full_name()); } print_indent(output, indent + 1); outln(output, "("); @@ -125,9 +125,9 @@ String FunctionType::to_string() const else builder.append(", "); builder.append(parameter.type()->to_string()); - if (!parameter.name().is_empty()) { + if (parameter.name() && !parameter.full_name().is_empty()) { builder.append(" "); - builder.append(parameter.name()); + builder.append(parameter.full_name()); } } builder.append(")"); @@ -143,7 +143,7 @@ void Parameter::dump(FILE* output, size_t indent) const } if (!m_name.is_null()) { print_indent(output, indent); - outln(output, "{}", m_name); + outln(output, "{}", m_name->full_name()); } if (m_type) m_type->dump(output, indent + 1); @@ -176,7 +176,7 @@ void VariableDeclaration::dump(FILE* output, size_t indent) const if (m_type) m_type->dump(output, indent + 1); print_indent(output, indent + 1); - outln(output, "{}", m_name); + outln(output, "{}", full_name()); if (m_initial_value) m_initial_value->dump(output, indent + 1); } @@ -318,7 +318,7 @@ void EnumDeclaration::dump(FILE* output, size_t indent) const { ASTNode::dump(output, indent); print_indent(output, indent); - outln(output, "{}", m_name); + outln(output, "{}", full_name()); for (auto& entry : m_entries) { print_indent(output, indent + 1); outln(output, "{}", entry.name); @@ -331,7 +331,7 @@ void StructOrClassDeclaration::dump(FILE* output, size_t indent) const { ASTNode::dump(output, indent); print_indent(output, indent); - outln(output, "{}", m_name); + outln(output, "{}", full_name()); for (auto& member : m_members) { member.dump(output, indent + 1); } @@ -510,7 +510,7 @@ void NamespaceDeclaration::dump(FILE* output, size_t indent) const { ASTNode::dump(output, indent); print_indent(output, indent + 1); - outln(output, "{}", m_name); + outln(output, "{}", full_name()); for (auto& decl : m_declarations) decl.dump(output, indent + 1); } @@ -527,19 +527,26 @@ void Name::dump(FILE* output, size_t indent) const outln(output, "{}", full_name()); } -String Name::full_name() const +StringView Name::full_name() const { + if (m_full_name.has_value()) + return *m_full_name; + StringBuilder builder; if (!m_scope.is_empty()) { for (auto& scope : m_scope) { builder.appendff("{}::", scope.name()); } } - return String::formatted("{}{}", builder.to_string(), m_name.is_null() ? "" : m_name->name()); + m_full_name = String::formatted("{}{}", builder.to_string(), m_name.is_null() ? "" : m_name->name()); + return *m_full_name; } -String TemplatizedName::full_name() const +StringView TemplatizedName::full_name() const { + if (m_full_name.has_value()) + return *m_full_name; + StringBuilder name; name.append(Name::full_name()); name.append('<'); @@ -547,7 +554,8 @@ String TemplatizedName::full_name() const name.append(type.to_string()); } name.append('>'); - return name.to_string(); + m_full_name = name.to_string(); + return *m_full_name; } void CppCastExpression::dump(FILE* output, size_t indent) const @@ -624,4 +632,16 @@ void Destructor::dump(FILE* output, size_t indent) const } } +StringView Declaration::full_name() const +{ + if (!m_full_name.has_value()) { + if (m_name) + m_full_name = m_name->full_name(); + else + m_full_name = String::empty(); + } + + return *m_full_name; +} + } diff --git a/Userland/Libraries/LibCpp/AST.h b/Userland/Libraries/LibCpp/AST.h index 8ee5a0ae04..537ab5509c 100644 --- a/Userland/Libraries/LibCpp/AST.h +++ b/Userland/Libraries/LibCpp/AST.h @@ -125,8 +125,9 @@ public: virtual bool is_function() const { return false; } virtual bool is_namespace() const { return false; } bool is_member() const { return parent() != nullptr && parent()->is_declaration() && verify_cast<Declaration>(parent())->is_struct_or_class(); } - StringView name() const { return m_name; } - void set_name(StringView name) { m_name = move(name); } + const Name* name() const { return m_name; } + StringView full_name() const; + void set_name(RefPtr<Name> name) { m_name = move(name); } protected: Declaration(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename) @@ -134,7 +135,8 @@ protected: { } - StringView m_name; + RefPtr<Name> m_name; + mutable Optional<String> m_full_name; }; class InvalidDeclaration : public Declaration { @@ -204,7 +206,7 @@ public: virtual void dump(FILE* = stdout, size_t indent = 0) const override; virtual bool is_parameter() const override { return true; } - Parameter(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename, StringView name) + Parameter(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename, RefPtr<Name> name) : VariableOrParameterDeclaration(parent, start, end, filename) { m_name = name; @@ -436,7 +438,7 @@ public: : Expression(parent, start, end, filename) { } - virtual String full_name() const; + virtual StringView full_name() const; const Identifier* name() const { return m_name.ptr(); } void set_name(RefPtr<Identifier>&& name) { m_name = move(name); } @@ -447,6 +449,7 @@ public: private: RefPtr<Identifier> m_name; NonnullRefPtrVector<Identifier> m_scope; + mutable Optional<String> m_full_name; }; class TemplatizedName : public Name { @@ -454,7 +457,7 @@ public: virtual ~TemplatizedName() override = default; virtual const char* class_name() const override { return "TemplatizedName"; } virtual bool is_templatized() const override { return true; } - virtual String full_name() const override; + virtual StringView full_name() const override; TemplatizedName(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename) : Name(parent, start, end, filename) @@ -465,6 +468,7 @@ public: private: NonnullRefPtrVector<Type> m_template_arguments; + mutable Optional<String> m_full_name; }; class NumericLiteral : public Expression { diff --git a/Userland/Libraries/LibCpp/Parser.cpp b/Userland/Libraries/LibCpp/Parser.cpp index f1dec3a00d..c5fdb17080 100644 --- a/Userland/Libraries/LibCpp/Parser.cpp +++ b/Userland/Libraries/LibCpp/Parser.cpp @@ -104,8 +104,7 @@ NonnullRefPtr<FunctionDeclaration> Parser::parse_function_declaration(ASTNode& p func->set_qualifiers(parse_function_qualifiers()); func->set_return_type(parse_type(*func)); - auto function_name = consume(Token::Type::Identifier); - func->set_name(text_of_token(function_name)); + func->set_name(parse_name(*func)); consume(Token::Type::LeftParen); auto parameters = parse_parameter_list(*func); @@ -318,7 +317,7 @@ NonnullRefPtr<VariableDeclaration> Parser::parse_variable_declaration(ASTNode& p return var; } var->set_type(parse_type(var)); - auto identifier_token = consume(Token::Type::Identifier); + auto name = parse_name(*var); RefPtr<Expression> initial_value; if (match(Token::Type::Equals)) { @@ -334,7 +333,7 @@ NonnullRefPtr<VariableDeclaration> Parser::parse_variable_declaration(ASTNode& p consume(Token::Type::Semicolon); var->set_end(position()); - var->set_name(text_of_token(identifier_token)); + var->set_name(name); var->set_initial_value(move(initial_value)); return var; @@ -720,9 +719,10 @@ bool Parser::match_function_declaration() VERIFY(m_root_node); (void)parse_type(get_dummy_node()); - if (!peek(Token::Type::Identifier).has_value()) + if (!match_name()) return false; - consume(); + + (void)parse_name(get_dummy_node()); if (!peek(Token::Type::LeftParen).has_value()) return false; @@ -750,7 +750,7 @@ Optional<NonnullRefPtrVector<Parameter>> Parser::parse_parameter_list(ASTNode& p NonnullRefPtrVector<Parameter> parameters; while (peek().type() != Token::Type::RightParen && !eof()) { if (match_ellipsis()) { - auto param = create_ast_node<Parameter>(parent, position(), {}, StringView {}); + auto param = create_ast_node<Parameter>(parent, position(), {}, RefPtr<Name> {}); consume(Token::Type::Dot); consume(Token::Type::Dot); auto last_dot = consume(Token::Type::Dot); @@ -760,15 +760,12 @@ Optional<NonnullRefPtrVector<Parameter>> Parser::parse_parameter_list(ASTNode& p } else { auto type = parse_type(parent); - auto name_identifier = peek(Token::Type::Identifier); - if (name_identifier.has_value()) - consume(Token::Type::Identifier); - - StringView name; - if (name_identifier.has_value()) - name = text_of_token(name_identifier.value()); + RefPtr<Name> name; + if (match_name()) { + name = parse_name(parent); + } - auto param = create_ast_node<Parameter>(parent, type->start(), name_identifier.has_value() ? name_identifier.value().end() : type->end(), name); + auto param = create_ast_node<Parameter>(parent, type->start(), !name.is_null() ? name->end() : type->end(), name); type->set_parent(*param.ptr()); param->set_type(move(type)); @@ -1087,8 +1084,8 @@ NonnullRefPtr<EnumDeclaration> Parser::parse_enum_declaration(ASTNode& parent) enum_decl->set_type(EnumDeclaration::Type::RegularEnum); } - auto name_token = consume(Token::Type::Identifier); - enum_decl->set_name(text_of_token(name_token)); + auto name = parse_name(*enum_decl); + enum_decl->set_name(name); consume(Token::Type::LeftCurly); while (!eof() && peek().type() != Token::Type::RightCurly) { auto name = text_of_token(consume(Token::Type::Identifier)); @@ -1149,8 +1146,8 @@ NonnullRefPtr<StructOrClassDeclaration> Parser::parse_class_declaration(ASTNode& auto decl = create_ast_node<StructOrClassDeclaration>(parent, position(), {}, type); - auto name_token = consume(Token::Type::Identifier); - decl->set_name(text_of_token(name_token)); + auto name = parse_name(*decl); + decl->set_name(name); auto has_final = match_keyword("final"); @@ -1394,8 +1391,8 @@ NonnullRefPtr<NamespaceDeclaration> Parser::parse_namespace_declaration(ASTNode& if (!is_nested_namespace) consume(Token::Type::Keyword); - auto name_token = consume(Token::Type::Identifier); - namespace_decl->set_name(name_token.text()); + auto name = parse_name(*namespace_decl); + namespace_decl->set_name(name); if (peek().type() == Token::Type::ColonColon) { consume(Token::Type::ColonColon); @@ -1565,7 +1562,7 @@ NonnullRefPtr<BracedInitList> Parser::parse_braced_init_list(ASTNode& parent) } NonnullRefPtrVector<Declaration> Parser::parse_class_members(StructOrClassDeclaration& parent) { - auto class_name = parent.name(); + auto class_name = parent.full_name(); NonnullRefPtrVector<Declaration> members; while (!eof() && peek().type() != Token::Type::RightCurly) { @@ -1652,11 +1649,8 @@ void Parser::parse_constructor_or_destructor_impl(FunctionDeclaration& func, Cto consume(Token::Type::Tilde); } - auto name_token = consume(); - if (name_token.type() != Token::Type::Identifier && name_token.type() != Token::Type::KnownType) { - error("Unexpected constructor name"); - } - func.set_name(name_token.text()); + auto name = parse_name(func); + func.set_name(name); consume(Token::Type::LeftParen); auto parameters = parse_parameter_list(func); |