diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index a6ae855..8cc5f2f 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -4810,4 +4810,13 @@ target_link_libraries(step658_test PRIVATE tree_sitter_javascript tree_sitter_typescript tree_sitter_java tree_sitter_rust tree_sitter_go) +add_executable(step659_test tests/step659_test.cpp) +target_include_directories(step659_test PRIVATE src) +target_link_libraries(step659_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/src/EntropyScannerModel.h b/editor/src/EntropyScannerModel.h new file mode 100644 index 0000000..e9b9971 --- /dev/null +++ b/editor/src/EntropyScannerModel.h @@ -0,0 +1,65 @@ +#pragma once +// Step 659: Entropy scanner - editor side + +#include +#include +#include + +struct EntropyObservation { + int duplicateSignatures = 0; + int similarModuleNames = 0; + int unusedExports = 0; +}; + +class EntropyScannerModel { +public: + static EntropyObservation scan(const std::vector& signatures, + const std::vector& moduleNames, + const std::vector& exports, + const std::set& usedExports) { + EntropyObservation o; + o.duplicateSignatures = countDuplicates(signatures); + o.similarModuleNames = countPrefixSimilar(moduleNames); + o.unusedExports = countUnused(exports, usedExports); + return o; + } + + static int entropyScore(const EntropyObservation& o) { + return o.duplicateSignatures + o.similarModuleNames + o.unusedExports; + } + + static bool shouldSuggestRefactor(const EntropyObservation& o, int threshold = 3) { + return entropyScore(o) >= threshold; + } + +private: + static int countDuplicates(const std::vector& values) { + std::set seen; + int duplicates = 0; + for (const auto& v : values) { + if (!seen.insert(v).second) ++duplicates; + } + return duplicates; + } + + static int countPrefixSimilar(const std::vector& names) { + int similar = 0; + for (std::size_t i = 0; i < names.size(); ++i) { + for (std::size_t j = i + 1; j < names.size(); ++j) { + if (names[i].size() >= 3 && names[j].rfind(names[i].substr(0, 3), 0) == 0) { + ++similar; + } + } + } + return similar; + } + + static int countUnused(const std::vector& exports, + const std::set& used) { + int unused = 0; + for (const auto& e : exports) { + if (used.find(e) == used.end()) ++unused; + } + return unused; + } +}; diff --git a/editor/tests/step659_test.cpp b/editor/tests/step659_test.cpp new file mode 100644 index 0000000..80fbb49 --- /dev/null +++ b/editor/tests/step659_test.cpp @@ -0,0 +1,24 @@ +// Step 659: Entropy scanner - editor side (12 tests) + +#include "EntropyScannerModel.h" +#include +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: "<=1,"similar");P();} +void t3(){T(scan_counts_unused_exports);auto o=EntropyScannerModel::scan({}, {},{"x","y"},{"x"});C(o.unusedExports==1,"unused");P();} +void t4(){T(score_sums_components);EntropyObservation o{1,2,3};C(EntropyScannerModel::entropyScore(o)==6,"score");P();} +void t5(){T(suggest_refactor_true_at_threshold);EntropyObservation o{1,1,1};C(EntropyScannerModel::shouldSuggestRefactor(o,3),"suggest");P();} +void t6(){T(suggest_refactor_false_below_threshold);EntropyObservation o{1,0,0};C(!EntropyScannerModel::shouldSuggestRefactor(o,3),"no suggest");P();} +void t7(){T(empty_inputs_yield_zeroes);auto o=EntropyScannerModel::scan({}, {}, {}, {});C(o.duplicateSignatures==0&&o.similarModuleNames==0&&o.unusedExports==0,"zero");P();} +void t8(){T(multiple_duplicate_signatures_counted);auto o=EntropyScannerModel::scan({"a","a","a"},{},{},{});C(o.duplicateSignatures==2,"dups");P();} +void t9(){T(used_export_not_counted_unused);auto o=EntropyScannerModel::scan({}, {}, {"x"}, {"x"});C(o.unusedExports==0,"used");P();} +void t10(){T(threshold_parameter_changes_behavior);EntropyObservation o{1,1,0};C(EntropyScannerModel::shouldSuggestRefactor(o,2)&&!EntropyScannerModel::shouldSuggestRefactor(o,3),"threshold");P();} +void t11(){T(similar_prefix_requires_min_length);auto o=EntropyScannerModel::scan({}, {"ab","ac"},{},{});C(o.similarModuleNames==0,"prefix");P();} +void t12(){T(scan_combined_case);auto o=EntropyScannerModel::scan({"a","a"},{"modA","modB"},{"x"},{});C(EntropyScannerModel::entropyScore(o)>=3,"combined");P();} + +int main(){std::cout<<"Step 659: Entropy scanner\n";t1();t2();t3();t4();t5();t6();t7();t8();t9();t10();t11();t12();std::cout<<"\nResults: "<