Skip to content

Commit 3c24150

Browse files
committed
fix: resolve false positives for issues #2, #6, #7, #8
- #7: Add word boundary to missing_error_handling regex to prevent matching 'refetch()' as 'fetch()' - #6: Skip fetch/axios/http matches inside comment lines (single-line, JSDoc, block comments) - #2a: Skip unsafe_double_type_assertion matches in comment lines and detect common English phrases (e.g. 'as soon as React') - #2b: Skip production_console_log when guarded by conditional (if) on same or preceding line - Fix BUG matching inside DEBUG by adding leading word boundary to todo_comment regex - Add comprehensive false-positive test fixture covering all reported cases
1 parent 3eb07de commit 3c24150

3 files changed

Lines changed: 465 additions & 23 deletions

File tree

ai-slop-detector.ts

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ class AISlopDetector {
270270
},
271271
{
272272
id: 'missing_error_handling',
273-
pattern: /(fetch|axios|http)\s*\(/g,
273+
pattern: /\b(fetch|axios|http)\s*\(/g,
274274
message: "Potential missing error handling for promise. Consider adding try/catch or .catch().",
275275
severity: 'medium',
276276
description: 'Detects calls that might need error handling',
@@ -289,7 +289,7 @@ class AISlopDetector {
289289
},
290290
{
291291
id: 'todo_comment',
292-
pattern: /(TODO|FIXME|HACK|XXX|BUG)\b/g,
292+
pattern: /\b(TODO|FIXME|HACK|XXX|BUG)\b/g,
293293
message: "Found TODO/FIXME/HACK comment indicating incomplete implementation.",
294294
severity: 'medium',
295295
description: 'Detects incomplete implementation markers'
@@ -729,21 +729,36 @@ class AISlopDetector {
729729

730730
// Special handling for missing error handling - look for properly handled fetch calls
731731
if (pattern.id === 'missing_error_handling') {
732+
const fullLine = line.trim();
733+
// Skip matches inside comment lines (single-line, JSDoc, block)
734+
if (fullLine.startsWith('//') || fullLine.startsWith('*') || fullLine.startsWith('/*')) {
735+
continue;
736+
}
732737
// Check if this fetch call is part of a properly handled async function
733738
const isProperlyHandled = this.isFetchCallProperlyHandled(lines, i, match.index);
734739
if (isProperlyHandled) {
735-
continue; // Skip this fetch call as it's properly handled
740+
continue;
736741
}
737742
}
738743

739744
// Special handling for unsafe_double_type_assertion - skip legitimate UI library patterns
740745
if (pattern.id === 'unsafe_double_type_assertion') {
741-
// Check the full line context to identify potentially legitimate patterns
742746
const fullLine = line.trim();
743-
// Skip patterns that are actually safe (as unknown as Type) since we changed the regex
744-
// but double-check to be extra sure
747+
// Skip patterns that are actually safe (as unknown as Type)
745748
if (fullLine.includes('as unknown as')) {
746-
continue; // This is actually safe - skip it
749+
continue;
750+
}
751+
// Skip matches inside comment lines (e.g., "as soon as React")
752+
if (fullLine.startsWith('//') || fullLine.startsWith('*') || fullLine.startsWith('/*')) {
753+
continue;
754+
}
755+
// Skip matches where the preceding token is a preposition or common English word
756+
// indicating natural language rather than a type assertion
757+
const matchStart = match.index ?? 0;
758+
const preceding = line.substring(Math.max(0, matchStart - 10), matchStart).trim();
759+
const englishIndicators = ['as soon', 'as quick', 'as fast', 'as smooth', 'as long', 'as much', 'as little', 'as well', 'as good', 'as bad', 'as easy', 'as hard', 'as simple', 'as clear'];
760+
if (englishIndicators.some(phrase => preceding.toLowerCase().endsWith(phrase))) {
761+
continue;
747762
}
748763
}
749764

@@ -756,6 +771,20 @@ class AISlopDetector {
756771
continue;
757772
}
758773

774+
// Skip console calls guarded by a conditional on the same line
775+
// e.g., if (isDev) console.log('debug');
776+
if (/^if\s*\(/.test(fullLine)) {
777+
continue;
778+
}
779+
780+
// Skip console calls inside a conditional block opened on a prior line
781+
if (i > 0) {
782+
const prevLine = lines[i - 1].trim();
783+
if (/^if\s*\(/.test(prevLine) && (prevLine.includes('{') || fullLine.startsWith('{') === false)) {
784+
continue;
785+
}
786+
}
787+
759788
// Skip general debugging logs that might be intentional in development
760789
if (fullLine.includes('console.log(') &&
761790
(fullLine.includes('Debug') || fullLine.includes('debug') || fullLine.includes('debug:'))) {

0 commit comments

Comments
 (0)