1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-06-01 09:58:14 +00:00

LanguageServers/Cpp: Refactor logic of find declaration

This commit is contained in:
Itamar 2021-04-03 14:40:13 +03:00 committed by Andreas Kling
parent e16036b9cc
commit 510b5073de
2 changed files with 59 additions and 12 deletions

View file

@ -386,30 +386,76 @@ Optional<GUI::AutocompleteProvider::ProjectLocation> ParserAutoComplete::find_pr
return {};
}
struct TargetDeclaration {
enum Type {
Variable,
Type,
Function,
Property
} type;
String name;
};
static Optional<TargetDeclaration> get_target_declaration(const ASTNode& node)
{
dbgln("get_target_declaration");
if (!node.is_identifier()) {
dbgln_if(CPP_LANGUAGE_SERVER_DEBUG, "node is not an identifier");
return {};
}
const ASTNode* n = &node;
while (n) {
dbgln("{}", n->class_name());
n = n->parent();
}
String name = static_cast<const Identifier&>(node).m_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 };
if ((node.parent() && node.parent()->is_type()) || (node.parent()->is_name() && node.parent()->parent() && node.parent()->parent()->is_type()))
return TargetDeclaration { TargetDeclaration::Type::Type, name };
if ((node.parent() && node.parent()->is_member_expression()))
return TargetDeclaration { TargetDeclaration::Type::Property, name };
return TargetDeclaration { TargetDeclaration::Type::Variable, name };
}
RefPtr<Declaration> ParserAutoComplete::find_declaration_of(const DocumentData& document_data, const ASTNode& node) const
{
dbgln_if(CPP_LANGUAGE_SERVER_DEBUG, "find_declaration_of: {}", document_data.parser().text_of_node(node));
dbgln_if(CPP_LANGUAGE_SERVER_DEBUG, "find_declaration_of: {} ({})", document_data.parser().text_of_node(node), node.class_name());
auto target_decl = get_target_declaration(node);
if (!target_decl.has_value())
return {};
auto declarations = get_available_declarations(document_data, node);
for (auto& decl : declarations) {
if (node.is_identifier() && decl.is_variable_or_parameter_declaration()) {
if (((Cpp::VariableOrParameterDeclaration&)decl).m_name == static_cast<const Identifier&>(node).m_name)
if (decl.is_function() && target_decl.value().type == TargetDeclaration::Function) {
if (((Cpp::FunctionDeclaration&)decl).m_name == target_decl.value().name)
return decl;
}
if (node.is_type() && decl.is_struct_or_class()) {
if (((Cpp::StructOrClassDeclaration&)decl).m_name == static_cast<const Type&>(node).m_name->full_name())
if (decl.is_variable_or_parameter_declaration() && target_decl.value().type == TargetDeclaration::Variable) {
if (((Cpp::VariableOrParameterDeclaration&)decl).m_name == target_decl.value().name)
return decl;
}
if (node.is_function_call() && decl.is_function()) {
if (((Cpp::FunctionDeclaration&)decl).m_name == static_cast<const FunctionCall&>(node).m_name->full_name())
return decl;
}
if (is_property(node) && decl.is_struct_or_class()) {
if (decl.is_struct_or_class() && target_decl.value().type == TargetDeclaration::Property) {
// TODO: Also check that the type of the struct/class matches (not just the property name)
for (auto& member : ((Cpp::StructOrClassDeclaration&)decl).m_members) {
VERIFY(node.is_identifier());
if (member.m_name == ((const Identifier&)node).m_name)
if (member.m_name == target_decl.value().name) {
return member;
}
}
}
if (decl.is_struct_or_class() && target_decl.value().type == TargetDeclaration::Type) {
if (((Cpp::StructOrClassDeclaration&)decl).m_name == target_decl.value().name)
return decl;
}
}
return {};
}