@rigour-labs/core 3.0.5 → 4.0.0
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.
- package/dist/deep/fact-extractor.d.ts +80 -0
- package/dist/deep/fact-extractor.js +626 -0
- package/dist/deep/index.d.ts +14 -0
- package/dist/deep/index.js +12 -0
- package/dist/deep/prompts.d.ts +22 -0
- package/dist/deep/prompts.js +374 -0
- package/dist/deep/verifier.d.ts +16 -0
- package/dist/deep/verifier.js +388 -0
- package/dist/gates/deep-analysis.d.ts +28 -0
- package/dist/gates/deep-analysis.js +302 -0
- package/dist/gates/deprecated-apis-rules-lang.d.ts +21 -0
- package/dist/gates/deprecated-apis-rules-lang.js +311 -0
- package/dist/gates/deprecated-apis-rules-node.d.ts +19 -0
- package/dist/gates/deprecated-apis-rules-node.js +199 -0
- package/dist/gates/deprecated-apis-rules.d.ts +6 -0
- package/dist/gates/deprecated-apis-rules.js +6 -0
- package/dist/gates/deprecated-apis.js +1 -502
- package/dist/gates/hallucinated-imports-lang.d.ts +16 -0
- package/dist/gates/hallucinated-imports-lang.js +374 -0
- package/dist/gates/hallucinated-imports-stdlib.d.ts +12 -0
- package/dist/gates/hallucinated-imports-stdlib.js +228 -0
- package/dist/gates/hallucinated-imports.d.ts +0 -98
- package/dist/gates/hallucinated-imports.js +10 -678
- package/dist/gates/phantom-apis-data.d.ts +33 -0
- package/dist/gates/phantom-apis-data.js +398 -0
- package/dist/gates/phantom-apis.js +1 -393
- package/dist/gates/phantom-apis.test.js +52 -0
- package/dist/gates/promise-safety-helpers.d.ts +19 -0
- package/dist/gates/promise-safety-helpers.js +101 -0
- package/dist/gates/promise-safety-rules.d.ts +7 -0
- package/dist/gates/promise-safety-rules.js +19 -0
- package/dist/gates/promise-safety.d.ts +1 -21
- package/dist/gates/promise-safety.js +51 -257
- package/dist/gates/runner.d.ts +4 -2
- package/dist/gates/runner.js +46 -1
- package/dist/gates/test-quality-lang.d.ts +30 -0
- package/dist/gates/test-quality-lang.js +188 -0
- package/dist/gates/test-quality.d.ts +0 -14
- package/dist/gates/test-quality.js +13 -186
- package/dist/index.d.ts +10 -0
- package/dist/index.js +12 -2
- package/dist/inference/cloud-provider.d.ts +34 -0
- package/dist/inference/cloud-provider.js +126 -0
- package/dist/inference/index.d.ts +17 -0
- package/dist/inference/index.js +23 -0
- package/dist/inference/model-manager.d.ts +26 -0
- package/dist/inference/model-manager.js +106 -0
- package/dist/inference/sidecar-provider.d.ts +15 -0
- package/dist/inference/sidecar-provider.js +153 -0
- package/dist/inference/types.d.ts +77 -0
- package/dist/inference/types.js +19 -0
- package/dist/pattern-index/indexer-helpers.d.ts +38 -0
- package/dist/pattern-index/indexer-helpers.js +111 -0
- package/dist/pattern-index/indexer-lang.d.ts +13 -0
- package/dist/pattern-index/indexer-lang.js +244 -0
- package/dist/pattern-index/indexer-ts.d.ts +22 -0
- package/dist/pattern-index/indexer-ts.js +258 -0
- package/dist/pattern-index/indexer.d.ts +4 -106
- package/dist/pattern-index/indexer.js +58 -707
- package/dist/pattern-index/staleness-data.d.ts +6 -0
- package/dist/pattern-index/staleness-data.js +262 -0
- package/dist/pattern-index/staleness.js +1 -258
- package/dist/settings.d.ts +104 -0
- package/dist/settings.js +186 -0
- package/dist/storage/db.d.ts +16 -0
- package/dist/storage/db.js +132 -0
- package/dist/storage/findings.d.ts +14 -0
- package/dist/storage/findings.js +38 -0
- package/dist/storage/index.d.ts +9 -0
- package/dist/storage/index.js +8 -0
- package/dist/storage/patterns.d.ts +35 -0
- package/dist/storage/patterns.js +62 -0
- package/dist/storage/scans.d.ts +42 -0
- package/dist/storage/scans.js +55 -0
- package/dist/templates/index.d.ts +12 -16
- package/dist/templates/index.js +11 -527
- package/dist/templates/paradigms.d.ts +2 -0
- package/dist/templates/paradigms.js +46 -0
- package/dist/templates/presets.d.ts +14 -0
- package/dist/templates/presets.js +227 -0
- package/dist/templates/universal-config.d.ts +2 -0
- package/dist/templates/universal-config.js +190 -0
- package/dist/types/index.d.ts +438 -15
- package/dist/types/index.js +41 -1
- package/package.json +6 -2
|
@@ -24,6 +24,7 @@ import { FileScanner } from '../utils/scanner.js';
|
|
|
24
24
|
import { Logger } from '../utils/logger.js';
|
|
25
25
|
import fs from 'fs-extra';
|
|
26
26
|
import path from 'path';
|
|
27
|
+
import { GO_PHANTOM_RULES, CSHARP_PHANTOM_RULES, JAVA_PHANTOM_RULES, NODE_STDLIB_METHODS, PYTHON_STDLIB_METHODS } from './phantom-apis-data.js';
|
|
27
28
|
export class PhantomApisGate extends Gate {
|
|
28
29
|
config;
|
|
29
30
|
constructor(config = {}) {
|
|
@@ -280,396 +281,3 @@ export class PhantomApisGate extends Gate {
|
|
|
280
281
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
281
282
|
}
|
|
282
283
|
}
|
|
283
|
-
/**
|
|
284
|
-
* Go commonly hallucinated APIs — AI mixes up Python/JS idioms with Go.
|
|
285
|
-
*/
|
|
286
|
-
const GO_PHANTOM_RULES = [
|
|
287
|
-
{ pattern: /\bstrings\.includes\s*\(/, module: 'strings', phantom: 'includes', suggestion: "Use strings.Contains()" },
|
|
288
|
-
{ pattern: /\bstrings\.lower\s*\(/, module: 'strings', phantom: 'lower', suggestion: "Use strings.ToLower()" },
|
|
289
|
-
{ pattern: /\bstrings\.upper\s*\(/, module: 'strings', phantom: 'upper', suggestion: "Use strings.ToUpper()" },
|
|
290
|
-
{ pattern: /\bstrings\.strip\s*\(/, module: 'strings', phantom: 'strip', suggestion: "Use strings.TrimSpace()" },
|
|
291
|
-
{ pattern: /\bstrings\.find\s*\(/, module: 'strings', phantom: 'find', suggestion: "Use strings.Index()" },
|
|
292
|
-
{ pattern: /\bstrings\.startswith\s*\(/, module: 'strings', phantom: 'startswith', suggestion: "Use strings.HasPrefix()" },
|
|
293
|
-
{ pattern: /\bstrings\.endswith\s*\(/, module: 'strings', phantom: 'endswith', suggestion: "Use strings.HasSuffix()" },
|
|
294
|
-
{ pattern: /\bos\.ReadFile\s*\(/, module: 'os', phantom: 'ReadFile', suggestion: "Use os.ReadFile() (Go 1.16+) or ioutil.ReadFile() (legacy)" },
|
|
295
|
-
{ pattern: /\bos\.Exists\s*\(/, module: 'os', phantom: 'Exists', suggestion: "Use os.Stat() and check os.IsNotExist(err)" },
|
|
296
|
-
{ pattern: /\bos\.isdir\s*\(/, module: 'os', phantom: 'isdir', suggestion: "Use os.Stat() then .IsDir()" },
|
|
297
|
-
{ pattern: /\bos\.listdir\s*\(/, module: 'os', phantom: 'listdir', suggestion: "Use os.ReadDir()" },
|
|
298
|
-
{ pattern: /\bfmt\.Format\s*\(/, module: 'fmt', phantom: 'Format', suggestion: "Use fmt.Sprintf()" },
|
|
299
|
-
{ pattern: /\bfmt\.Print\s*\((?!ln|f)/, module: 'fmt', phantom: 'Print', suggestion: "fmt.Print() exists but did you mean fmt.Println() or fmt.Printf()?" },
|
|
300
|
-
{ pattern: /\bhttp\.Get\s*\([^)]*\)\s*\.\s*Body/, module: 'http', phantom: 'Get().Body', suggestion: "http.Get() returns (*Response, error) — must check error first" },
|
|
301
|
-
{ pattern: /\bjson\.parse\s*\(/, module: 'json', phantom: 'parse', suggestion: "Use json.Unmarshal()" },
|
|
302
|
-
{ pattern: /\bjson\.stringify\s*\(/, module: 'json', phantom: 'stringify', suggestion: "Use json.Marshal()" },
|
|
303
|
-
{ pattern: /\bfilepath\.Combine\s*\(/, module: 'filepath', phantom: 'Combine', suggestion: "Use filepath.Join()" },
|
|
304
|
-
{ pattern: /\bmath\.Max\s*\(/, module: 'math', phantom: 'Max (pre-1.21)', suggestion: "math.Max() only works on float64. For int, use max() builtin (Go 1.21+)" },
|
|
305
|
-
{ pattern: /\bsort\.Sort\s*\(\s*\[\]/, module: 'sort', phantom: 'Sort([]T)', suggestion: "Use slices.Sort() (Go 1.21+) or sort.Slice()" },
|
|
306
|
-
];
|
|
307
|
-
/**
|
|
308
|
-
* C# commonly hallucinated APIs — AI mixes up Java/Python idioms with .NET.
|
|
309
|
-
*/
|
|
310
|
-
const CSHARP_PHANTOM_RULES = [
|
|
311
|
-
{ pattern: /\.length\b(?!\s*\()/, module: 'String', phantom: '.length', suggestion: "Use .Length (capital L) in C#" },
|
|
312
|
-
{ pattern: /\.equals\s*\(/, module: 'Object', phantom: '.equals()', suggestion: "Use .Equals() (capital E) in C#" },
|
|
313
|
-
{ pattern: /\.toString\s*\(/, module: 'Object', phantom: '.toString()', suggestion: "Use .ToString() (capital T) in C#" },
|
|
314
|
-
{ pattern: /\.hashCode\s*\(/, module: 'Object', phantom: '.hashCode()', suggestion: "Use .GetHashCode() in C#" },
|
|
315
|
-
{ pattern: /\.getClass\s*\(/, module: 'Object', phantom: '.getClass()', suggestion: "Use .GetType() in C#" },
|
|
316
|
-
{ pattern: /\.isEmpty\s*\(/, module: 'String', phantom: '.isEmpty()', suggestion: "Use string.IsNullOrEmpty() or .Length == 0 in C#" },
|
|
317
|
-
{ pattern: /\.charAt\s*\(/, module: 'String', phantom: '.charAt()', suggestion: "Use string[index] indexer in C#" },
|
|
318
|
-
{ pattern: /\.substring\s*\(/, module: 'String', phantom: '.substring()', suggestion: "Use .Substring() (capital S) in C#" },
|
|
319
|
-
{ pattern: /\.indexOf\s*\(/, module: 'String', phantom: '.indexOf()', suggestion: "Use .IndexOf() (capital I) in C#" },
|
|
320
|
-
{ pattern: /List<[^>]+>\s+\w+\s*=\s*new\s+ArrayList/, module: 'Collections', phantom: 'ArrayList', suggestion: "Use new List<T>() in C# — ArrayList is Java" },
|
|
321
|
-
{ pattern: /HashMap</, module: 'Collections', phantom: 'HashMap', suggestion: "Use Dictionary<TKey, TValue> in C#" },
|
|
322
|
-
{ pattern: /System\.out\.println/, module: 'System', phantom: 'System.out.println', suggestion: "Use Console.WriteLine() in C#" },
|
|
323
|
-
{ pattern: /\.stream\s*\(\)\s*\./, module: 'Collections', phantom: '.stream()', suggestion: "Use LINQ (.Select, .Where, etc.) in C# — .stream() is Java" },
|
|
324
|
-
{ pattern: /\.forEach\s*\(\s*\w+\s*->/, module: 'Collections', phantom: '.forEach(x ->)', suggestion: "Use .ForEach(x =>) or foreach loop in C#" },
|
|
325
|
-
{ pattern: /File\.readAllText\s*\(/, module: 'File', phantom: 'readAllText', suggestion: "Use File.ReadAllText() (capital R) in C#" },
|
|
326
|
-
{ pattern: /throws\s+\w+Exception/, module: 'method', phantom: 'throws', suggestion: "C# doesn't use checked exceptions — remove throws clause" },
|
|
327
|
-
];
|
|
328
|
-
/**
|
|
329
|
-
* Java commonly hallucinated APIs — AI mixes up Python/JS/C# idioms with JDK.
|
|
330
|
-
*/
|
|
331
|
-
const JAVA_PHANTOM_RULES = [
|
|
332
|
-
{ pattern: /\.len\s*\(/, module: 'Object', phantom: '.len()', suggestion: "Use .length() for String, .size() for Collection, .length for arrays in Java" },
|
|
333
|
-
{ pattern: /\bprint\s*\(\s*['"]/, module: 'IO', phantom: 'print()', suggestion: "Use System.out.println() in Java" },
|
|
334
|
-
{ pattern: /\.push\s*\(/, module: 'List', phantom: '.push()', suggestion: "Use .add() for List in Java" },
|
|
335
|
-
{ pattern: /\.append\s*\((?!.*StringBuilder|.*StringBuffer)/, module: 'List', phantom: '.append()', suggestion: "Use .add() for List in Java — .append() is for StringBuilder" },
|
|
336
|
-
{ pattern: /\.include(?:s)?\s*\(/, module: 'Collection', phantom: '.includes()', suggestion: "Use .contains() in Java" },
|
|
337
|
-
{ pattern: /\.slice\s*\(/, module: 'List', phantom: '.slice()', suggestion: "Use .subList() for List in Java" },
|
|
338
|
-
{ pattern: /\.map\s*\(\s*\w+\s*=>/, module: 'Collection', phantom: '.map(x =>)', suggestion: "Use .stream().map(x ->) in Java — arrow is -> not =>" },
|
|
339
|
-
{ pattern: /\.filter\s*\(\s*\w+\s*=>/, module: 'Collection', phantom: '.filter(x =>)', suggestion: "Use .stream().filter(x ->) in Java — arrow is -> not =>" },
|
|
340
|
-
{ pattern: /Console\.(?:Write|Read)/, module: 'IO', phantom: 'Console', suggestion: "Console is C# — use System.out.println() or Scanner in Java" },
|
|
341
|
-
{ pattern: /\bvar\s+\w+\s*:\s*\w+\s*=/, module: 'syntax', phantom: 'var x: Type =', suggestion: "Java var doesn't use type annotation: use 'var x =' or 'Type x ='" },
|
|
342
|
-
{ pattern: /\.sorted\s*\(\s*\)(?!\s*\.)/, module: 'List', phantom: '.sorted()', suggestion: "Use Collections.sort() or .stream().sorted() in Java" },
|
|
343
|
-
{ pattern: /\.reversed\s*\(/, module: 'List', phantom: '.reversed()', suggestion: "Use Collections.reverse() in Java (pre-21) or .reversed() (Java 21+)" },
|
|
344
|
-
{ pattern: /String\.format\s*\(\s*\$"/, module: 'String', phantom: 'String.format($"...")', suggestion: "String interpolation $\"\" is C# — use String.format(\"%s\", ...) in Java" },
|
|
345
|
-
{ pattern: /\bnew\s+Map\s*[<(]/, module: 'Collections', phantom: 'new Map()', suggestion: "Use new HashMap<>() in Java — Map is an interface" },
|
|
346
|
-
{ pattern: /\bnew\s+List\s*[<(]/, module: 'Collections', phantom: 'new List()', suggestion: "Use new ArrayList<>() in Java — List is an interface" },
|
|
347
|
-
];
|
|
348
|
-
/**
|
|
349
|
-
* Node.js 22.x stdlib method signatures.
|
|
350
|
-
* Only the most commonly hallucinated modules are covered.
|
|
351
|
-
* Each set contains ALL public methods/properties accessible on the module.
|
|
352
|
-
*/
|
|
353
|
-
const NODE_STDLIB_METHODS = {
|
|
354
|
-
fs: new Set([
|
|
355
|
-
// Sync methods
|
|
356
|
-
'readFileSync', 'writeFileSync', 'appendFileSync', 'copyFileSync', 'renameSync',
|
|
357
|
-
'unlinkSync', 'mkdirSync', 'rmdirSync', 'rmSync', 'readdirSync', 'statSync',
|
|
358
|
-
'lstatSync', 'existsSync', 'accessSync', 'chmodSync', 'chownSync', 'closeSync',
|
|
359
|
-
'fchmodSync', 'fchownSync', 'fdatasyncSync', 'fstatSync', 'fsyncSync',
|
|
360
|
-
'ftruncateSync', 'futimesSync', 'linkSync', 'lutimesSync', 'mkdtempSync',
|
|
361
|
-
'openSync', 'opendirSync', 'readSync', 'readlinkSync', 'realpathSync',
|
|
362
|
-
'symlinkSync', 'truncateSync', 'utimesSync', 'writeSync', 'cpSync',
|
|
363
|
-
'statfsSync', 'globSync',
|
|
364
|
-
// Async callback methods
|
|
365
|
-
'readFile', 'writeFile', 'appendFile', 'copyFile', 'rename', 'unlink',
|
|
366
|
-
'mkdir', 'rmdir', 'rm', 'readdir', 'stat', 'lstat', 'access', 'chmod',
|
|
367
|
-
'chown', 'close', 'fchmod', 'fchown', 'fdatasync', 'fstat', 'fsync',
|
|
368
|
-
'ftruncate', 'futimes', 'link', 'lutimes', 'mkdtemp', 'open', 'opendir',
|
|
369
|
-
'read', 'readlink', 'realpath', 'symlink', 'truncate', 'utimes', 'write',
|
|
370
|
-
'cp', 'statfs', 'glob',
|
|
371
|
-
// Streams
|
|
372
|
-
'createReadStream', 'createWriteStream',
|
|
373
|
-
// Watch
|
|
374
|
-
'watch', 'watchFile', 'unwatchFile',
|
|
375
|
-
// Constants & promises
|
|
376
|
-
'constants', 'promises',
|
|
377
|
-
]),
|
|
378
|
-
path: new Set([
|
|
379
|
-
'basename', 'delimiter', 'dirname', 'extname', 'format', 'isAbsolute',
|
|
380
|
-
'join', 'normalize', 'parse', 'posix', 'relative', 'resolve', 'sep',
|
|
381
|
-
'toNamespacedPath', 'win32', 'matchesGlob',
|
|
382
|
-
]),
|
|
383
|
-
crypto: new Set([
|
|
384
|
-
'createHash', 'createHmac', 'createCipheriv', 'createDecipheriv',
|
|
385
|
-
'createSign', 'createVerify', 'createDiffieHellman', 'createDiffieHellmanGroup',
|
|
386
|
-
'createECDH', 'createSecretKey', 'createPublicKey', 'createPrivateKey',
|
|
387
|
-
'generateKey', 'generateKeyPair', 'generateKeyPairSync', 'generateKeySync',
|
|
388
|
-
'generatePrime', 'generatePrimeSync',
|
|
389
|
-
'getCiphers', 'getCurves', 'getDiffieHellman', 'getFips', 'getHashes',
|
|
390
|
-
'getRandomValues', 'hash',
|
|
391
|
-
'hkdf', 'hkdfSync',
|
|
392
|
-
'pbkdf2', 'pbkdf2Sync',
|
|
393
|
-
'privateDecrypt', 'privateEncrypt', 'publicDecrypt', 'publicEncrypt',
|
|
394
|
-
'randomBytes', 'randomFillSync', 'randomFill', 'randomInt', 'randomUUID',
|
|
395
|
-
'scrypt', 'scryptSync',
|
|
396
|
-
'setEngine', 'setFips',
|
|
397
|
-
'sign', 'verify',
|
|
398
|
-
'subtle', 'timingSafeEqual',
|
|
399
|
-
'constants', 'webcrypto', 'X509Certificate',
|
|
400
|
-
'checkPrime', 'checkPrimeSync',
|
|
401
|
-
'Certificate', 'Cipher', 'Decipher', 'DiffieHellman', 'DiffieHellmanGroup',
|
|
402
|
-
'ECDH', 'Hash', 'Hmac', 'KeyObject', 'Sign', 'Verify',
|
|
403
|
-
]),
|
|
404
|
-
os: new Set([
|
|
405
|
-
'arch', 'availableParallelism', 'constants', 'cpus', 'devNull',
|
|
406
|
-
'endianness', 'EOL', 'freemem', 'getPriority', 'homedir',
|
|
407
|
-
'hostname', 'loadavg', 'machine', 'networkInterfaces', 'platform',
|
|
408
|
-
'release', 'setPriority', 'tmpdir', 'totalmem', 'type',
|
|
409
|
-
'uptime', 'userInfo', 'version',
|
|
410
|
-
]),
|
|
411
|
-
child_process: new Set([
|
|
412
|
-
'exec', 'execFile', 'execFileSync', 'execSync',
|
|
413
|
-
'fork', 'spawn', 'spawnSync',
|
|
414
|
-
]),
|
|
415
|
-
http: new Set([
|
|
416
|
-
'createServer', 'get', 'globalAgent', 'request',
|
|
417
|
-
'Agent', 'ClientRequest', 'Server', 'ServerResponse', 'IncomingMessage',
|
|
418
|
-
'METHODS', 'STATUS_CODES', 'maxHeaderSize', 'validateHeaderName', 'validateHeaderValue',
|
|
419
|
-
'setMaxIdleHTTPParsers',
|
|
420
|
-
]),
|
|
421
|
-
https: new Set([
|
|
422
|
-
'createServer', 'get', 'globalAgent', 'request',
|
|
423
|
-
'Agent', 'Server',
|
|
424
|
-
]),
|
|
425
|
-
url: new Set([
|
|
426
|
-
'domainToASCII', 'domainToUnicode', 'fileURLToPath', 'format',
|
|
427
|
-
'pathToFileURL', 'resolve', 'URL', 'URLSearchParams',
|
|
428
|
-
// Deprecated but still exist
|
|
429
|
-
'parse', 'Url',
|
|
430
|
-
]),
|
|
431
|
-
util: new Set([
|
|
432
|
-
'callbackify', 'debuglog', 'deprecate', 'format', 'formatWithOptions',
|
|
433
|
-
'getSystemErrorName', 'getSystemErrorMap', 'inherits', 'inspect',
|
|
434
|
-
'isDeepStrictEqual', 'parseArgs', 'parseEnv', 'promisify',
|
|
435
|
-
'stripVTControlCharacters', 'styleText',
|
|
436
|
-
'TextDecoder', 'TextEncoder', 'MIMEType', 'MIMEParams',
|
|
437
|
-
'types', 'toUSVString', 'transferableAbortController', 'transferableAbortSignal',
|
|
438
|
-
'aborted',
|
|
439
|
-
]),
|
|
440
|
-
stream: new Set([
|
|
441
|
-
'Readable', 'Writable', 'Duplex', 'Transform', 'PassThrough',
|
|
442
|
-
'pipeline', 'finished', 'compose', 'addAbortSignal',
|
|
443
|
-
'getDefaultHighWaterMark', 'setDefaultHighWaterMark',
|
|
444
|
-
'promises', 'consumers',
|
|
445
|
-
]),
|
|
446
|
-
events: new Set([
|
|
447
|
-
'EventEmitter', 'once', 'on', 'getEventListeners',
|
|
448
|
-
'setMaxListeners', 'listenerCount', 'addAbortListener',
|
|
449
|
-
'getMaxListeners', 'EventEmitterAsyncResource',
|
|
450
|
-
]),
|
|
451
|
-
buffer: new Set([
|
|
452
|
-
'Buffer', 'SlowBuffer', 'transcode',
|
|
453
|
-
'constants', 'kMaxLength', 'kStringMaxLength',
|
|
454
|
-
'atob', 'btoa', 'isAscii', 'isUtf8', 'resolveObjectURL',
|
|
455
|
-
'Blob', 'File',
|
|
456
|
-
]),
|
|
457
|
-
querystring: new Set([
|
|
458
|
-
'decode', 'encode', 'escape', 'parse', 'stringify', 'unescape',
|
|
459
|
-
]),
|
|
460
|
-
net: new Set([
|
|
461
|
-
'createServer', 'createConnection', 'connect',
|
|
462
|
-
'isIP', 'isIPv4', 'isIPv6',
|
|
463
|
-
'Server', 'Socket', 'BlockList', 'SocketAddress',
|
|
464
|
-
'getDefaultAutoSelectFamily', 'setDefaultAutoSelectFamily',
|
|
465
|
-
'getDefaultAutoSelectFamilyAttemptTimeout', 'setDefaultAutoSelectFamilyAttemptTimeout',
|
|
466
|
-
]),
|
|
467
|
-
dns: new Set([
|
|
468
|
-
'lookup', 'lookupService', 'resolve', 'resolve4', 'resolve6',
|
|
469
|
-
'resolveAny', 'resolveCname', 'resolveCaa', 'resolveMx', 'resolveNaptr',
|
|
470
|
-
'resolveNs', 'resolvePtr', 'resolveSoa', 'resolveSrv', 'resolveTxt',
|
|
471
|
-
'reverse', 'setServers', 'getServers', 'setDefaultResultOrder',
|
|
472
|
-
'getDefaultResultOrder',
|
|
473
|
-
'promises', 'Resolver', 'ADDRCONFIG', 'V4MAPPED', 'ALL',
|
|
474
|
-
]),
|
|
475
|
-
tls: new Set([
|
|
476
|
-
'createServer', 'connect', 'createSecureContext', 'createSecurePair',
|
|
477
|
-
'getCiphers', 'rootCertificates', 'DEFAULT_ECDH_CURVE', 'DEFAULT_MAX_VERSION',
|
|
478
|
-
'DEFAULT_MIN_VERSION', 'DEFAULT_CIPHERS',
|
|
479
|
-
'Server', 'TLSSocket', 'SecureContext',
|
|
480
|
-
]),
|
|
481
|
-
zlib: new Set([
|
|
482
|
-
'createGzip', 'createGunzip', 'createDeflate', 'createInflate',
|
|
483
|
-
'createDeflateRaw', 'createInflateRaw', 'createBrotliCompress',
|
|
484
|
-
'createBrotliDecompress', 'createUnzip',
|
|
485
|
-
'gzip', 'gunzip', 'deflate', 'inflate', 'deflateRaw', 'inflateRaw',
|
|
486
|
-
'brotliCompress', 'brotliDecompress', 'unzip',
|
|
487
|
-
'gzipSync', 'gunzipSync', 'deflateSync', 'inflateSync',
|
|
488
|
-
'deflateRawSync', 'inflateRawSync', 'brotliCompressSync',
|
|
489
|
-
'brotliDecompressSync', 'unzipSync',
|
|
490
|
-
'constants',
|
|
491
|
-
]),
|
|
492
|
-
readline: new Set([
|
|
493
|
-
'createInterface', 'clearLine', 'clearScreenDown', 'cursorTo',
|
|
494
|
-
'moveCursor', 'emitKeypressEvents',
|
|
495
|
-
'Interface', 'InterfaceConstructor', 'promises',
|
|
496
|
-
]),
|
|
497
|
-
cluster: new Set([
|
|
498
|
-
'disconnect', 'fork', 'isMaster', 'isPrimary', 'isWorker',
|
|
499
|
-
'schedulingPolicy', 'settings', 'setupMaster', 'setupPrimary',
|
|
500
|
-
'worker', 'workers',
|
|
501
|
-
'Worker', 'SCHED_NONE', 'SCHED_RR',
|
|
502
|
-
]),
|
|
503
|
-
worker_threads: new Set([
|
|
504
|
-
'isMainThread', 'parentPort', 'resourceLimits', 'threadId',
|
|
505
|
-
'workerData', 'getEnvironmentData', 'setEnvironmentData',
|
|
506
|
-
'markAsUntransferable', 'moveMessagePortToContext', 'receiveMessageOnPort',
|
|
507
|
-
'BroadcastChannel', 'MessageChannel', 'MessagePort', 'Worker',
|
|
508
|
-
'SHARE_ENV',
|
|
509
|
-
]),
|
|
510
|
-
timers: new Set([
|
|
511
|
-
'setTimeout', 'clearTimeout', 'setInterval', 'clearInterval',
|
|
512
|
-
'setImmediate', 'clearImmediate',
|
|
513
|
-
'promises',
|
|
514
|
-
]),
|
|
515
|
-
perf_hooks: new Set([
|
|
516
|
-
'performance', 'PerformanceObserver', 'PerformanceEntry',
|
|
517
|
-
'PerformanceMark', 'PerformanceMeasure', 'PerformanceNodeTiming',
|
|
518
|
-
'PerformanceResourceTiming', 'monitorEventLoopDelay',
|
|
519
|
-
'createHistogram',
|
|
520
|
-
]),
|
|
521
|
-
assert: new Set([
|
|
522
|
-
'ok', 'fail', 'equal', 'notEqual', 'deepEqual', 'notDeepEqual',
|
|
523
|
-
'deepStrictEqual', 'notDeepStrictEqual', 'strictEqual', 'notStrictEqual',
|
|
524
|
-
'throws', 'doesNotThrow', 'rejects', 'doesNotReject',
|
|
525
|
-
'ifError', 'match', 'doesNotMatch',
|
|
526
|
-
'strict', 'AssertionError', 'CallTracker',
|
|
527
|
-
]),
|
|
528
|
-
};
|
|
529
|
-
/**
|
|
530
|
-
* Python 3.12+ stdlib method signatures.
|
|
531
|
-
* Covers the most commonly hallucinated modules.
|
|
532
|
-
*/
|
|
533
|
-
const PYTHON_STDLIB_METHODS = {
|
|
534
|
-
os: new Set([
|
|
535
|
-
'getcwd', 'chdir', 'listdir', 'scandir', 'mkdir', 'makedirs',
|
|
536
|
-
'rmdir', 'removedirs', 'remove', 'unlink', 'rename', 'renames',
|
|
537
|
-
'replace', 'stat', 'lstat', 'fstat', 'chmod', 'chown', 'link',
|
|
538
|
-
'symlink', 'readlink', 'walk', 'fwalk', 'path', 'environ',
|
|
539
|
-
'getenv', 'putenv', 'unsetenv', 'getpid', 'getppid', 'getuid',
|
|
540
|
-
'getgid', 'system', 'popen', 'execv', 'execve', 'execvp',
|
|
541
|
-
'execvpe', '_exit', 'fork', 'kill', 'wait', 'waitpid',
|
|
542
|
-
'cpu_count', 'urandom', 'sep', 'linesep', 'devnull', 'curdir',
|
|
543
|
-
'pardir', 'extsep', 'altsep', 'pathsep', 'name', 'access',
|
|
544
|
-
'open', 'close', 'read', 'write', 'pipe', 'dup', 'dup2',
|
|
545
|
-
'ftruncate', 'isatty', 'lseek', 'terminal_size', 'get_terminal_size',
|
|
546
|
-
'get_blocking', 'set_blocking', 'add_dll_directory',
|
|
547
|
-
'get_exec_path', 'getlogin', 'strerror', 'umask',
|
|
548
|
-
'truncate', 'fchdir', 'fchmod', 'fchown',
|
|
549
|
-
]),
|
|
550
|
-
json: new Set([
|
|
551
|
-
'dump', 'dumps', 'load', 'loads',
|
|
552
|
-
'JSONDecoder', 'JSONEncoder', 'JSONDecodeError',
|
|
553
|
-
'tool',
|
|
554
|
-
]),
|
|
555
|
-
sys: new Set([
|
|
556
|
-
'argv', 'exit', 'path', 'modules', 'stdin', 'stdout', 'stderr',
|
|
557
|
-
'version', 'version_info', 'platform', 'executable', 'prefix',
|
|
558
|
-
'exec_prefix', 'maxsize', 'maxunicode', 'byteorder', 'builtin_module_names',
|
|
559
|
-
'flags', 'float_info', 'hash_info', 'implementation', 'int_info',
|
|
560
|
-
'getdefaultencoding', 'getfilesystemencoding', 'getrecursionlimit',
|
|
561
|
-
'getrefcount', 'getsizeof', 'gettrace', 'getprofile',
|
|
562
|
-
'setrecursionlimit', 'settrace', 'setprofile',
|
|
563
|
-
'exc_info', 'last_type', 'last_value', 'last_traceback',
|
|
564
|
-
'api_version', 'copyright', 'dont_write_bytecode',
|
|
565
|
-
'ps1', 'ps2', 'intern', 'is_finalizing',
|
|
566
|
-
'orig_argv', 'platlibdir', 'stdlib_module_names',
|
|
567
|
-
'thread_info', 'unraisablehook', 'winver',
|
|
568
|
-
'addaudithook', 'audit', 'breakpointhook',
|
|
569
|
-
'call_tracing', 'displayhook', 'excepthook',
|
|
570
|
-
'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth',
|
|
571
|
-
'getallocatedblocks', 'getwindowsversion',
|
|
572
|
-
'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth',
|
|
573
|
-
'set_int_max_str_digits', 'get_int_max_str_digits',
|
|
574
|
-
'activate_stack_trampoline', 'deactivate_stack_trampoline',
|
|
575
|
-
'is_stack_trampoline_active', 'last_exc',
|
|
576
|
-
'monitoring', 'exception',
|
|
577
|
-
]),
|
|
578
|
-
re: new Set([
|
|
579
|
-
'compile', 'search', 'match', 'fullmatch', 'split', 'findall',
|
|
580
|
-
'finditer', 'sub', 'subn', 'escape', 'purge', 'error',
|
|
581
|
-
'Pattern', 'Match',
|
|
582
|
-
'A', 'ASCII', 'DEBUG', 'DOTALL', 'I', 'IGNORECASE',
|
|
583
|
-
'L', 'LOCALE', 'M', 'MULTILINE', 'NOFLAG',
|
|
584
|
-
'S', 'U', 'UNICODE', 'VERBOSE', 'X',
|
|
585
|
-
]),
|
|
586
|
-
math: new Set([
|
|
587
|
-
'ceil', 'comb', 'copysign', 'fabs', 'factorial', 'floor',
|
|
588
|
-
'fmod', 'frexp', 'fsum', 'gcd', 'isclose', 'isfinite',
|
|
589
|
-
'isinf', 'isnan', 'isqrt', 'lcm', 'ldexp', 'log', 'log10',
|
|
590
|
-
'log1p', 'log2', 'modf', 'perm', 'pow', 'prod', 'remainder',
|
|
591
|
-
'trunc', 'ulp', 'nextafter', 'sumprod',
|
|
592
|
-
'exp', 'exp2', 'expm1', 'sqrt', 'cbrt',
|
|
593
|
-
'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh',
|
|
594
|
-
'cos', 'cosh', 'degrees', 'dist', 'hypot', 'radians',
|
|
595
|
-
'sin', 'sinh', 'tan', 'tanh',
|
|
596
|
-
'erf', 'erfc', 'gamma', 'lgamma',
|
|
597
|
-
'pi', 'e', 'tau', 'inf', 'nan',
|
|
598
|
-
]),
|
|
599
|
-
datetime: new Set([
|
|
600
|
-
'date', 'time', 'datetime', 'timedelta', 'timezone', 'tzinfo',
|
|
601
|
-
'MINYEAR', 'MAXYEAR', 'UTC',
|
|
602
|
-
]),
|
|
603
|
-
pathlib: new Set([
|
|
604
|
-
'Path', 'PurePath', 'PurePosixPath', 'PureWindowsPath',
|
|
605
|
-
'PosixPath', 'WindowsPath',
|
|
606
|
-
]),
|
|
607
|
-
subprocess: new Set([
|
|
608
|
-
'run', 'call', 'check_call', 'check_output', 'Popen',
|
|
609
|
-
'PIPE', 'STDOUT', 'DEVNULL', 'CompletedProcess',
|
|
610
|
-
'CalledProcessError', 'SubprocessError', 'TimeoutExpired',
|
|
611
|
-
'getoutput', 'getstatusoutput',
|
|
612
|
-
]),
|
|
613
|
-
shutil: new Set([
|
|
614
|
-
'copy', 'copy2', 'copyfile', 'copyfileobj', 'copymode', 'copystat',
|
|
615
|
-
'copytree', 'rmtree', 'move', 'disk_usage', 'chown', 'which',
|
|
616
|
-
'make_archive', 'get_archive_formats', 'register_archive_format',
|
|
617
|
-
'unregister_archive_format', 'unpack_archive', 'get_unpack_formats',
|
|
618
|
-
'register_unpack_format', 'unregister_unpack_format',
|
|
619
|
-
'get_terminal_size', 'SameFileError',
|
|
620
|
-
]),
|
|
621
|
-
collections: new Set([
|
|
622
|
-
'ChainMap', 'Counter', 'OrderedDict', 'UserDict', 'UserList',
|
|
623
|
-
'UserString', 'abc', 'defaultdict', 'deque', 'namedtuple',
|
|
624
|
-
]),
|
|
625
|
-
hashlib: new Set([
|
|
626
|
-
'md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512',
|
|
627
|
-
'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
|
|
628
|
-
'blake2b', 'blake2s', 'shake_128', 'shake_256',
|
|
629
|
-
'new', 'algorithms_available', 'algorithms_guaranteed',
|
|
630
|
-
'pbkdf2_hmac', 'scrypt', 'file_digest',
|
|
631
|
-
]),
|
|
632
|
-
random: new Set([
|
|
633
|
-
'seed', 'getstate', 'setstate', 'getrandbits',
|
|
634
|
-
'randrange', 'randint', 'choice', 'choices', 'shuffle', 'sample',
|
|
635
|
-
'random', 'uniform', 'triangular', 'betavariate', 'expovariate',
|
|
636
|
-
'gammavariate', 'gauss', 'lognormvariate', 'normalvariate',
|
|
637
|
-
'vonmisesvariate', 'paretovariate', 'weibullvariate',
|
|
638
|
-
'Random', 'SystemRandom', 'randbytes',
|
|
639
|
-
]),
|
|
640
|
-
time: new Set([
|
|
641
|
-
'time', 'time_ns', 'clock_gettime', 'clock_gettime_ns',
|
|
642
|
-
'clock_settime', 'clock_settime_ns', 'clock_getres',
|
|
643
|
-
'gmtime', 'localtime', 'mktime', 'asctime', 'ctime',
|
|
644
|
-
'strftime', 'strptime', 'sleep', 'monotonic', 'monotonic_ns',
|
|
645
|
-
'perf_counter', 'perf_counter_ns', 'process_time', 'process_time_ns',
|
|
646
|
-
'thread_time', 'thread_time_ns', 'get_clock_info',
|
|
647
|
-
'struct_time', 'timezone', 'altzone', 'daylight', 'tzname',
|
|
648
|
-
'CLOCK_BOOTTIME', 'CLOCK_MONOTONIC', 'CLOCK_MONOTONIC_RAW',
|
|
649
|
-
'CLOCK_PROCESS_CPUTIME_ID', 'CLOCK_REALTIME',
|
|
650
|
-
'CLOCK_TAI', 'CLOCK_THREAD_CPUTIME_ID',
|
|
651
|
-
]),
|
|
652
|
-
csv: new Set([
|
|
653
|
-
'reader', 'writer', 'DictReader', 'DictWriter',
|
|
654
|
-
'Sniffer', 'register_dialect', 'unregister_dialect',
|
|
655
|
-
'get_dialect', 'list_dialects', 'field_size_limit',
|
|
656
|
-
'QUOTE_ALL', 'QUOTE_MINIMAL', 'QUOTE_NONNUMERIC', 'QUOTE_NONE',
|
|
657
|
-
'QUOTE_NOTNULL', 'QUOTE_STRINGS',
|
|
658
|
-
'Dialect', 'Error', 'excel', 'excel_tab', 'unix_dialect',
|
|
659
|
-
]),
|
|
660
|
-
logging: new Set([
|
|
661
|
-
'getLogger', 'basicConfig', 'shutdown', 'setLoggerClass',
|
|
662
|
-
'setLogRecordFactory', 'lastResort', 'captureWarnings',
|
|
663
|
-
'debug', 'info', 'warning', 'error', 'critical', 'exception',
|
|
664
|
-
'log', 'disable', 'addLevelName', 'getLevelName', 'getLevelNamesMapping',
|
|
665
|
-
'makeLogRecord', 'getHandlerByName', 'getHandlerNames',
|
|
666
|
-
'Logger', 'Handler', 'Formatter', 'Filter', 'LogRecord',
|
|
667
|
-
'StreamHandler', 'FileHandler', 'NullHandler',
|
|
668
|
-
'BufferingFormatter', 'LoggerAdapter', 'PercentStyle',
|
|
669
|
-
'StrFormatStyle', 'StringTemplateStyle',
|
|
670
|
-
'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL',
|
|
671
|
-
'FATAL', 'WARN', 'NOTSET',
|
|
672
|
-
'raiseExceptions', 'root',
|
|
673
|
-
'handlers', 'config',
|
|
674
|
-
]),
|
|
675
|
-
};
|
|
@@ -247,6 +247,33 @@ func check() {
|
|
|
247
247
|
expect(failures).toHaveLength(1);
|
|
248
248
|
expect(failures[0].details).toContain('Exists');
|
|
249
249
|
});
|
|
250
|
+
it('should NOT flag real Go stdlib functions (os.ReadFile, fmt.Print, math.Max)', async () => {
|
|
251
|
+
mockFindFiles.mockResolvedValue(['main.go']);
|
|
252
|
+
mockReadFile.mockResolvedValue(`
|
|
253
|
+
package main
|
|
254
|
+
|
|
255
|
+
import (
|
|
256
|
+
"fmt"
|
|
257
|
+
"math"
|
|
258
|
+
"os"
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
func main() {
|
|
262
|
+
data, err := os.ReadFile("config.json")
|
|
263
|
+
if err != nil {
|
|
264
|
+
fmt.Printf("error: %v\n", err)
|
|
265
|
+
return
|
|
266
|
+
}
|
|
267
|
+
fmt.Println(string(data))
|
|
268
|
+
fmt.Print("done\n")
|
|
269
|
+
x := math.Max(1.5, 2.5)
|
|
270
|
+
fmt.Sprintf("max: %f", x)
|
|
271
|
+
fmt.Fprintf(os.Stderr, "log\n")
|
|
272
|
+
}
|
|
273
|
+
`);
|
|
274
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
275
|
+
expect(failures).toHaveLength(0);
|
|
276
|
+
});
|
|
250
277
|
});
|
|
251
278
|
describe('PhantomApisGate — C#', () => {
|
|
252
279
|
let gate;
|
|
@@ -317,4 +344,29 @@ class Service {
|
|
|
317
344
|
const failures = await gate.run({ cwd: '/project' });
|
|
318
345
|
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
319
346
|
});
|
|
347
|
+
it('should NOT flag real Java methods (Deque.push, StringBuilder.append, stream().sorted(), List.reversed())', async () => {
|
|
348
|
+
mockFindFiles.mockResolvedValue(['RealJava.java']);
|
|
349
|
+
mockReadFile.mockResolvedValue(`
|
|
350
|
+
import java.util.*;
|
|
351
|
+
import java.util.stream.*;
|
|
352
|
+
class RealJava {
|
|
353
|
+
void test() {
|
|
354
|
+
Deque<String> deque = new ArrayDeque<>();
|
|
355
|
+
deque.push("hello");
|
|
356
|
+
|
|
357
|
+
Stack<Integer> stack = new Stack<>();
|
|
358
|
+
stack.push(42);
|
|
359
|
+
|
|
360
|
+
StringBuilder sb = new StringBuilder();
|
|
361
|
+
sb.append("world");
|
|
362
|
+
|
|
363
|
+
List<Integer> nums = List.of(3, 1, 2);
|
|
364
|
+
List<Integer> sorted = nums.stream().sorted().collect(Collectors.toList());
|
|
365
|
+
List<Integer> rev = nums.reversed();
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
`);
|
|
369
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
370
|
+
expect(failures).toHaveLength(0);
|
|
371
|
+
});
|
|
320
372
|
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper utilities for promise-safety gate.
|
|
3
|
+
* Extracted to keep promise-safety.ts under 500 lines.
|
|
4
|
+
*/
|
|
5
|
+
export interface PromiseViolation {
|
|
6
|
+
file: string;
|
|
7
|
+
line: number;
|
|
8
|
+
type: 'unhandled-then' | 'unsafe-parse' | 'async-no-await' | 'unsafe-fetch' | 'ignored-error' | 'deadlock-risk' | 'bare-except';
|
|
9
|
+
code: string;
|
|
10
|
+
reason: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function extractBraceBody(content: string, startIdx: number): string | null;
|
|
13
|
+
export declare function extractIndentedBody(content: string, startIdx: number): string | null;
|
|
14
|
+
export declare function isInsideTryBlock(lines: string[], lineIdx: number): boolean;
|
|
15
|
+
export declare function isInsidePythonTry(lines: string[], lineIdx: number): boolean;
|
|
16
|
+
export declare function isInsideRubyRescue(lines: string[], lineIdx: number): boolean;
|
|
17
|
+
export declare function hasCatchAhead(lines: string[], idx: number): boolean;
|
|
18
|
+
export declare function hasStatusCheckAhead(lines: string[], idx: number): boolean;
|
|
19
|
+
export declare function stripStrings(line: string): string;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper utilities for promise-safety gate.
|
|
3
|
+
* Extracted to keep promise-safety.ts under 500 lines.
|
|
4
|
+
*/
|
|
5
|
+
export function extractBraceBody(content, startIdx) {
|
|
6
|
+
let depth = 1;
|
|
7
|
+
let idx = startIdx;
|
|
8
|
+
while (depth > 0 && idx < content.length) {
|
|
9
|
+
if (content[idx] === '{')
|
|
10
|
+
depth++;
|
|
11
|
+
if (content[idx] === '}')
|
|
12
|
+
depth--;
|
|
13
|
+
idx++;
|
|
14
|
+
}
|
|
15
|
+
return depth === 0 ? content.substring(startIdx, idx - 1) : null;
|
|
16
|
+
}
|
|
17
|
+
export function extractIndentedBody(content, startIdx) {
|
|
18
|
+
const rest = content.substring(startIdx);
|
|
19
|
+
const lines = rest.split('\n');
|
|
20
|
+
if (lines.length < 2)
|
|
21
|
+
return null;
|
|
22
|
+
let bodyIndent = -1;
|
|
23
|
+
const bodyLines = [];
|
|
24
|
+
for (let i = 1; i < lines.length; i++) {
|
|
25
|
+
const line = lines[i];
|
|
26
|
+
if (line.trim() === '' || line.trim().startsWith('#')) {
|
|
27
|
+
bodyLines.push(line);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const indent = line.length - line.trimStart().length;
|
|
31
|
+
if (bodyIndent === -1) {
|
|
32
|
+
bodyIndent = indent;
|
|
33
|
+
}
|
|
34
|
+
if (indent < bodyIndent)
|
|
35
|
+
break;
|
|
36
|
+
bodyLines.push(line);
|
|
37
|
+
}
|
|
38
|
+
return bodyLines.join('\n');
|
|
39
|
+
}
|
|
40
|
+
export function isInsideTryBlock(lines, lineIdx) {
|
|
41
|
+
let braceDepth = 0;
|
|
42
|
+
for (let j = lineIdx - 1; j >= Math.max(0, lineIdx - 30); j--) {
|
|
43
|
+
const prevLine = stripStrings(lines[j]);
|
|
44
|
+
for (const ch of prevLine) {
|
|
45
|
+
if (ch === '}')
|
|
46
|
+
braceDepth++;
|
|
47
|
+
if (ch === '{')
|
|
48
|
+
braceDepth--;
|
|
49
|
+
}
|
|
50
|
+
if (/\btry\s*\{/.test(prevLine) && braceDepth <= 0)
|
|
51
|
+
return true;
|
|
52
|
+
if (/\}\s*catch\s*\(/.test(prevLine))
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
export function isInsidePythonTry(lines, lineIdx) {
|
|
58
|
+
const lineIndent = lines[lineIdx].length - lines[lineIdx].trimStart().length;
|
|
59
|
+
for (let j = lineIdx - 1; j >= Math.max(0, lineIdx - 30); j--) {
|
|
60
|
+
const trimmed = lines[j].trim();
|
|
61
|
+
if (trimmed === '')
|
|
62
|
+
continue;
|
|
63
|
+
const indent = lines[j].length - lines[j].trimStart().length;
|
|
64
|
+
if (indent < lineIndent && /^\s*try\s*:/.test(lines[j]))
|
|
65
|
+
return true;
|
|
66
|
+
if (indent < lineIndent && /^\s*(?:except|finally)\s*/.test(lines[j]))
|
|
67
|
+
return false;
|
|
68
|
+
if (indent === 0 && /^(?:def|class|async\s+def)\s/.test(trimmed))
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
export function isInsideRubyRescue(lines, lineIdx) {
|
|
74
|
+
for (let j = lineIdx - 1; j >= Math.max(0, lineIdx - 30); j--) {
|
|
75
|
+
const trimmed = lines[j].trim();
|
|
76
|
+
if (trimmed === 'begin')
|
|
77
|
+
return true;
|
|
78
|
+
if (/^rescue\b/.test(trimmed))
|
|
79
|
+
return false;
|
|
80
|
+
if (/^(?:def|class|module)\s/.test(trimmed))
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
export function hasCatchAhead(lines, idx) {
|
|
86
|
+
for (let j = idx; j < Math.min(idx + 10, lines.length); j++) {
|
|
87
|
+
if (/\.catch\s*\(/.test(lines[j]))
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
export function hasStatusCheckAhead(lines, idx) {
|
|
93
|
+
for (let j = idx; j < Math.min(idx + 10, lines.length); j++) {
|
|
94
|
+
if (/\.\s*ok\b/.test(lines[j]) || /\.status(?:Text)?\b/.test(lines[j]))
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
export function stripStrings(line) {
|
|
100
|
+
return line.replace(/`[^`]*`/g, '""').replace(/"[^"]*"/g, '""').replace(/'[^']*'/g, '""');
|
|
101
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language detection data for promise-safety gate.
|
|
3
|
+
* Extracted to keep promise-safety.ts under 500 lines.
|
|
4
|
+
*/
|
|
5
|
+
export type Lang = 'js' | 'python' | 'go' | 'ruby' | 'csharp' | 'unknown';
|
|
6
|
+
export declare const LANG_EXTENSIONS: Record<string, Lang>;
|
|
7
|
+
export declare const LANG_GLOBS: Record<Lang, string[]>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language detection data for promise-safety gate.
|
|
3
|
+
* Extracted to keep promise-safety.ts under 500 lines.
|
|
4
|
+
*/
|
|
5
|
+
export const LANG_EXTENSIONS = {
|
|
6
|
+
'.ts': 'js', '.tsx': 'js', '.js': 'js', '.jsx': 'js', '.mjs': 'js', '.cjs': 'js',
|
|
7
|
+
'.py': 'python', '.pyw': 'python',
|
|
8
|
+
'.go': 'go',
|
|
9
|
+
'.rb': 'ruby', '.rake': 'ruby',
|
|
10
|
+
'.cs': 'csharp',
|
|
11
|
+
};
|
|
12
|
+
export const LANG_GLOBS = {
|
|
13
|
+
js: ['**/*.{ts,js,tsx,jsx,mjs,cjs}'],
|
|
14
|
+
python: ['**/*.py'],
|
|
15
|
+
go: ['**/*.go'],
|
|
16
|
+
ruby: ['**/*.rb'],
|
|
17
|
+
csharp: ['**/*.cs'],
|
|
18
|
+
unknown: [],
|
|
19
|
+
};
|