// Step 1932: Sprint 280 Integration — Poly-API cross-language step + breakpoint round-trip // // Scenario: a Go+TypeScript polyglot service. // - HandleRequest is implemented in both Go and TypeScript. // - A breakpoint is set on the HandleRequest AST node in both languages. // - A polyglot stack trace shows the call crossing from TypeScript into Go. // - Step-into at the boundary switches the active adapter to Go. // - Removing the breakpoint clears both languages. // // t1: breakpoint fires in both languages after addToAll // t2: step-into at TypeScript→Go boundary switches router to Go // t3: step-over at boundary stays in TypeScript (caller side) // t4: removeFromAll clears both Go and TypeScript breakpoints // t5: Sprint280IntegrationSummary reports 5 steps completed #include "BreakpointSyncOrchestrator.h" #include "CrossLanguageStepIntoHandler.h" #include "CrossLanguageStepOverHandler.h" #include "DebugAdapterRouter.h" #include "PolyglotStackTraceDecoder.h" #include "Sprint280IntegrationSummary.h" #include namespace ws = whetstone; static int p=0,f=0; #define T(n) { std::cout<<" "<<#n<<"... "; } #define P() { std::cout<<"PASS\n"; ++p; } #define F(m) { std::cout<<"FAIL: "< makeStack() { ws::PolyglotStackTraceDecoder dec; return dec.decode({ {1, "apiHandler", "api.ts", 30}, // TypeScript, boundary (next is Go) {2, "HandleRequest", "server.go", 42}, // Go, boundary (prev is TypeScript) {3, "processQuery", "server.go", 88}, // Go, non-boundary }); } void t1(){ T(breakpoint_fires_in_both_languages); ws::BreakpointSyncOrchestrator o; o.addToAll("HandleRequest", { {"Go", {"server.go", 42}}, {"TypeScript", {"api.ts", 30}} }); C(o.totalActiveBreakpoints() == 2, "two active"); auto langs = o.activeLanguages("HandleRequest"); bool hasGo = false, hasTs = false; for (auto& l : langs) { if (l == "Go") hasGo = true; if (l == "TypeScript") hasTs = true; } C(hasGo && hasTs, "both Go and TypeScript active"); P(); } void t2(){ T(stepInto_TypeScript_Go_boundary_switches_router); auto router = makeRouter(); auto frames = makeStack(); ws::CrossLanguageStepIntoHandler h; // frames[0] is TypeScript boundary; frames[1] is Go auto r = h.stepInto(frames[0], router, frames, 0); C( r.switched, "switched"); C( r.previousLanguage == "TypeScript", "previous TypeScript"); C( r.newLanguage == "Go", "new Go"); C( router.getActiveLanguage() == "Go", "router now Go"); C( r.targetFrameId == frames[1].id, "targetFrameId correct"); P(); } void t3(){ T(stepOver_boundary_stays_in_TypeScript); auto router = makeRouter(); auto frames = makeStack(); ws::CrossLanguageStepOverHandler h; // frames[0] is TypeScript boundary — step-over stays in TypeScript auto r = h.stepOver(frames[0], router); C( r.crossed, "crossed"); C( r.newLanguage == "TypeScript", "stays TypeScript"); C( router.getActiveLanguage() == "TypeScript", "router still TypeScript"); P(); } void t4(){ T(removeFromAll_clears_both_languages); ws::BreakpointSyncOrchestrator o; o.addToAll("HandleRequest", { {"Go", {"server.go", 42}}, {"TypeScript", {"api.ts", 30}} }); C(o.totalActiveBreakpoints() == 2, "two before remove"); o.removeFromAll("HandleRequest"); C(o.totalActiveBreakpoints() == 0, "zero after remove"); C(o.activeLanguages("HandleRequest").empty(), "no active languages"); P(); } void t5(){ T(sprint280_integration_summary); ws::Sprint280IntegrationSummary s; C(s.stepsCompleted == 5, "5 steps"); C(s.success, "success"); C(s.sprintName() == "Sprint 280: Cross-Language Step + Breakpoints", "name"); P(); } int main(){ std::cout << "Step 1932: Sprint 280 Integration\n"; t1(); t2(); t3(); t4(); t5(); std::cout << "\n" << p << "/" << (p+f) << " passed\n"; return f > 0 ? 1 : 0; }