sicua
Version:
A tool for analyzing project structure and dependencies
206 lines (202 loc) • 7.3 kB
JavaScript
;
/**
* Ground truth verification for line counting accuracy
* This creates test cases with KNOWN correct answers to verify which method is right
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifyLineCounterAccuracy = verifyLineCounterAccuracy;
exports.findMostAccurateMethod = findMostAccurateMethod;
exports.quickGroundTruthTest = quickGroundTruthTest;
const lineCounter_1 = require("./lineCounter");
const lineCounterVer_1 = require("./lineCounterVer");
/**
* Test cases with manually verified correct answers
*/
const GROUND_TRUTH_TESTS = [
{
name: "Simple case",
content: `const x = 1;
// This is a comment
const y = 2;`,
expected: {
totalLines: 3,
codeLines: 2,
commentLines: 1,
blankLines: 0,
},
explanation: "2 code lines, 1 comment line, 0 blank lines",
},
{
name: "Mixed line (code + comment)",
content: `const x = 1; // Inline comment
const y = 2;`,
expected: {
totalLines: 2,
codeLines: 2, // This should count as CODE, not comment
commentLines: 0, // The comment is part of the code line
blankLines: 0,
},
explanation: "Mixed lines should count as CODE lines, not comment lines",
},
{
name: "Block comment",
content: `/*
* Multi-line comment
* Another line
*/
const x = 1;`,
expected: {
totalLines: 5,
codeLines: 1,
commentLines: 4,
blankLines: 0,
},
explanation: "4 comment lines, 1 code line",
},
{
name: "JSDoc (should be excluded)",
content: `/**
* JSDoc comment - should NOT count as comment
* @param x parameter
*/
const func = (x) => x;`,
expected: {
totalLines: 5,
codeLines: 1,
commentLines: 0, // JSDoc should be excluded
blankLines: 4, // JSDoc lines count as blank/ignored
},
explanation: "JSDoc should be excluded per requirements",
},
{
name: "Blank lines",
content: `const x = 1;
const y = 2;
`,
expected: {
totalLines: 5,
codeLines: 2,
commentLines: 0,
blankLines: 3,
},
explanation: "2 code lines, 3 blank lines",
},
{
name: "Complex mixed",
content: `const obj = { // Start object
prop: 'value', // Property comment
/* Block comment */
other: 42
}; // End object`,
expected: {
totalLines: 6,
codeLines: 4, // Lines with actual code (even if they have comments)
commentLines: 1, // Only the pure block comment line
blankLines: 1,
},
explanation: "Mixed lines should count as code, pure comment lines as comments",
},
];
/**
* Run ground truth verification
*/
function verifyLineCounterAccuracy() {
const results = {
original: { correct: 0, total: GROUND_TRUTH_TESTS.length, accuracy: 0 },
simple: { correct: 0, total: GROUND_TRUTH_TESTS.length, accuracy: 0 },
regex: { correct: 0, total: GROUND_TRUTH_TESTS.length, accuracy: 0 },
detailed: { correct: 0, total: GROUND_TRUTH_TESTS.length, accuracy: 0 },
};
const failures = [];
GROUND_TRUTH_TESTS.forEach((test) => {
// Run all counting methods silently
const original = (0, lineCounter_1.countLines)(test.content);
const simple = (0, lineCounterVer_1.simpleLineCount)(test.content);
const regex = (0, lineCounterVer_1.regexLineCount)(test.content);
const detailed = (0, lineCounterVer_1.detailedLineCount)(test.content);
const testResults = { original, simple, regex, detailed };
// Check each method against expected results
const checkMethod = (methodName, result) => {
const matches = result.totalLines === test.expected.totalLines &&
result.codeLines === test.expected.codeLines &&
result.commentLines === test.expected.commentLines &&
result.blankLines === test.expected.blankLines;
if (matches) {
results[methodName].correct++;
}
return matches;
};
const originalCorrect = checkMethod("original", original);
const simpleCorrect = checkMethod("simple", simple);
const regexCorrect = checkMethod("regex", regex);
const detailedCorrect = checkMethod("detailed", detailed);
// If any method failed, record the failure
if (!originalCorrect ||
!simpleCorrect ||
!regexCorrect ||
!detailedCorrect) {
failures.push({
testName: test.name,
expected: test.expected,
results: testResults,
});
}
});
// Calculate accuracies
Object.keys(results).forEach((method) => {
const methodResults = results[method];
methodResults.accuracy = Math.round((methodResults.correct / methodResults.total) * 100);
});
// Only log summary
console.log("📊 Ground Truth Verification Results:");
console.log(` Original method: ${results.original.accuracy}% (${results.original.correct}/${results.original.total})`);
console.log(` Simple method: ${results.simple.accuracy}% (${results.simple.correct}/${results.simple.total})`);
console.log(` Regex method: ${results.regex.accuracy}% (${results.regex.correct}/${results.regex.total})`);
console.log(` Detailed method: ${results.detailed.accuracy}% (${results.detailed.correct}/${results.detailed.total})`);
if (failures.length > 0) {
console.log(`❌ ${failures.length} test case(s) failed. Failed tests: ${failures
.map((f) => f.testName)
.join(", ")}`);
}
else {
console.log(`✅ All methods passed all ground truth tests!`);
}
return { results, failures };
}
/**
* Identify which counting method is most accurate
*/
function findMostAccurateMethod() {
const verification = verifyLineCounterAccuracy();
const accuracies = verification.results;
let bestMethod = "original";
let bestAccuracy = accuracies.original.accuracy;
Object.entries(accuracies).forEach(([method, stats]) => {
if (stats.accuracy > bestAccuracy) {
bestMethod = method;
bestAccuracy = stats.accuracy;
}
});
console.log(`🏆 Most accurate method: ${bestMethod} (${bestAccuracy}% accuracy)`);
if (bestAccuracy < 100) {
console.log("⚠️ No method achieved 100% accuracy - line counter needs fixes!");
}
return bestMethod;
}
/**
* Quick test to see which methods agree with ground truth
*/
function quickGroundTruthTest() {
const verification = verifyLineCounterAccuracy();
const accuracies = Object.fromEntries(Object.entries(verification.results).map(([method, stats]) => [
method,
stats.accuracy,
]));
const mostAccurate = findMostAccurateMethod();
const needsFixes = Math.max(...Object.values(accuracies)) < 100;
return {
mostAccurate,
allAccuracies: accuracies,
needsFixes,
};
}