Step 659: entropy scanner model
This commit is contained in:
@@ -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)
|
||||
|
||||
65
editor/src/EntropyScannerModel.h
Normal file
65
editor/src/EntropyScannerModel.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
// Step 659: Entropy scanner - editor side
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct EntropyObservation {
|
||||
int duplicateSignatures = 0;
|
||||
int similarModuleNames = 0;
|
||||
int unusedExports = 0;
|
||||
};
|
||||
|
||||
class EntropyScannerModel {
|
||||
public:
|
||||
static EntropyObservation scan(const std::vector<std::string>& signatures,
|
||||
const std::vector<std::string>& moduleNames,
|
||||
const std::vector<std::string>& exports,
|
||||
const std::set<std::string>& 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<std::string>& values) {
|
||||
std::set<std::string> seen;
|
||||
int duplicates = 0;
|
||||
for (const auto& v : values) {
|
||||
if (!seen.insert(v).second) ++duplicates;
|
||||
}
|
||||
return duplicates;
|
||||
}
|
||||
|
||||
static int countPrefixSimilar(const std::vector<std::string>& 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<std::string>& exports,
|
||||
const std::set<std::string>& used) {
|
||||
int unused = 0;
|
||||
for (const auto& e : exports) {
|
||||
if (used.find(e) == used.end()) ++unused;
|
||||
}
|
||||
return unused;
|
||||
}
|
||||
};
|
||||
24
editor/tests/step659_test.cpp
Normal file
24
editor/tests/step659_test.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
// Step 659: Entropy scanner - editor side (12 tests)
|
||||
|
||||
#include "EntropyScannerModel.h"
|
||||
#include <iostream>
|
||||
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: "<<m<<"\n"; ++f; }
|
||||
#define C(c,m) if(!(c)){F(m);return;}
|
||||
|
||||
void t1(){T(scan_counts_duplicate_signatures);auto o=EntropyScannerModel::scan({"a()","a()"},{},{},{});C(o.duplicateSignatures==1,"dup");P();}
|
||||
void t2(){T(scan_counts_similar_module_names);auto o=EntropyScannerModel::scan({}, {"modAlpha","modBeta"},{},{});C(o.similarModuleNames>=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: "<<p<<"/"<<(p+f)<<" passed\n";return f?1:0;}
|
||||
24
progress.md
24
progress.md
@@ -13576,3 +13576,27 @@ apiary browser visibility into one Phase 40a readiness flow.
|
||||
- `editor/src/Phase40aIntegration.h` (`38` <= `600`)
|
||||
- `editor/tests/step658_test.cpp` within test-file size guidance (`20` lines)
|
||||
- Header-only architecture and naming conventions remain aligned with `ARCHITECTURE.md`
|
||||
|
||||
### Step 659: Entropy scanner - editor-side
|
||||
**Status:** PASS (12/12 tests)
|
||||
|
||||
Adds entropy scanning model for duplicate signatures, similar module names, and
|
||||
unused exports with scoring and refactor-threshold recommendation logic.
|
||||
|
||||
**Files added:**
|
||||
- `editor/src/EntropyScannerModel.h` - entropy scan/scoring model
|
||||
- `editor/tests/step659_test.cpp` - 12 tests for scan signals and thresholds
|
||||
|
||||
**Files modified:**
|
||||
- `editor/CMakeLists.txt` - `step659_test` target
|
||||
|
||||
**Verification run:**
|
||||
- `cmake -S editor -B editor/build-native` - PASS
|
||||
- `cmake --build editor/build-native --target step659_test step658_test` - PASS
|
||||
- `./editor/build-native/step659_test` - PASS (12/12)
|
||||
- `./editor/build-native/step658_test` - PASS (8/8) regression coverage
|
||||
|
||||
**Architecture gate check:**
|
||||
- `editor/src/EntropyScannerModel.h` (`65` <= `600`)
|
||||
- `editor/tests/step659_test.cpp` within test-file size guidance (`24` lines)
|
||||
- Header-only architecture and naming conventions remain aligned with `ARCHITECTURE.md`
|
||||
|
||||
Reference in New Issue
Block a user