Step 102: memory strategy dashboard
This commit is contained in:
@@ -202,6 +202,7 @@ All 38 steps implemented and passing. Each step has a corresponding test (`step1
|
||||
- [x] Step 99: **IMPLEMENTED** — Annotation context menu for add/edit/remove via ASTMutationAPI (2/2 tests pass)
|
||||
- [x] Step 100: **IMPLEMENTED** — Memory strategy suggestions with lightbulb gutter icons and apply popup (1/1 tests pass)
|
||||
- [x] Step 101: **IMPLEMENTED** — Annotation conflict highlighting with gutter linkage and quick-fix actions (1/1 tests pass)
|
||||
- [x] Step 102: **IMPLEMENTED** — Memory strategy dashboard panel with counts and JSON export (1/1 tests pass)
|
||||
|
||||
---
|
||||
|
||||
@@ -283,6 +284,7 @@ vcpkg's imgui 1.91.9 removed the `sdl2-binding` feature (only `sdl3-binding` exi
|
||||
**Step 99:** Compile and pass (2/2)
|
||||
**Step 100:** Compile and pass (1/1)
|
||||
**Step 101:** Compile and pass (1/1)
|
||||
**Step 102:** Compile and pass (1/1)
|
||||
|
||||
---
|
||||
|
||||
@@ -393,3 +395,4 @@ Sprint 4 in progress. Step 76 (LayoutManager) done. Next: Step 77 (custom code e
|
||||
| 2026-02-09 | Codex | Step 99: Annotation context menu (add/edit/remove) via ASTMutationAPI. 2/2 tests pass. |
|
||||
| 2026-02-09 | Codex | Step 100: Memory strategy suggestions with lightbulb icons and apply popup. 1/1 tests pass. |
|
||||
| 2026-02-09 | Codex | Step 101: Annotation conflict highlighting with quick-fix actions. 1/1 tests pass. |
|
||||
| 2026-02-09 | Codex | Step 102: Memory strategy dashboard panel with counts and JSON export. 1/1 tests pass. |
|
||||
|
||||
@@ -554,6 +554,10 @@ add_executable(step101_test tests/step101_test.cpp)
|
||||
target_include_directories(step101_test PRIVATE src)
|
||||
target_link_libraries(step101_test PRIVATE nlohmann_json::nlohmann_json)
|
||||
|
||||
add_executable(step102_test tests/step102_test.cpp)
|
||||
target_include_directories(step102_test PRIVATE src)
|
||||
target_link_libraries(step102_test PRIVATE nlohmann_json::nlohmann_json)
|
||||
|
||||
find_package(SDL2 CONFIG REQUIRED)
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(glad CONFIG REQUIRED)
|
||||
|
||||
88
editor/src/StrategyDashboard.h
Normal file
88
editor/src/StrategyDashboard.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
// Step 102: Memory strategy dashboard helpers
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "ast/ASTNode.h"
|
||||
#include "ast/Annotation.h"
|
||||
#include "ast/Function.h"
|
||||
#include "ast/Module.h"
|
||||
|
||||
struct AnnotationEntry {
|
||||
std::string nodeId;
|
||||
std::string nodeName;
|
||||
std::string label;
|
||||
int line = -1;
|
||||
};
|
||||
|
||||
inline bool isMemoryAnnotation(const ASTNode* anno) {
|
||||
if (!anno) return false;
|
||||
const auto& ct = anno->conceptType;
|
||||
return ct == "DeallocateAnnotation" || ct == "LifetimeAnnotation" ||
|
||||
ct == "ReclaimAnnotation" || ct == "OwnerAnnotation" ||
|
||||
ct == "AllocateAnnotation";
|
||||
}
|
||||
|
||||
inline std::string annotationLabelFor(const ASTNode* anno) {
|
||||
if (!anno) return "";
|
||||
if (anno->conceptType == "ReclaimAnnotation") {
|
||||
auto* a = static_cast<const ReclaimAnnotation*>(anno);
|
||||
return "@Reclaim(" + a->strategy + ")";
|
||||
}
|
||||
if (anno->conceptType == "OwnerAnnotation") {
|
||||
auto* a = static_cast<const OwnerAnnotation*>(anno);
|
||||
return "@Owner(" + a->strategy + ")";
|
||||
}
|
||||
if (anno->conceptType == "DeallocateAnnotation") {
|
||||
auto* a = static_cast<const DeallocateAnnotation*>(anno);
|
||||
return "@Deallocate(" + a->strategy + ")";
|
||||
}
|
||||
if (anno->conceptType == "LifetimeAnnotation") {
|
||||
auto* a = static_cast<const LifetimeAnnotation*>(anno);
|
||||
return "@Lifetime(" + a->strategy + ")";
|
||||
}
|
||||
if (anno->conceptType == "AllocateAnnotation") {
|
||||
auto* a = static_cast<const AllocateAnnotation*>(anno);
|
||||
return "@Allocate(" + a->strategy + ")";
|
||||
}
|
||||
return anno->conceptType;
|
||||
}
|
||||
|
||||
inline std::string nodeNameFor(const ASTNode* node) {
|
||||
if (!node) return "";
|
||||
if (node->conceptType == "Function") return static_cast<const Function*>(node)->name;
|
||||
if (node->conceptType == "Module") return static_cast<const Module*>(node)->name;
|
||||
return node->conceptType;
|
||||
}
|
||||
|
||||
inline void collectAnnotationEntries(const ASTNode* node, std::vector<AnnotationEntry>& out) {
|
||||
if (!node) return;
|
||||
for (auto* anno : node->getChildren("annotations")) {
|
||||
if (!isMemoryAnnotation(anno)) continue;
|
||||
AnnotationEntry e;
|
||||
e.nodeId = node->id;
|
||||
e.nodeName = nodeNameFor(node);
|
||||
e.label = annotationLabelFor(anno);
|
||||
if (node->hasSpan()) e.line = node->spanStartLine;
|
||||
out.push_back(std::move(e));
|
||||
}
|
||||
for (auto* child : node->allChildren()) {
|
||||
collectAnnotationEntries(child, out);
|
||||
}
|
||||
}
|
||||
|
||||
inline nlohmann::json buildAnnotationSummaryJson(const std::vector<AnnotationEntry>& entries) {
|
||||
nlohmann::json j;
|
||||
j["annotations"] = nlohmann::json::array();
|
||||
for (const auto& e : entries) {
|
||||
j["annotations"].push_back({
|
||||
{"nodeId", e.nodeId},
|
||||
{"nodeName", e.nodeName},
|
||||
{"label", e.label},
|
||||
{"line", e.line}
|
||||
});
|
||||
}
|
||||
return j;
|
||||
}
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "ASTMutationAPI.h"
|
||||
#include "MemoryStrategyInference.h"
|
||||
#include "AnnotationConflict.h"
|
||||
#include "StrategyDashboard.h"
|
||||
#include "ast/Generator.h"
|
||||
#include "ast/Annotation.h"
|
||||
|
||||
@@ -1826,6 +1827,55 @@ int main(int, char**) {
|
||||
|
||||
ImGui::End();
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Memory Strategies dashboard
|
||||
// ---------------------------------------------------------------
|
||||
ImGui::Begin("Memory Strategies");
|
||||
ImGui::PushFont(uiFont);
|
||||
Module* ast = state.active() ? state.active()->sync.getAST() : nullptr;
|
||||
if (!ast) {
|
||||
ImGui::TextDisabled("(no AST)");
|
||||
} else {
|
||||
std::vector<AnnotationEntry> entries;
|
||||
collectAnnotationEntries(ast, entries);
|
||||
std::map<std::string, int> counts;
|
||||
for (const auto& e : entries) counts[e.label]++;
|
||||
|
||||
ImGui::Text("Annotations");
|
||||
ImGui::Separator();
|
||||
for (const auto& [label, count] : counts) {
|
||||
ImGui::Text("%s: %d", label.c_str(), count);
|
||||
}
|
||||
ImGui::Spacing();
|
||||
|
||||
ImGui::Text("Details");
|
||||
ImGui::Separator();
|
||||
for (const auto& e : entries) {
|
||||
std::string lineInfo = e.line >= 0 ? ("L" + std::to_string(e.line + 1)) : "-";
|
||||
std::string row = e.label + " — " + e.nodeName + " (" + lineInfo + ")";
|
||||
if (ImGui::Selectable(row.c_str())) {
|
||||
if (state.active()) state.jumpTo(state.active(), e.line, 0);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Text("Suggestions");
|
||||
ImGui::Separator();
|
||||
for (const auto& s : state.suggestions) {
|
||||
if (s.confidence < 0.5) continue;
|
||||
std::string row = s.annotationType + "(" + s.strategy + ") — " +
|
||||
s.nodeId + " (" + std::to_string(s.confidence) + ")";
|
||||
ImGui::TextUnformatted(row.c_str());
|
||||
}
|
||||
|
||||
if (ImGui::Button("Export JSON")) {
|
||||
auto j = buildAnnotationSummaryJson(entries);
|
||||
state.outputLog += "Annotation summary:\\n" + j.dump(2) + "\\n";
|
||||
}
|
||||
}
|
||||
ImGui::PopFont();
|
||||
ImGui::End();
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Status bar
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
37
editor/tests/step102_test.cpp
Normal file
37
editor/tests/step102_test.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
// Step 102 TDD Test: Memory strategy dashboard helpers
|
||||
//
|
||||
// Tests:
|
||||
// 1. Collect annotation entries and build JSON
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include "StrategyDashboard.h"
|
||||
#include "ast/Module.h"
|
||||
#include "ast/Function.h"
|
||||
#include "ast/Annotation.h"
|
||||
|
||||
int main() {
|
||||
int passed = 0;
|
||||
int failed = 0;
|
||||
|
||||
Module* mod = new Module("m1", "mod", "cpp");
|
||||
mod->setSpan(0, 0, 5, 0);
|
||||
auto* fn = new Function("f1", "foo");
|
||||
fn->setSpan(1, 0, 3, 0);
|
||||
mod->addChild("functions", fn);
|
||||
|
||||
auto* anno = new LifetimeAnnotation("a1", "RAII");
|
||||
fn->addChild("annotations", anno);
|
||||
|
||||
std::vector<AnnotationEntry> entries;
|
||||
collectAnnotationEntries(mod, entries);
|
||||
assert(entries.size() == 1);
|
||||
auto j = buildAnnotationSummaryJson(entries);
|
||||
assert(j.contains("annotations"));
|
||||
assert(j["annotations"].size() == 1);
|
||||
std::cout << "Test 1 PASS: dashboard helpers" << std::endl;
|
||||
++passed;
|
||||
|
||||
std::cout << "\n=== Step 102 Results: " << passed << " passed, " << failed << " failed ===" << std::endl;
|
||||
return failed > 0 ? 1 : 0;
|
||||
}
|
||||
Reference in New Issue
Block a user