From e26cbe8b3284e1edf11330dcabad1177c67c2abd Mon Sep 17 00:00:00 2001 From: Bill Date: Mon, 16 Feb 2026 08:19:57 -0700 Subject: [PATCH] Step 341: Phase 12d Integration + Sprint 12 Summary (8/8 tests) Co-Authored-By: Claude Opus 4.6 --- editor/CMakeLists.txt | 9 + editor/tests/step341_test.cpp | 369 ++++++++++++++++++++++++++++++++++ 2 files changed, 378 insertions(+) create mode 100644 editor/tests/step341_test.cpp diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 24e137e..0f9370a 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -2053,4 +2053,13 @@ target_link_libraries(step340_test PRIVATE tree_sitter_javascript tree_sitter_typescript tree_sitter_java tree_sitter_rust tree_sitter_go) +add_executable(step341_test tests/step341_test.cpp) +target_include_directories(step341_test PRIVATE src) +target_link_libraries(step341_test PRIVATE + nlohmann_json::nlohmann_json + unofficial::tree-sitter::tree-sitter + tree_sitter_python tree_sitter_cpp tree_sitter_elisp + tree_sitter_javascript tree_sitter_typescript + tree_sitter_java tree_sitter_rust tree_sitter_go) + # Step 12: Dear ImGui shell scaffolding created (main.cpp exists but not built due to dependencies) diff --git a/editor/tests/step341_test.cpp b/editor/tests/step341_test.cpp new file mode 100644 index 0000000..6d0caa7 --- /dev/null +++ b/editor/tests/step341_test.cpp @@ -0,0 +1,369 @@ +// Step 341: Phase 12d Integration + Sprint 12 Summary (8 tests) +// Full C++ depth validation: parse → AST → generate roundtrips, cross-language, +// combined workflow + C++ constructs, sprint 12 totals verification + +#include +#include +#include +#include +#include "ast/PreprocessorNodes.h" +#include "ast/EnumNamespaceNodes.h" +#include "ast/ClassDeclaration.h" +#include "ast/GenericType.h" +#include "ast/AsyncNodes.h" +#include "ast/Serialization.h" +#include "ast/Parser.h" +#include "ast/PythonGenerator.h" +#include "ast/CppGenerator.h" +#include "ast/JavaGenerator.h" +#include "ast/RustGenerator.h" +#include "ast/GoGenerator.h" +#include "ast/JavaScriptGenerator.h" +#include "ast/ElispGenerator.h" +#include "ast/KotlinGenerator.h" +#include "ast/CSharpGenerator.h" +#include "CompactAST.h" + +int main() { + int passed = 0; + + // Test 1: Parse realistic C++ header: includes + pragma + namespace + enum + class + function + { + std::string src = R"( +#pragma once +#include +#include "ast/ASTNode.h" + +namespace whetstone { + +enum class NodeKind : int { + Function = 0, + Variable = 1, + Class = 2 +}; + +class ASTVisitor { +public: + virtual void visit() {} +}; + +void helper(int x) { return; } + +} +)"; + auto mod = TreeSitterParser::parseCpp(src); + auto stmts = mod->getChildren("statements"); + + // Collect all concept types present + std::set types; + for (auto* s : stmts) types.insert(s->conceptType); + + assert(types.count("PragmaDirective") || types.count("IncludeDirective")); + assert(types.count("NamespaceDeclaration")); + + // Namespace should contain enum, class, function + bool foundNs = false; + for (auto* s : stmts) { + if (s->conceptType == "NamespaceDeclaration") { + foundNs = true; + auto body = s->getChildren("body"); + std::set bodyTypes; + for (auto* b : body) bodyTypes.insert(b->conceptType); + assert(bodyTypes.count("EnumDeclaration")); + assert(bodyTypes.count("ClassDeclaration")); + assert(bodyTypes.count("Function")); + } + } + assert(foundNs); + std::cout << "Test 1 PASSED: Parse realistic C++ header with all constructs\n"; + passed++; + } + + // Test 2: Round-trip: C++ header → AST → JSON → fromJson → generate → verify structure + { + std::string src = R"( +enum class Color : int { + Red = 0, + Green = 1 +}; +)"; + auto mod = TreeSitterParser::parseCpp(src); + auto stmts = mod->getChildren("statements"); + bool foundEnum = false; + for (auto* s : stmts) { + if (s->conceptType == "EnumDeclaration") { + foundEnum = true; + // JSON roundtrip + nlohmann::json j = propertiesToJson(s); + auto* restored = createNode(s->conceptType); + setPropertiesFromJson(restored, j); + // Verify properties survived + auto* orig = static_cast(s); + auto* rest = static_cast(restored); + assert(rest->name == orig->name); + assert(rest->isScoped == orig->isScoped); + delete restored; + } + } + assert(foundEnum); + std::cout << "Test 2 PASSED: Enum parse → JSON roundtrip → verify\n"; + passed++; + } + + // Test 3: Enum inside namespace: parse → verify scoping in AST + { + std::string src = R"( +namespace outer { + enum class Status { Active, Inactive }; +} +)"; + auto mod = TreeSitterParser::parseCpp(src); + auto stmts = mod->getChildren("statements"); + bool found = false; + for (auto* s : stmts) { + if (s->conceptType == "NamespaceDeclaration") { + auto* ns = static_cast(s); + assert(ns->name == "outer"); + auto body = ns->getChildren("body"); + bool hasEnum = false; + for (auto* b : body) { + if (b->conceptType == "EnumDeclaration") { + hasEnum = true; + auto* e = static_cast(b); + assert(e->name == "Status"); + assert(e->isScoped); + } + } + assert(hasEnum); + found = true; + } + } + assert(found); + std::cout << "Test 3 PASSED: Enum inside namespace scoping\n"; + passed++; + } + + // Test 4: Cross-language: C++ enum → Java enum + Python class(Enum) + Rust enum + { + EnumDeclaration e; e.name = "Color"; e.isScoped = true; + e.addChild("members", new EnumMember("m1", "Red", "0")); + e.addChild("members", new EnumMember("m2", "Green", "1")); + e.addChild("members", new EnumMember("m3", "Blue", "2")); + + CppGenerator cppGen; + std::string cppOut = cppGen.generate(&e); + assert(cppOut.find("enum class Color") != std::string::npos); + + JavaGenerator javaGen; + std::string javaOut = javaGen.generate(&e); + assert(javaOut.find("enum Color") != std::string::npos); + assert(javaOut.find("Red") != std::string::npos); + + PythonGenerator pyGen; + std::string pyOut = pyGen.generate(&e); + assert(pyOut.find("class Color(Enum)") != std::string::npos); + + RustGenerator rustGen; + std::string rustOut = rustGen.generate(&e); + assert(rustOut.find("enum Color") != std::string::npos); + + KotlinGenerator ktGen; + std::string ktOut = ktGen.generate(&e); + assert(ktOut.find("enum class Color") != std::string::npos); + + CSharpGenerator csGen; + std::string csOut = csGen.generate(&e); + assert(csOut.find("enum Color") != std::string::npos); + + std::cout << "Test 4 PASSED: C++ enum → 6 language outputs\n"; + passed++; + } + + // Test 5: Combined namespace + class + enum + function → full pipeline + { + NamespaceDeclaration ns; ns.name = "ast"; + + auto* cls = new ClassDeclaration(); cls->name = "Node"; cls->isAbstract = true; + auto* meth = new Function(); meth->name = "accept"; + cls->addChild("methods", meth); + ns.addChild("body", cls); + + auto* e = new EnumDeclaration(); e->name = "Kind"; e->isScoped = true; + e->addChild("members", new EnumMember("m1", "Expr")); + e->addChild("members", new EnumMember("m2", "Stmt")); + ns.addChild("body", e); + + auto* func = new Function(); func->name = "createNode"; + ns.addChild("body", func); + + CppGenerator gen; + std::string out = gen.generate(&ns); + assert(out.find("namespace ast") != std::string::npos); + assert(out.find("Node") != std::string::npos); + assert(out.find("accept") != std::string::npos); + assert(out.find("enum class Kind") != std::string::npos); + assert(out.find("Expr") != std::string::npos); + assert(out.find("createNode") != std::string::npos); + + std::cout << "Test 5 PASSED: Combined namespace + class + enum + function pipeline\n"; + passed++; + } + + // Test 6: All new AST nodes serialize/deserialize correctly (batch verification) + { + // IncludeDirective + IncludeDirective inc; inc.path = "vector"; inc.isSystem = true; + nlohmann::json j1 = propertiesToJson(&inc); + auto* r1 = createNode("IncludeDirective"); + setPropertiesFromJson(r1, j1); + assert(static_cast(r1)->path == "vector"); + assert(static_cast(r1)->isSystem); + + // PragmaDirective + PragmaDirective prag; prag.directive = "once"; + nlohmann::json j2 = propertiesToJson(&prag); + auto* r2 = createNode("PragmaDirective"); + setPropertiesFromJson(r2, j2); + assert(static_cast(r2)->directive == "once"); + + // MacroDefinition + MacroDefinition mac; mac.name = "MAX"; mac.isFunctionLike = true; + mac.parameters = {"a", "b"}; mac.body = "((a)>(b)?(a):(b))"; + nlohmann::json j3 = propertiesToJson(&mac); + auto* r3 = createNode("MacroDefinition"); + setPropertiesFromJson(r3, j3); + auto* rm = static_cast(r3); + assert(rm->name == "MAX"); + assert(rm->isFunctionLike); + assert(rm->parameters.size() == 2); + + // EnumDeclaration + EnumDeclaration ed; ed.name = "Color"; ed.isScoped = true; ed.underlyingType = "int"; + nlohmann::json j4 = propertiesToJson(&ed); + auto* r4 = createNode("EnumDeclaration"); + setPropertiesFromJson(r4, j4); + auto* re = static_cast(r4); + assert(re->name == "Color"); + assert(re->isScoped); + assert(re->underlyingType == "int"); + + // NamespaceDeclaration + NamespaceDeclaration nsd; nsd.name = "whetstone"; + nlohmann::json j5 = propertiesToJson(&nsd); + auto* r5 = createNode("NamespaceDeclaration"); + setPropertiesFromJson(r5, j5); + assert(static_cast(r5)->name == "whetstone"); + + // TypeAlias + TypeAlias ta; ta.aliasName = "Ptr"; ta.targetType = "int*"; ta.isUsing = true; + nlohmann::json j6 = propertiesToJson(&ta); + auto* r6 = createNode("TypeAlias"); + setPropertiesFromJson(r6, j6); + auto* rt = static_cast(r6); + assert(rt->aliasName == "Ptr"); + assert(rt->targetType == "int*"); + assert(rt->isUsing); + + delete r1; delete r2; delete r3; delete r4; delete r5; delete r6; + std::cout << "Test 6 PASSED: All 6 new AST nodes serialize/deserialize correctly\n"; + passed++; + } + + // Test 7: CompactAST names for all new node types + { + IncludeDirective inc; inc.path = "vector"; inc.isSystem = true; + PragmaDirective prag; prag.directive = "once"; + MacroDefinition mac; mac.name = "MAX"; + EnumDeclaration ed; ed.name = "Color"; + EnumMember em("m1", "Red", "0"); + NamespaceDeclaration nsd; nsd.name = "whetstone"; + TypeAlias ta; ta.aliasName = "Ptr"; + + assert(getNodeName(&inc) == "vector"); + assert(getNodeName(&prag) == "once"); + assert(getNodeName(&mac) == "MAX"); + assert(getNodeName(&ed) == "Color"); + assert(getNodeName(&em) == "Red"); + assert(getNodeName(&nsd) == "whetstone"); + assert(getNodeName(&ta) == "Ptr"); + + std::cout << "Test 7 PASSED: CompactAST names for all new node types\n"; + passed++; + } + + // Test 8: C++ self-hosting progress — parse simplified Whetstone header fragment + { + std::string src = R"( +#pragma once +#include +#include +#include "ASTNode.h" + +namespace whetstone { + +enum class NodeKind { + Module, + Function, + Variable +}; + +class ProjectionGenerator { +public: + virtual std::string generate() {} +}; + +class CppGenerator : public ProjectionGenerator { +public: + std::string generate() {} +}; + +} +)"; + auto mod = TreeSitterParser::parseCpp(src); + auto stmts = mod->getChildren("statements"); + + // Count constructs found + int includes = 0, pragmas = 0, namespaces = 0; + for (auto* s : stmts) { + if (s->conceptType == "IncludeDirective") includes++; + if (s->conceptType == "PragmaDirective") pragmas++; + if (s->conceptType == "NamespaceDeclaration") namespaces++; + } + assert(includes >= 2); // , , "ASTNode.h" + assert(pragmas >= 1); + assert(namespaces >= 1); + + // Inside namespace: enum + 2 classes + for (auto* s : stmts) { + if (s->conceptType == "NamespaceDeclaration") { + auto body = s->getChildren("body"); + int enums = 0, classes = 0; + for (auto* b : body) { + if (b->conceptType == "EnumDeclaration") enums++; + if (b->conceptType == "ClassDeclaration") classes++; + } + assert(enums >= 1); + assert(classes >= 2); + + // CppGenerator should inherit from ProjectionGenerator + for (auto* b : body) { + if (b->conceptType == "ClassDeclaration") { + auto* cls = static_cast(b); + if (cls->name == "CppGenerator") { + auto bases = cls->getBases(); + assert(!bases.empty()); + assert(bases[0].name == "ProjectionGenerator"); + } + } + } + } + } + + std::cout << "Test 8 PASSED: Self-hosting progress — Whetstone header fragment parsed\n"; + passed++; + } + + std::cout << "\nResults: " << passed << "/8\n"; + assert(passed == 8); + return 0; +}