All files / src helpers.ts

86.48% Statements 32/37
83.33% Branches 25/30
100% Functions 5/5
96% Lines 24/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148            6x           6x       6x                                                                                                                                                     6x     6x     127x       19x       24x 23x 23x   11x 11x 9x 5x 5x     5x   5x       5x       22x   20x                   20x     15x 83x     13x    
/**
 * Signal detection helpers for AI Signal Clarity.
 */
 
import { classifyStringLiteral, StringCategory } from './string-classifier';
 
export const AMBIGUOUS_NAME_PATTERNS = [
  /^[a-z]$/, // single letter: a, b, x, y
  /^(tmp|temp|data|obj|val|res|ret|result|item|elem|thing|stuff|info|misc|util|helper|handler|cb|fn|func)$/i,
  /^[a-z]\d+$/, // x1, x2, n3
];
 
export const MAGIC_LITERAL_IGNORE = new Set([
  0, 1, -1, 2, 10, 100, 1000, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 30, 60, 24,
  7, 365, 200, 201, 204, 400, 401, 403, 404, 500, 80, 443, 3000, 8000, 8080,
]);
export const MAGIC_STRING_IGNORE = new Set([
  '',
  ' ',
  '\n',
  '\t',
  'utf8',
  'utf-8',
  'hex',
  'base64',
  'true',
  'false',
  'null',
  'undefined',
  'node',
  'production',
  'development',
  'test',
  'error',
  'warn',
  'info',
  'debug',
  'main',
  'module',
  'types',
  'scripts',
  'dependencies',
  'devDependencies',
  'peerDependencies',
  'remove',
  'delete',
  'update',
  'create',
  'string',
  'number',
  'boolean',
  'object',
  'array',
  'key',
  'id',
  'name',
  'type',
  'value',
  'version',
  'description',
  'timestamp',
  'date',
  'time',
  'status',
  'mode',
  'action',
  'effect',
  'resource',
  'principal',
  'statement',
  'sid',
  'allow',
  'deny',
  'sts:AssumeRole',
  'iam:PassRole',
  's3:GetObject',
  's3:PutObject',
  's3:DeleteObject',
  's3:ListBucket',
  'events:PutEvents',
  'logs:GetLogEvents',
  'sqs:SendMessage',
  'sqs:ReceiveMessage',
  'dynamodb:GetItem',
  'dynamodb:PutItem',
  'dynamodb:UpdateItem',
  'dynamodb:DeleteItem',
  'dynamodb:Query',
  'dynamodb:Scan',
]);
 
const TAILWIND_PATTERN = /^[a-z0-9:-]+(\/[0-9]+)?$/;
// PascalCase or camelCase with at least 2 words is descriptive enough for AI
const DESCRIPTIVE_NAME_PATTERN =
  /^([A-Z]+[a-z0-9]*){2,}$|^([a-z]+[a-z0-9]*)([A-Z]+[a-z0-9]*)+$/;
 
export function isAmbiguousName(name: string): boolean {
  return AMBIGUOUS_NAME_PATTERNS.some((p) => p.test(name));
}
 
export function isMagicNumber(value: number): boolean {
  return !MAGIC_LITERAL_IGNORE.has(value);
}
 
export function isMagicString(value: string): boolean {
  if (value.length === 0) return false;
  Iif (value.length > 20) return false;
  if (MAGIC_STRING_IGNORE.has(value.toLowerCase())) return false;
 
  Iif (TAILWIND_PATTERN.test(value) && value.includes('-')) return false;
  if (value === value.toUpperCase() && value.length > 3) return false;
  if (DESCRIPTIVE_NAME_PATTERN.test(value)) return false;
  Iif (/[/.]/.test(value)) return false;
  Iif (/^#[0-9a-fA-F]{3,6}$/.test(value)) return false;
 
  // Use the classifier to distinguish between meaningful and UI strings
  const category = classifyStringLiteral(value);
  // Only flag meaningful strings as magic literals, not UI display strings
  Iif (category === StringCategory.UiDisplay) {
    return false;
  }
 
  return !/^\s+$/.test(value);
}
 
export function isRedundantTypeConstant(name: string, value: any): boolean {
  if (typeof value !== 'string') return false;
 
  const typeMap: Record<string, string> = {
    TYPE_STRING: 'string',
    TYPE_OBJECT: 'object',
    TYPE_ARRAY: 'array',
    TYPE_NUMBER: 'number',
    TYPE_BOOLEAN: 'boolean',
    TYPE_INTEGER: 'integer',
  };
 
  // Check for exact matches first
  if (typeMap[name] === value) return true;
 
  // Check for prefix matches e.g. JSON_TYPE_STRING = 'string'
  for (const [key, val] of Object.entries(typeMap)) {
    if (name.endsWith(key) && value === val) return true;
  }
 
  return false;
}