mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 06:14:58 +00:00
LibCpp: Support for parsing c-style fixed arrays (arr[2])
Also adds tests for finding declaration of arrays inside CppComprehension which requires proper parsing for passing. Side-effect of this patch: if we ctrl+click on array variables, it should jump to the correct declaration inside HackStudio.
This commit is contained in:
parent
34b04271f4
commit
ac435f914c
7 changed files with 184 additions and 8 deletions
|
@ -33,6 +33,12 @@ static bool s_some_test_failed = false;
|
|||
return; \
|
||||
} while (0)
|
||||
|
||||
#define RUN(function) \
|
||||
function; \
|
||||
if (s_some_test_failed) { \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
constexpr auto TESTS_ROOT_DIR = "/home/anon/Tests/cpp-tests/comprehension"sv;
|
||||
|
||||
class FileDB : public CodeComprehension::FileDB {
|
||||
|
@ -61,18 +67,24 @@ static void test_complete_local_args();
|
|||
static void test_complete_local_vars();
|
||||
static void test_complete_type();
|
||||
static void test_find_variable_definition();
|
||||
static void test_find_array_variable_declaration_single();
|
||||
static void test_find_array_variable_declaration_single_empty();
|
||||
static void test_find_array_variable_declaration_double();
|
||||
static void test_complete_includes();
|
||||
static void test_parameters_hint();
|
||||
|
||||
int run_tests()
|
||||
{
|
||||
test_complete_local_args();
|
||||
test_complete_local_vars();
|
||||
test_complete_type();
|
||||
test_find_variable_definition();
|
||||
test_complete_includes();
|
||||
test_parameters_hint();
|
||||
return s_some_test_failed ? 1 : 0;
|
||||
RUN(test_complete_local_args());
|
||||
RUN(test_complete_local_vars());
|
||||
RUN(test_complete_type());
|
||||
RUN(test_find_variable_definition());
|
||||
RUN(test_find_array_variable_declaration_single());
|
||||
RUN(test_find_array_variable_declaration_single_empty());
|
||||
RUN(test_find_array_variable_declaration_double());
|
||||
RUN(test_complete_includes());
|
||||
RUN(test_parameters_hint());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void add_file(FileDB& filedb, DeprecatedString const& name)
|
||||
|
@ -145,6 +157,60 @@ void test_find_variable_definition()
|
|||
FAIL("wrong declaration location");
|
||||
}
|
||||
|
||||
void test_find_array_variable_declaration_single()
|
||||
{
|
||||
I_TEST(Find 1D Array as a Variable Declaration)
|
||||
FileDB filedb;
|
||||
auto filename = "find_array_variable_declaration.cpp";
|
||||
add_file(filedb, filename);
|
||||
CodeComprehension::Cpp::CppComprehensionEngine engine(filedb);
|
||||
auto position = engine.find_declaration_of(filename, { 3, 6 });
|
||||
if (!position.has_value())
|
||||
FAIL("declaration not found");
|
||||
|
||||
if (position.value().file == filename && position.value().line == 2 && position.value().column >= 4)
|
||||
PASS;
|
||||
|
||||
printf("Found at position %zu %zu\n", position.value().line, position.value().column);
|
||||
FAIL("wrong declaration location");
|
||||
}
|
||||
|
||||
void test_find_array_variable_declaration_single_empty()
|
||||
{
|
||||
I_TEST(Find 1D Empty size Array as a Variable Declaration)
|
||||
FileDB filedb;
|
||||
auto filename = "find_array_variable_declaration.cpp";
|
||||
add_file(filedb, filename);
|
||||
CodeComprehension::Cpp::CppComprehensionEngine engine(filedb);
|
||||
auto position = engine.find_declaration_of(filename, { 6, 6 });
|
||||
if (!position.has_value())
|
||||
FAIL("declaration not found");
|
||||
|
||||
if (position.value().file == filename && position.value().line == 5 && position.value().column >= 4)
|
||||
PASS;
|
||||
|
||||
printf("Found at position %zu %zu\n", position.value().line, position.value().column);
|
||||
FAIL("wrong declaration location");
|
||||
}
|
||||
|
||||
void test_find_array_variable_declaration_double()
|
||||
{
|
||||
I_TEST(Find 2D Array as a Variable Declaration)
|
||||
FileDB filedb;
|
||||
auto filename = "find_array_variable_declaration.cpp";
|
||||
add_file(filedb, filename);
|
||||
CodeComprehension::Cpp::CppComprehensionEngine engine(filedb);
|
||||
auto position = engine.find_declaration_of(filename, { 9, 6 });
|
||||
if (!position.has_value())
|
||||
FAIL("declaration not found");
|
||||
|
||||
if (position.value().file == filename && position.value().line == 8 && position.value().column >= 4)
|
||||
PASS;
|
||||
|
||||
printf("Found at position %zu %zu\n", position.value().line, position.value().column);
|
||||
FAIL("wrong declaration location");
|
||||
}
|
||||
|
||||
void test_complete_includes()
|
||||
{
|
||||
I_TEST(Complete include statements)
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
void foo()
|
||||
{
|
||||
int arr[2] = {1,2};
|
||||
arr[1] = 0;
|
||||
|
||||
int arr2[] = {5,6};
|
||||
arr2[0] = 11;
|
||||
|
||||
int arr3[1][2] = {{3,4}};
|
||||
arr3[0][0] = 72;
|
||||
}
|
|
@ -572,6 +572,24 @@ StringView TemplatizedName::full_name() const
|
|||
return *m_full_name;
|
||||
}
|
||||
|
||||
void SizedName::dump(FILE* output, size_t indent) const
|
||||
{
|
||||
Name::dump(output, indent);
|
||||
print_indent(output, indent + 1);
|
||||
|
||||
StringBuilder dimension_info;
|
||||
for (auto const& dim : m_dimensions) {
|
||||
dimension_info.append('[');
|
||||
dimension_info.append(dim);
|
||||
dimension_info.append(']');
|
||||
}
|
||||
|
||||
if (dimension_info.is_empty()) {
|
||||
dimension_info.append("[]"sv);
|
||||
}
|
||||
outln(output, "{}", dimension_info.to_deprecated_string());
|
||||
}
|
||||
|
||||
void CppCastExpression::dump(FILE* output, size_t indent) const
|
||||
{
|
||||
ASTNode::dump(output, indent);
|
||||
|
|
|
@ -434,6 +434,7 @@ public:
|
|||
virtual void dump(FILE* = stdout, size_t indent = 0) const override;
|
||||
virtual bool is_name() const override { return true; }
|
||||
virtual bool is_templatized() const { return false; }
|
||||
virtual bool is_sized() const { return false; }
|
||||
|
||||
Name(ASTNode const* parent, Optional<Position> start, Optional<Position> end, DeprecatedString const& filename)
|
||||
: Expression(parent, start, end, filename)
|
||||
|
@ -453,6 +454,25 @@ private:
|
|||
mutable Optional<DeprecatedString> m_full_name;
|
||||
};
|
||||
|
||||
class SizedName : public Name {
|
||||
public:
|
||||
virtual ~SizedName() override = default;
|
||||
virtual StringView class_name() const override { return "SizedName"sv; }
|
||||
virtual bool is_sized() const override { return true; }
|
||||
void dump(FILE* output, size_t indent) const override;
|
||||
|
||||
SizedName(ASTNode const* parent, Optional<Position> start, Optional<Position> end, DeprecatedString const& filename)
|
||||
: Name(parent, start, end, filename)
|
||||
{
|
||||
}
|
||||
|
||||
void append_dimension(StringView dim) { m_dimensions.append(dim); };
|
||||
|
||||
private:
|
||||
Vector<StringView> m_dimensions;
|
||||
mutable Optional<DeprecatedString> m_full_name;
|
||||
};
|
||||
|
||||
class TemplatizedName : public Name {
|
||||
public:
|
||||
virtual ~TemplatizedName() override = default;
|
||||
|
@ -1020,5 +1040,6 @@ template<>
|
|||
inline bool ASTNode::fast_is<NamedType>() const { return is_type() && verify_cast<Type>(*this).is_named_type(); }
|
||||
template<>
|
||||
inline bool ASTNode::fast_is<TemplatizedName>() const { return is_name() && verify_cast<Name>(*this).is_templatized(); }
|
||||
|
||||
template<>
|
||||
inline bool ASTNode::fast_is<SizedName>() const { return is_name() && verify_cast<Name>(*this).is_sized(); }
|
||||
}
|
||||
|
|
|
@ -294,6 +294,19 @@ bool Parser::match_variable_declaration()
|
|||
|
||||
(void)parse_name(get_dummy_node());
|
||||
|
||||
while (!eof() && (peek().type() == Token::Type::LeftBracket)) {
|
||||
consume(Token::Type::LeftBracket);
|
||||
|
||||
if (match(Token::Type::Integer)) {
|
||||
consume(Token::Type::Integer);
|
||||
}
|
||||
if (!match(Token::Type::RightBracket)) {
|
||||
error("No closing right bracket"sv);
|
||||
return false;
|
||||
}
|
||||
consume(Token::Type::RightBracket);
|
||||
}
|
||||
|
||||
if (match(Token::Type::Equals)) {
|
||||
consume(Token::Type::Equals);
|
||||
if (!match_expression()) {
|
||||
|
@ -1449,7 +1462,9 @@ NonnullRefPtr<Name const> Parser::parse_name(ASTNode const& parent)
|
|||
return name_node;
|
||||
}
|
||||
|
||||
bool is_templatized = false;
|
||||
if (match_template_arguments()) {
|
||||
is_templatized = true;
|
||||
consume(Token::Type::Less);
|
||||
NonnullRefPtr<TemplatizedName> templatized_name = create_ast_node<TemplatizedName>(parent, name_node->start(), {});
|
||||
templatized_name->set_name(name_node->name());
|
||||
|
@ -1464,6 +1479,27 @@ NonnullRefPtr<Name const> Parser::parse_name(ASTNode const& parent)
|
|||
consume(Token::Type::Greater);
|
||||
}
|
||||
|
||||
if (!is_templatized && (peek().type() == Token::Type::LeftBracket)) {
|
||||
NonnullRefPtr<SizedName> sized_name = create_ast_node<SizedName>(parent, name_node->start(), {});
|
||||
sized_name->set_name(name_node->name());
|
||||
sized_name->set_scope(name_node->scope());
|
||||
|
||||
while (peek().type() == Token::Type::LeftBracket) {
|
||||
consume(Token::Type::LeftBracket);
|
||||
|
||||
StringView size = "0"sv;
|
||||
if (peek().type() == Token::Type::Integer) {
|
||||
auto token = consume(Token::Type::Integer);
|
||||
size = token.text();
|
||||
}
|
||||
sized_name->append_dimension(size);
|
||||
|
||||
consume(Token::Type::RightBracket);
|
||||
}
|
||||
name_node->set_end(position());
|
||||
name_node = sized_name;
|
||||
}
|
||||
|
||||
name_node->set_end(previous_token_end());
|
||||
return name_node;
|
||||
}
|
||||
|
@ -1564,6 +1600,8 @@ NonnullRefPtr<BracedInitList const> Parser::parse_braced_init_list(ASTNode const
|
|||
consume(Token::Type::LeftCurly);
|
||||
while (!eof() && peek().type() != Token::Type::RightCurly) {
|
||||
init_list->add_expression(parse_expression(*init_list));
|
||||
if (peek().type() == Token::Type::Comma)
|
||||
consume(Token::Type::Comma);
|
||||
}
|
||||
consume(Token::Type::RightCurly);
|
||||
init_list->set_end(position());
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
TranslationUnit[0:0->2:0]
|
||||
FunctionDeclaration[0:0->2:0]
|
||||
NamedType[0:0->0:3]
|
||||
void
|
||||
foo
|
||||
(
|
||||
)
|
||||
FunctionDefinition[0:11->2:0]
|
||||
{
|
||||
VariableDeclaration[1:4->1:20]
|
||||
NamedType[1:4->1:6]
|
||||
int
|
||||
x
|
||||
BracedInitList[1:15->1:20]
|
||||
NumericLiteral[1:16->1:16]
|
||||
1
|
||||
NumericLiteral[1:18->1:18]
|
||||
2
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
void foo() {
|
||||
int x[0] = {1,2};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue