Files
whetstone_DSL/editor/tests/step526_test.cpp

159 lines
6.7 KiB
C++
Raw Normal View History

// Step 526: Symbol Scope Extractor (12 tests)
#include "SymbolScopeExtractor.h"
#include <iostream>
static int passed = 0, failed = 0;
#define TEST(name) { std::cout << " " << #name << "... "; }
#define PASS() { std::cout << "PASS\n"; ++passed; }
#define FAIL(msg) { std::cout << "FAIL: " << msg << "\n"; ++failed; }
#define CHECK(cond, msg) if (!(cond)) { FAIL(msg); return; } else {}
static std::vector<ScopedSymbol> sampleCppFunctionSymbols() {
return {
{"render", "Function", 1},
{"buffer", "Variable", 2},
{"cursor", "Variable", 3},
{"cursor", "Variable", 1},
{"count", "Parameter", 3},
{"EditorState", "Type", 0},
{"std", "Namespace", 0},
{"#include", "Import", 0}
};
}
void test_cpp_function_snapshot_filters_by_allowed_kinds() {
TEST(cpp_function_snapshot_filters_by_allowed_kinds);
SymbolScopeExtractor e;
auto snapshot = e.buildSnapshot("cpp", "Function", sampleCppFunctionSymbols());
CHECK(snapshot.supported, "cpp function should be supported");
CHECK(snapshot.candidates.size() == 6, "only allowed symbol kinds should be included");
PASS();
}
void test_snapshot_prefers_nearest_scope_for_same_symbol_name() {
TEST(snapshot_prefers_nearest_scope_for_same_symbol_name);
SymbolScopeExtractor e;
auto snapshot = e.buildSnapshot("cpp", "Function", sampleCppFunctionSymbols());
int depth = -1;
for (const auto& c : snapshot.candidates) {
if (c.name == "cursor") depth = c.scopeDepth;
}
CHECK(depth == 3, "nearest symbol depth should be retained");
PASS();
}
void test_unknown_language_is_unsupported() {
TEST(unknown_language_is_unsupported);
SymbolScopeExtractor e;
auto snapshot = e.buildSnapshot("haskell", "Function", sampleCppFunctionSymbols());
CHECK(!snapshot.supported, "unknown language should be unsupported");
CHECK(snapshot.candidates.empty(), "unsupported snapshot should have no candidates");
PASS();
}
void test_unknown_node_kind_is_unsupported() {
TEST(unknown_node_kind_is_unsupported);
SymbolScopeExtractor e;
auto snapshot = e.buildSnapshot("cpp", "LambdaMagic", sampleCppFunctionSymbols());
CHECK(!snapshot.supported, "unknown node kind should be unsupported");
PASS();
}
void test_unresolved_symbols_empty_for_in_scope_requests() {
TEST(unresolved_symbols_empty_for_in_scope_requests);
SymbolScopeExtractor e;
auto snapshot = e.buildSnapshot("cpp", "Function", sampleCppFunctionSymbols());
auto unresolved = e.unresolvedSymbols(snapshot, {"cursor", "count", "EditorState"});
CHECK(unresolved.empty(), "all requested symbols are in scope");
PASS();
}
void test_unresolved_symbols_reports_out_of_scope_requests() {
TEST(unresolved_symbols_reports_out_of_scope_requests);
SymbolScopeExtractor e;
auto snapshot = e.buildSnapshot("cpp", "Function", sampleCppFunctionSymbols());
auto unresolved = e.unresolvedSymbols(snapshot, {"cursor", "ghost", "unknownType"});
CHECK(unresolved.size() == 2, "two symbols should be unresolved");
CHECK(unresolved[0] == "ghost", "results should be sorted");
CHECK(unresolved[1] == "unknownType", "results should include both unresolved names");
PASS();
}
void test_can_apply_blocks_unresolved_symbol_requests() {
TEST(can_apply_blocks_unresolved_symbol_requests);
SymbolScopeExtractor e;
auto snapshot = e.buildSnapshot("cpp", "Function", sampleCppFunctionSymbols());
CHECK(!e.canApply(snapshot, {"cursor", "ghost"}), "unresolved symbol should block apply");
PASS();
}
void test_can_apply_false_when_snapshot_is_unsupported() {
TEST(can_apply_false_when_snapshot_is_unsupported);
SymbolScopeExtractor e;
auto snapshot = e.buildSnapshot("zig", "Function", sampleCppFunctionSymbols());
CHECK(!e.canApply(snapshot, {"cursor"}), "unsupported snapshot should block apply");
PASS();
}
void test_forbidden_symbols_are_excluded_from_snapshot() {
TEST(forbidden_symbols_are_excluded_from_snapshot);
SymbolScopeExtractor e;
auto snapshot = e.buildSnapshot("cpp", "Function", sampleCppFunctionSymbols(), {"cursor"});
auto unresolved = e.unresolvedSymbols(snapshot, {"cursor"});
CHECK(unresolved.size() == 1, "forbidden symbol should be excluded");
CHECK(unresolved[0] == "cursor", "forbidden symbol should be unresolved");
PASS();
}
void test_register_rule_adds_new_language_mapping() {
TEST(register_rule_adds_new_language_mapping);
SymbolScopeExtractor e;
e.registerRule("java", "Method", {"Variable", "Parameter"});
auto snapshot = e.buildSnapshot("java", "Method", {{"value", "Variable", 1}});
CHECK(snapshot.supported, "new rule should become supported");
CHECK(snapshot.candidates.size() == 1, "registered rule should include matching kind");
PASS();
}
void test_register_rule_overrides_existing_mapping() {
TEST(register_rule_overrides_existing_mapping);
SymbolScopeExtractor e;
e.registerRule("cpp", "Function", {"Function"});
auto snapshot = e.buildSnapshot("cpp", "Function", sampleCppFunctionSymbols());
CHECK(snapshot.supported, "overridden rule should remain supported");
CHECK(snapshot.candidates.size() == 1, "override should restrict allowed kinds");
CHECK(snapshot.candidates[0].name == "render", "function should remain");
PASS();
}
void test_empty_visible_symbol_set_yields_empty_candidates() {
TEST(empty_visible_symbol_set_yields_empty_candidates);
SymbolScopeExtractor e;
auto snapshot = e.buildSnapshot("cpp", "Function", {});
CHECK(snapshot.supported, "supported rule should remain supported");
CHECK(snapshot.candidates.empty(), "empty input should produce empty candidates");
PASS();
}
int main() {
std::cout << "Step 526: Symbol Scope Extractor\n";
test_cpp_function_snapshot_filters_by_allowed_kinds(); // 1
test_snapshot_prefers_nearest_scope_for_same_symbol_name(); // 2
test_unknown_language_is_unsupported(); // 3
test_unknown_node_kind_is_unsupported(); // 4
test_unresolved_symbols_empty_for_in_scope_requests(); // 5
test_unresolved_symbols_reports_out_of_scope_requests(); // 6
test_can_apply_blocks_unresolved_symbol_requests(); // 7
test_can_apply_false_when_snapshot_is_unsupported(); // 8
test_forbidden_symbols_are_excluded_from_snapshot(); // 9
test_register_rule_adds_new_language_mapping(); // 10
test_register_rule_overrides_existing_mapping(); // 11
test_empty_visible_symbol_set_yields_empty_candidates(); // 12
std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n";
return failed == 0 ? 0 : 1;
}