arkgate 4.8.21 → 4.8.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -133,7 +133,7 @@ function matchTestTitle(content, id) {
133
133
  if (!id)
134
134
  return undefined;
135
135
  const escaped = escapeRegExp(id);
136
- const re = new RegExp(`(?:describe|it|test|context)\\s*\\(\\s*(['"\`])([^'"\`]*${escaped}[^'"\`]*)\\1`, 'i');
136
+ const re = new RegExp(`(?:describe|it|test|context)\\s*\\(\\s*(['"\`])((?:(?!\\1)[^\\\\]|\\\\.)*?${escaped}(?:(?!\\1)[^\\\\]|\\\\.)*?)\\1`, 'i');
137
137
  const match = re.exec(maskNonCode(content, false));
138
138
  const title = match?.[2];
139
139
  return title === undefined ? undefined : title;
@@ -160,7 +160,7 @@ function declarationShape(content, name) {
160
160
  },
161
161
  {
162
162
  shape: 'const',
163
- source: `(?:^|[\\s;{}])export\\s+(?:const|let|var)\\s+${n}\\s*=`,
163
+ source: `(?:^|[\\s;{}])export\\s+(?:const|let|var)\\s+${n}(?:\\s*:(?:[^=]|=>)+?)?\\s*=(?!>)`,
164
164
  },
165
165
  {
166
166
  shape: 'type',
@@ -382,15 +382,36 @@ function rankCoverage(invariant, files, scanTests = true) {
382
382
  }
383
383
  }
384
384
  }
385
- const best = testTitle
385
+ let best = testTitle
386
386
  ? { kind: 'test-title', file: testTitle.file, title: testTitle.title }
387
387
  : declaration
388
388
  ? { kind: 'declaration', file: declaration.file, shape: declaration.shape }
389
389
  : mention
390
390
  ? { kind: 'mention-only', file: mention.file, context: mention.context }
391
391
  : { kind: 'none' };
392
+ if (best.kind === 'mention-only' &&
393
+ best.context === 'comment' &&
394
+ needle &&
395
+ symbolInCodeElsewhere(files.fileContents, tests, needle.name, best.file)) {
396
+ best = { kind: 'declaration-miss', symbol: needle.name };
397
+ }
392
398
  return { best, ...(testTitle ? { testTitle } : {}), ...(declaration ? { declaration } : {}) };
393
399
  }
400
+ /** True when `name` survives comment/string masking in some non-test file other than `mentionFile`. */
401
+ function symbolInCodeElsewhere(fileContents, tests, name, mentionFile) {
402
+ const needle = new RegExp(`(?:^|[^A-Za-z0-9_$])${escapeRegExp(name)}(?=$|[^A-Za-z0-9_$])`);
403
+ const mention = normalizePath(mentionFile);
404
+ for (const file of Object.keys(fileContents)) {
405
+ if (tests.has(normalizePath(file)) || normalizePath(file) === mention)
406
+ continue;
407
+ const content = fileContents[file];
408
+ if (!content)
409
+ continue;
410
+ if (needle.test(maskNonCode(content, true)))
411
+ return true;
412
+ }
413
+ return false;
414
+ }
394
415
  /**
395
416
  * Best coverage evidence for `invariant` in `files`.
396
417
  * test-title beats a declaration; a declaration beats a bare mention; a bare
@@ -409,6 +430,7 @@ export function countsAsCoverage(ev) {
409
430
  case 'declaration':
410
431
  return true;
411
432
  case 'mention-only':
433
+ case 'declaration-miss':
412
434
  case 'none':
413
435
  return false;
414
436
  }
@@ -434,6 +456,8 @@ export function describeCoverage(invariant, ev) {
434
456
  return `found \`${ev.shape} ${declaredLabel(invariant)}\` in ${ev.file}`;
435
457
  case 'mention-only':
436
458
  return `${invariant.id} appears only in ${mentionWhere(ev.context)} in ${ev.file}; put it in a describe/it title`;
459
+ case 'declaration-miss':
460
+ return `no declaration matched \`${ev.symbol}\``;
437
461
  case 'none':
438
462
  return 'no scanned test names it in a describe/it title and no declared symbol was found';
439
463
  }
@@ -392,7 +392,7 @@ declare function createAdapterResult(input: {
392
392
  }): CurrentAdapterResult;
393
393
 
394
394
  /** ArkGate library version — single source of truth. */
395
- declare const version = "4.8.21";
395
+ declare const version = "4.8.22";
396
396
 
397
397
  /**
398
398
  * AI Code Gate (basic).
@@ -1738,8 +1738,10 @@ type DeclarationShape = 'function' | 'class' | 'const' | 'method' | 'type' | 'in
1738
1738
  type MentionContext = 'test-body' | 'comment' | 'string' | 'import';
1739
1739
  /**
1740
1740
  * One coverage verdict. Best evidence wins: test-title, then declaration,
1741
- * then mention-only, then none. Regexes, the test-file vs source split, and
1742
- * `Aggregate.method` lookup stay behind this value.
1741
+ * then mention-only, then none. A comment in another file, when the symbol
1742
+ * still occurs in code, is `declaration-miss` and does not count.
1743
+ * Regexes, the test-file vs source split, and `Aggregate.method` lookup stay
1744
+ * behind this value.
1743
1745
  */
1744
1746
  type CoverageEvidence = {
1745
1747
  kind: 'test-title';
@@ -1753,6 +1755,9 @@ type CoverageEvidence = {
1753
1755
  kind: 'mention-only';
1754
1756
  file: string;
1755
1757
  context: MentionContext;
1758
+ } | {
1759
+ kind: 'declaration-miss';
1760
+ symbol: string;
1756
1761
  } | {
1757
1762
  kind: 'none';
1758
1763
  };