From 04cfa2aba05088ab9e34542f65f33ca654e49c08 Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Sat, 16 May 2026 16:33:25 +0200 Subject: [PATCH] chore: auto-commit (4 archivos) - data.h - data_http.cpp - views.cpp - appicon.ico Co-Authored-By: Claude Opus 4.7 (1M context) --- appicon.ico | Bin 0 -> 11953 bytes data.h | 4 ++ data_http.cpp | 3 +- views.cpp | 132 +++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 appicon.ico diff --git a/appicon.ico b/appicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..3b4e44ac15fabfb5ca3792b9793562335acb3d7f GIT binary patch literal 11953 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 literal 0 HcmV?d00001 diff --git a/data.h b/data.h index 1c91015..e87860d 100644 --- a/data.h +++ b/data.h @@ -46,6 +46,10 @@ struct FunctionRow { std::string description; std::string created_at; bool tested = false; + // JSON array string ("[\"a\",\"b\"]") con IDs de funciones consumidas. + // Se carga junto con la lista para soportar reverse lookup "Used by" en + // el tab Dependencies del Explorer sin endpoint extra. + std::string uses_functions; }; struct AppRow { diff --git a/data_http.cpp b/data_http.cpp index 4c3bb9d..f0d57c7 100644 --- a/data_http.cpp +++ b/data_http.cpp @@ -373,7 +373,7 @@ bool load_all_functions_http(const std::string& api_url, HttpClient cli(host, port); auto j = api_query(cli, "SELECT id, name, lang, domain, kind, purity, description, " - "created_at, tested FROM functions ORDER BY name"); + "created_at, tested, uses_functions FROM functions ORDER BY name"); if (j.is_null() || !j.contains("rows")) return false; out.clear(); @@ -389,6 +389,7 @@ bool load_all_functions_http(const std::string& api_url, r.description = extract_str(row, 6); r.created_at = extract_str(row, 7); r.tested = extract_row_int(row, 8) != 0; + r.uses_functions = extract_str(row, 9); out.push_back(std::move(r)); } return true; diff --git a/views.cpp b/views.cpp index ba0491a..9e0d943 100644 --- a/views.cpp +++ b/views.cpp @@ -325,6 +325,31 @@ static int g_explorer_test_idx = 0; static char g_explorer_filter[128] = {}; static int g_explorer_lang_idx = 0; static int g_explorer_domain_idx = 0; +// Caches del tab Dependencies — se recomputan en explorer_select() para no +// reparsar JSON cada frame. uses_funcs/uses_types: parse de d.uses_functions +// y d.uses_types. used_by: reverse lookup cliente-side sobre g_explorer_funcs. +static std::vector g_explorer_uses_funcs; +static std::vector g_explorer_uses_types; +static std::vector g_explorer_used_by; + +// Parser tolerante de arrays JSON de strings (`["a","b"]`). Las entradas de +// la BD son IDs `[a-z0-9_]+` sin escapes, asi que un walker simple basta y +// evita anadir dependencia a nlohmann/json (que vive solo en data_http.cpp). +static std::vector parse_string_array_json(const std::string& json_str) { + std::vector out; + if (json_str.empty() || json_str == "[]") return out; + size_t i = 0, n = json_str.size(); + while (i < n) { + while (i < n && json_str[i] != '"') i++; + if (i >= n) break; + i++; // past opening " + size_t start = i; + while (i < n && json_str[i] != '"') i++; + if (i > start) out.emplace_back(json_str.substr(start, i - start)); + if (i < n) i++; // past closing " + } + return out; +} static void trigger_reload() { ImGui::GetIO().UserData = reinterpret_cast(1); @@ -1378,9 +1403,22 @@ static void explorer_select(const std::string& id) { g_explorer_detail = FunctionDetail{}; g_explorer_tests.clear(); g_explorer_test_idx = 0; + g_explorer_uses_funcs.clear(); + g_explorer_uses_types.clear(); + g_explorer_used_by.clear(); if (!g_api_url.empty() && !id.empty()) { load_function_detail_http(g_api_url, id, g_explorer_detail); load_unit_tests_http(g_api_url, id, g_explorer_tests); + // Caches del tab Dependencies — forward + reverse. + g_explorer_uses_funcs = parse_string_array_json(g_explorer_detail.uses_functions); + g_explorer_uses_types = parse_string_array_json(g_explorer_detail.uses_types); + for (const auto& f : g_explorer_funcs) { + if (f.id == id) continue; + auto deps = parse_string_array_json(f.uses_functions); + for (const auto& dep : deps) { + if (dep == id) { g_explorer_used_by.push_back(f.id); break; } + } + } } } @@ -1574,6 +1612,97 @@ void draw_functions_explorer() { } ImGui::EndTabItem(); } + // Tab Dependencies: muestra uses_functions, uses_types, y reverse + // lookup "used by" (clientes-side sobre g_explorer_funcs). Caches + // (g_explorer_uses_*) se rellenan en explorer_select(). + int total_deps = (int)(g_explorer_uses_funcs.size() + + g_explorer_uses_types.size()); + char deps_label[32]; + std::snprintf(deps_label, sizeof(deps_label), + "Dependencies (%d)", total_deps); + if (ImGui::BeginTabItem(deps_label)) { + ImGui::BeginChild("##deps_scroll", ImVec2(0, 0)); + + // Section 1: Uses functions (clickables; color dim si la id + // no resuelve en el catalogo actual). + char hdr1[64]; + std::snprintf(hdr1, sizeof(hdr1), + "Uses functions (%zu)", + g_explorer_uses_funcs.size()); + if (ImGui::CollapsingHeader(hdr1, + ImGuiTreeNodeFlags_DefaultOpen)) { + if (g_explorer_uses_funcs.empty()) { + ImGui::PushStyleColor(ImGuiCol_Text, + fn_tokens::colors::text_dim); + ImGui::TextUnformatted("(none)"); + ImGui::PopStyleColor(); + } else { + for (const auto& fid : g_explorer_uses_funcs) { + bool resolves = false; + for (const auto& f : g_explorer_funcs) { + if (f.id == fid) { resolves = true; break; } + } + ImVec4 col = resolves + ? fn_tokens::colors::text + : fn_tokens::colors::text_dim; + ImGui::PushStyleColor(ImGuiCol_Text, col); + ImGui::PushID(fid.c_str()); + if (ImGui::Selectable(fid.c_str())) { + if (resolves) explorer_select(fid); + } + ImGui::PopID(); + ImGui::PopStyleColor(); + } + } + } + + // Section 2: Uses types — sin navegacion (no hay type explorer + // todavia); bullets para indicar listado pasivo. + char hdr2[64]; + std::snprintf(hdr2, sizeof(hdr2), + "Uses types (%zu)", + g_explorer_uses_types.size()); + if (ImGui::CollapsingHeader(hdr2, + ImGuiTreeNodeFlags_DefaultOpen)) { + if (g_explorer_uses_types.empty()) { + ImGui::PushStyleColor(ImGuiCol_Text, + fn_tokens::colors::text_dim); + ImGui::TextUnformatted("(none)"); + ImGui::PopStyleColor(); + } else { + for (const auto& tid : g_explorer_uses_types) { + ImGui::BulletText("%s", tid.c_str()); + } + } + } + + // Section 3: Used by (reverse) — clientes detectados al + // seleccionar la funcion. + char hdr3[64]; + std::snprintf(hdr3, sizeof(hdr3), + "Used by (%zu)", + g_explorer_used_by.size()); + if (ImGui::CollapsingHeader(hdr3, + ImGuiTreeNodeFlags_DefaultOpen)) { + if (g_explorer_used_by.empty()) { + ImGui::PushStyleColor(ImGuiCol_Text, + fn_tokens::colors::text_dim); + ImGui::TextUnformatted("(no consumers in catalog)"); + ImGui::PopStyleColor(); + } else { + for (const auto& fid : g_explorer_used_by) { + ImGui::PushID(fid.c_str()); + if (ImGui::Selectable(fid.c_str())) { + explorer_select(fid); + } + ImGui::PopID(); + } + } + } + + ImGui::EndChild(); + ImGui::EndTabItem(); + } if (ImGui::BeginTabItem("Metadata")) { ImGui::BeginChild("##meta_scroll", ImVec2(0, 0)); auto kv = [](const char* k, const std::string& v) { @@ -1590,8 +1719,7 @@ void draw_functions_explorer() { kv("Created:", d.created_at); kv("Returns:", d.returns); kv("Error type:", d.error_type); - kv("Uses functions:", d.uses_functions); - kv("Uses types:", d.uses_types); + // Uses functions/types se muestran en el tab Dependencies. kv("Params schema:", d.params_schema); kv("Example:", d.example); kv("Notes:", d.notes);