/
thomas-king
/
CodeGenerator
Обзор
Документация
Войти
/
thomas-king
/
CodeGenerator
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
test/ClassDeclarationTests/ClassDeclarationTests.cpp
389 строк
16 KB
Ace Rodstin
Task #50. Add support for class initializer call.
26 окт 2023, 17:11
26 окт 2023, 17:11
bdde0fa
Код
Авторство
О чём код?
// // ClassDeclarationTests.cpp // CodeGenerator // // Created by Ace Rodstin on 10/23/23. // Updated by Ace Rodstin on 10/26/23. // // Copyright © 2023 Ace Rodstin. All rights reserved. // #include "Support.h" TEST(ClassDeclarationTests, classDeclaration) { // Given string expected = "class TestClass {\n" "\n" "};"; // When Symbol classSymbol { Type::Meta::CLASS, "TestClass" }; auto classDeclaration = Node::make<ClassDeclaration>(classSymbol); auto classDeclarationNode = Node::cast<Node>(classDeclaration); auto [module, moduleSourceFile] = createModule(); moduleSourceFile->append(classDeclarationNode, SourceFile::Section::CLASSES); auto [package, packageSourceFile] = translate(module); auto result = packageSourceFile.sourceCode; // Then EXPECT_STREQ(result.c_str(), expected.c_str()); } TEST(ClassDeclarationTests, classDeclarationWithConstantDeclaration) { // Given string expected = "class TestClass {\n" " const long int value = 1;\n" "};"; // When Symbol constantSymbol { Type::Atomic::INTEGER_64, "value" }; Object constantObject { Object::Type::VALUE, constantSymbol }; Literal constantLiteral { Type::Atomic::INTEGER_64, 1L }; RightValue value { RightValue::Kind::LITERAL, constantLiteral }; auto constantDeclaration = Node::make<ConstantDeclaration>(constantObject, value); auto constantDeclarationNode = Node::cast<Node>(constantDeclaration); Symbol classSymbol { Type::Meta::CLASS, "TestClass" }; auto classDeclaration = Node::make<ClassDeclaration>(classSymbol); classDeclaration->append(constantDeclarationNode, ClassDeclaration::Section::PROPERTIES); auto classDeclarationNode = Node::cast<Node>(classDeclaration); auto [module, moduleSourceFile] = createModule(); moduleSourceFile->append(classDeclarationNode, SourceFile::Section::CLASSES); auto [package, packageSourceFile] = translate(module); auto result = packageSourceFile.sourceCode; // Then EXPECT_STREQ(result.c_str(), expected.c_str()); } TEST(ClassDeclarationTests, classDeclarationWithMethodDeclaration) { // Given string expected = "class TestClass {\n" " long int testMethod(long int arg1) {\n" " return arg1;\n" " }\n" "};"; // When Symbol parameterSymbol { Type::Atomic::INTEGER_64, "arg1" }; Object parameterObject { Object::Type::VALUE, parameterSymbol }; auto parameterDeclaration = Node::make<ParameterDeclaration>(parameterObject); auto parameterDeclarationNode = Node::cast<Node>(parameterDeclaration); Symbol returnSymbol { Type::Atomic::INTEGER_64, "arg1" }; auto returnStatement = Node::make<ReturnStatement>(returnSymbol); auto returnStatementNode = Node::cast<Node>(returnStatement); Symbol functionSymbol { Type::Atomic::INTEGER_64, "testMethod" }; auto functionDeclaration = Node::make<FunctionDeclaration>(functionSymbol); functionDeclaration->append(parameterDeclarationNode, FunctionDeclaration::Section::PARAMETERS); functionDeclaration->append(returnStatementNode, FunctionDeclaration::Section::BODY); auto functionDeclarationNode = Node::cast<Node>(functionDeclaration); Symbol classSymbol { Type::Meta::CLASS, "TestClass" }; auto classDeclaration = Node::make<ClassDeclaration>(classSymbol); classDeclaration->append(functionDeclarationNode, ClassDeclaration::Section::METHODS); auto classDeclarationNode = Node::cast<Node>(classDeclaration); auto [module, moduleSourceFile] = createModule(); moduleSourceFile->append(classDeclarationNode, SourceFile::Section::CLASSES); auto [package, packageSourceFile] = translate(module); auto result = packageSourceFile.sourceCode; // Then EXPECT_STREQ(result.c_str(), expected.c_str()); } TEST(ClassDeclarationTests, classDeclarationWithInitializerDeclaration) { // Given string expected = "class TestClass {\n" " TestClass() {\n" "\n" " }\n" "};"; // When Symbol initializerSymbol { Type::Atomic::VOID, "TestClass" }; auto initializerDeclaration = Node::make<InitializerDeclaration>(initializerSymbol); auto initializerDeclarationNode = Node::cast<Node>(initializerDeclaration); Symbol classSymbol { Type::Meta::CLASS, "TestClass" }; auto classDeclaration = Node::make<ClassDeclaration>(classSymbol); classDeclaration->append(initializerDeclarationNode, ClassDeclaration::Section::METHODS); auto classDeclarationNode = Node::cast<Node>(classDeclaration); auto [module, moduleSourceFile] = createModule(); moduleSourceFile->append(classDeclarationNode, SourceFile::Section::CLASSES); auto [package, packageSourceFile] = translate(module); auto result = packageSourceFile.sourceCode; // Then EXPECT_STREQ(result.c_str(), expected.c_str()); } TEST(ClassDeclarationTests, classDeclarationWithInitializerDeclarationWith) { // Given string expected = "class TestClass {\n" " int value;\n" "\n" " TestClass(int value) {\n" " this->value = value;\n" " }\n" "};"; // When Symbol variableSymbol { Type::Atomic::INTEGER_32, "value" }; Object variableObject { Object::Type::VALUE, variableSymbol }; auto variableDeclaration = Node::make<VariableDeclaration>(variableObject); auto variableDeclarationNode = Node::cast<Node>(variableDeclaration); Symbol argumentSymbol { Type::Atomic::INTEGER_32, "value" }; Object argumentObject { Object::Type::VALUE, argumentSymbol }; auto parameterDeclaration = Node::make<ParameterDeclaration>(argumentObject); auto parameterDeclarationNode = Node::cast<Node>(parameterDeclaration); Symbol thisSymbol { Type::Atomic::VOID, "this" }; Object thisObject { Object::Type::REFERENCE, thisSymbol }; LeftValue leftValue1 { thisObject }; LeftValue leftValue2 { variableObject }; leftValue1.chain(leftValue2); RightValue rightValue { RightValue::Kind::OBJECT, argumentObject }; auto assignmentStatement = Node::make<AssignmentStatement>(leftValue1, rightValue); auto assignmentStatementNode = Node::cast<Node>(assignmentStatement); Symbol initializerSymbol { Type::Atomic::VOID, "TestClass" }; auto initializerDeclaration = Node::make<InitializerDeclaration>(initializerSymbol); initializerDeclaration->append(parameterDeclarationNode, InitializerDeclaration::Section::PARAMETERS); initializerDeclaration->append(assignmentStatementNode, InitializerDeclaration::Section::BODY); auto initializerDeclarationNode = Node::cast<Node>(initializerDeclaration); Symbol classSymbol { Type::Meta::CLASS, "TestClass" }; auto classDeclaration = Node::make<ClassDeclaration>(classSymbol); classDeclaration->append(variableDeclarationNode, ClassDeclaration::Section::PROPERTIES); classDeclaration->append(initializerDeclarationNode, ClassDeclaration::Section::METHODS); auto classDeclarationNode = Node::cast<Node>(classDeclaration); auto [module, moduleSourceFile] = createModule(); moduleSourceFile->append(classDeclarationNode, SourceFile::Section::CLASSES); auto [package, packageSourceFile] = translate(module); auto result = packageSourceFile.sourceCode; // Then EXPECT_STREQ(result.c_str(), expected.c_str()); } TEST(ClassDeclarationTests, classDeclarationWithVariableDeclarationWithMethodDeclaration) { // Given string expected = "class TestClass {\n" " long int value = 1;\n" "\n" " long int testMethod(long int arg1) {\n" " return arg1;\n" " }\n" "};"; // When Symbol variableSymbol { Type::Atomic::INTEGER_64, "value" }; Object variableObject { Object::Type::VALUE, variableSymbol }; Literal variableLiteral { Type::Atomic::INTEGER_64, 1L }; RightValue variableValue { RightValue::Kind::LITERAL, variableLiteral }; auto variableDeclaration = Node::make<VariableDeclaration>(variableObject, variableValue); auto variableDeclarationNode = Node::cast<Node>(variableDeclaration); Symbol parameterSymbol { Type::Atomic::INTEGER_64, "arg1" }; Object parameterObject { Object::Type::VALUE, parameterSymbol }; auto parameterDeclaration = Node::make<ParameterDeclaration>(parameterObject); auto parameterDeclarationNode = Node::cast<Node>(parameterDeclaration); Symbol returnSymbol { Type::Atomic::INTEGER_64, "arg1" }; auto returnStatement = Node::make<ReturnStatement>(returnSymbol); auto returnStatementNode = Node::cast<Node>(returnStatement); Symbol functionSymbol { Type::Atomic::INTEGER_64, "testMethod" }; auto functionDeclaration = Node::make<FunctionDeclaration>(functionSymbol); functionDeclaration->append(parameterDeclarationNode, FunctionDeclaration::Section::PARAMETERS); functionDeclaration->append(returnStatementNode, FunctionDeclaration::Section::BODY); auto functionDeclarationNode = Node::cast<Node>(functionDeclaration); Symbol classSymbol { Type::Meta::CLASS, "TestClass" }; auto classDeclaration = Node::make<ClassDeclaration>(classSymbol); classDeclaration->append(variableDeclarationNode, ClassDeclaration::Section::PROPERTIES); classDeclaration->append(functionDeclarationNode, ClassDeclaration::Section::METHODS); auto classDeclarationNode = Node::cast<Node>(classDeclaration); auto [module, moduleSourceFile] = createModule(); moduleSourceFile->append(classDeclarationNode, SourceFile::Section::CLASSES); auto [package, packageSourceFile] = translate(module); auto result = packageSourceFile.sourceCode; // Then EXPECT_STREQ(result.c_str(), expected.c_str()); } TEST(ClassDeclarationTests, classDeclarationWithVariableDeclarationsWithMethodsDeclaration) { // Given string expected = "class TestClass {\n" " long int value1 = 1;\n" " long int value2 = 2;\n" "\n" " void testFunction1() {\n" "\n" " }\n" "\n" " void testFunction2() {\n" "\n" " }\n" "};"; // When Symbol variableSymbol1 { Type::Atomic::INTEGER_64, "value1" }; Object variableObject1 { Object::Type::VALUE, variableSymbol1 }; Literal variableLiteral1 { Type::Atomic::INTEGER_64, 1L }; RightValue variableValue1 { RightValue::Kind::LITERAL, variableLiteral1 }; auto variableDeclaration1 = Node::make<VariableDeclaration>(variableObject1, variableValue1); auto variableDeclarationNode1 = Node::cast<Node>(variableDeclaration1); Symbol variableSymbol2 { Type::Atomic::INTEGER_64, "value2" }; Object variableObject2 { Object::Type::VALUE, variableSymbol2 }; Literal variableLiteral2 { Type::Atomic::INTEGER_64, 2L }; RightValue variableValue2 { RightValue::Kind::LITERAL, variableLiteral2 }; auto variableDeclaration2 = Node::make<VariableDeclaration>(variableObject2, variableValue2); auto variableDeclarationNode2 = Node::cast<Node>(variableDeclaration2); Symbol functionSymbol1 { Type::Atomic::VOID, "testFunction1" }; auto functionDeclaration1 = Node::make<FunctionDeclaration>(functionSymbol1); auto functionDeclarationNode1 = Node::cast<Node>(functionDeclaration1); Symbol functionSymbol2 { Type::Atomic::VOID, "testFunction2" }; auto functionDeclaration2 = Node::make<FunctionDeclaration>(functionSymbol2); auto functionDeclarationNode2 = Node::cast<Node>(functionDeclaration2); Symbol classSymbol { Type::Meta::CLASS, "TestClass" }; auto classDeclaration = Node::make<ClassDeclaration>(classSymbol); classDeclaration->append(variableDeclarationNode1, ClassDeclaration::Section::PROPERTIES); classDeclaration->append(variableDeclarationNode2, ClassDeclaration::Section::PROPERTIES); classDeclaration->append(functionDeclarationNode1, ClassDeclaration::Section::METHODS); classDeclaration->append(functionDeclarationNode2, ClassDeclaration::Section::METHODS); auto classDeclarationNode = Node::cast<Node>(classDeclaration); auto [module, moduleSourceFile] = createModule(); moduleSourceFile->append(classDeclarationNode, SourceFile::Section::CLASSES); auto [package, packageSourceFile] = translate(module); auto result = packageSourceFile.sourceCode; // Then EXPECT_STREQ(result.c_str(), expected.c_str()); } TEST(ClassDeclarationTests, chainedCall) { // Given string expected = "one.two->three.four()->five(1);"; // When Symbol propertySymbol1 { Type { "TestObject" }, "one" }; Object propertyObject1 { Object::Type::VALUE, propertySymbol1 }; Symbol propertySymbol2 { Type { "TestObject" }, "two" }; Object propertyObject2 { Object::Type::REFERENCE, propertySymbol2 }; Symbol propertySymbol3 { Type { "TestObject" }, "three" }; Object propertyObject3 { Object::Type::VALUE, propertySymbol3 }; Symbol functionSymbol1 { Type { "TestObject" }, "four" }; Object functionObject1 { Object::Type::REFERENCE, functionSymbol1 }; Symbol functionSymbol2 { Type::Atomic::VOID, "five" }; Object functionObject2 { Object::Type::REFERENCE, functionSymbol2 }; Literal literal { Type::Atomic::INTEGER_64, 1L }; RightValue argument { RightValue::Kind::LITERAL, literal }; auto functionCallExpression2 = Node::make<FunctionCallExpression>(functionObject2); functionCallExpression2->append(argument); auto functionCallExpression1 = Node::make<FunctionCallExpression>(functionObject1); functionCallExpression1->chain(functionCallExpression2); auto propertyCallExpression3 = Node::make<PropertyCallExpression>(propertyObject3); propertyCallExpression3->chain(functionCallExpression1); auto propertyCallExpression2 = Node::make<PropertyCallExpression>(propertyObject2); propertyCallExpression2->chain(propertyCallExpression3); auto propertyCallExpression1 = Node::make<PropertyCallExpression>(propertyObject1); propertyCallExpression1->chain(propertyCallExpression2); auto propertyCallExpressionNode = Node::cast<Node>(propertyCallExpression1); auto [module, moduleSourceFile] = createModule(); moduleSourceFile->append(propertyCallExpressionNode, SourceFile::Section::CLASSES); auto [package, packageSourceFile] = translate(module); auto result = packageSourceFile.sourceCode; // Then EXPECT_STREQ(result.c_str(), expected.c_str()); } TEST(ClassDeclarationTests, classInitializerCall) { // Given string expected = "TestClass();"; // When Symbol functionSymbol { Type::Atomic::VOID, "TestClass" }; Object functionObject { Object::Type::REFERENCE, functionSymbol }; auto functionCallExpression = Node::make<FunctionCallExpression>(functionObject); auto functionCallExpressionNode = Node::cast<Node>(functionCallExpression); auto [module, moduleSourceFile] = createModule(); moduleSourceFile->append(functionCallExpressionNode, SourceFile::Section::FUNCTIONS); auto [package, packageSourceFile] = translate(module); auto result = packageSourceFile.sourceCode; // Then EXPECT_STREQ(result.c_str(), expected.c_str()); } TEST(ClassDeclarationTests, classInitializerCallWithArgument) { // Given string expected = "TestClass(1);"; // When Literal literal { Type::Atomic::INTEGER_64, 1L }; RightValue argument { RightValue::Kind::LITERAL, literal }; Symbol functionSymbol { Type::Atomic::VOID, "TestClass" }; Object functionObject { Object::Type::REFERENCE, functionSymbol }; auto functionCallExpression = Node::make<FunctionCallExpression>(functionObject); functionCallExpression->append(argument); auto functionCallExpressionNode = Node::cast<Node>(functionCallExpression); auto [module, moduleSourceFile] = createModule(); moduleSourceFile->append(functionCallExpressionNode, SourceFile::Section::FUNCTIONS); auto [package, packageSourceFile] = translate(module); auto result = packageSourceFile.sourceCode; // Then EXPECT_STREQ(result.c_str(), expected.c_str()); }