ucn 5.5.3 → 5.6.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.
Files changed (71) hide show
  1. package/.claude/skills/ucn/SKILL.md +35 -12
  2. package/.claude/skills/ucn/references/commands.md +18 -14
  3. package/.claude/skills/ucn/references/resolution-rules.md +4 -0
  4. package/.claude/skills/ucn/references/trust-contract.md +4 -4
  5. package/CHANGELOG.md +474 -0
  6. package/README.md +69 -29
  7. package/cli/flags.js +184 -0
  8. package/cli/index.js +137 -324
  9. package/core/account.js +44 -87
  10. package/core/analysis.js +273 -107
  11. package/core/ast-analysis.js +2 -0
  12. package/core/bridge.js +14 -0
  13. package/core/cache.js +101 -16
  14. package/core/callers.js +352 -70
  15. package/core/capture.js +331 -0
  16. package/core/change-kinds.js +888 -0
  17. package/core/check.js +1117 -139
  18. package/core/command-contracts.js +7 -6
  19. package/core/constructed-class.js +1195 -0
  20. package/core/contract-membership.js +142 -0
  21. package/core/deadcode.js +362 -84
  22. package/core/deletion.js +401 -0
  23. package/core/discovery.js +104 -9
  24. package/core/entrypoints.js +12 -6
  25. package/core/evidence-bands.js +68 -0
  26. package/core/evidence-bands.json +44 -0
  27. package/core/execute.js +172 -161
  28. package/core/hot-summary.js +241 -0
  29. package/core/index-ir.js +3 -1
  30. package/core/ir.js +5 -1
  31. package/core/member-signatures.js +789 -0
  32. package/core/output/analysis-ext.js +20 -10
  33. package/core/output/analysis.js +98 -60
  34. package/core/output/check.js +98 -37
  35. package/core/output/doctor.js +34 -1
  36. package/core/output/find.js +2 -1
  37. package/core/output/lines.js +63 -3
  38. package/core/output/public.js +29 -11
  39. package/core/output/refactoring.js +32 -0
  40. package/core/output/reporting.js +15 -2
  41. package/core/output/search.js +11 -2
  42. package/core/output/tracing.js +35 -7
  43. package/core/output-budget.js +124 -57
  44. package/core/parallel-build.js +3 -3
  45. package/core/project.js +106 -23
  46. package/core/provenance-type.js +12 -5
  47. package/core/public-command.js +35 -9
  48. package/core/python-modules.js +6 -0
  49. package/core/reflection.js +151 -23
  50. package/core/registry.js +623 -72
  51. package/core/reporting.js +69 -34
  52. package/core/review-items.js +75 -0
  53. package/core/search.js +89 -128
  54. package/core/shared.js +0 -45
  55. package/core/snapshot.js +350 -0
  56. package/core/source-universe.js +707 -0
  57. package/core/test-units.js +3624 -0
  58. package/core/tracing.js +150 -96
  59. package/core/verify.js +27 -11
  60. package/languages/adapter.js +8 -3
  61. package/languages/c-family.js +12 -0
  62. package/languages/csharp.js +634 -0
  63. package/languages/go.js +120 -0
  64. package/languages/index.js +422 -4
  65. package/languages/java.js +712 -0
  66. package/languages/javascript.js +1460 -2
  67. package/languages/lexical-scope.js +68 -0
  68. package/languages/python.js +1672 -1
  69. package/languages/rust.js +91 -0
  70. package/mcp/server.js +44 -110
  71. package/package.json +10 -5
@@ -104,6 +104,14 @@ const JAVA_LANG_NOT_SERIALIZABLE = ['Object', 'Runnable', 'AutoCloseable', 'Comp
104
104
 
105
105
  const STRUCTURAL_TRAITS = {
106
106
  typeSystem: 'structural',
107
+ // How a callable's return contract can come from its body instead of its
108
+ // header. 'unannotated': a callable with no return annotation takes the
109
+ // type its body returns; 'placeholder': a written placeholder type is
110
+ // deduced from the body; 'opaque': a declared opaque type still exposes
111
+ // properties of the concrete value. Empty: the header is the contract.
112
+ inferredReturnForms: ['unannotated'],
113
+ // Callable kinds a body statement alone selects, with no header change.
114
+ callableKindFromBody: [],
107
115
  // A write on the instance can replace an inherited method with a
108
116
  // callable value, including a wrapper of the previous method.
109
117
  instanceAttributesShadowMethods: true,
@@ -154,6 +162,10 @@ const STRUCTURAL_TRAITS = {
154
162
  // 'namespace-usings' (C#: enclosing namespaces, then using directives,
155
163
  // global usings and project-file <Using> items), or null.
156
164
  typeNameScoping: null,
165
+ // The platform's generic types a language writes with a syntax of its
166
+ // own: { nullable, tuple }, each the type's qualified name (C#:
167
+ // `System.Nullable<T>` is `T?`). Two spellings of one type.
168
+ platformTypeForms: null,
157
169
  typeNameSourceCanonical: null,
158
170
  typeNameOwnersAt: null,
159
171
  implementationOwnerSyntax: null,
@@ -256,6 +268,9 @@ const STRUCTURAL_TRAITS = {
256
268
  constructorArgumentNodes: { delegation: { nodeType: 'call_expression', argsField: 'arguments' } },
257
269
  functionalTypeConstruction: false,
258
270
  constructorInheritance: { order: 'single', classNodes: ['class_declaration', 'class'], headerNode: 'class_heritage' },
271
+ // Methods whose result a context-manager statement binds (`with X() as
272
+ // v` binds `X().__enter__()`), or null when the language has none.
273
+ contextEnterMethods: null,
259
274
  implicitBaseConstruction: null,
260
275
  // Whether a constructor delegation is spelled by a keyword (`this(..)`,
261
276
  // `super(..)`, `base(..)`) rather than by the type's name (C++
@@ -303,6 +318,123 @@ const STRUCTURAL_TRAITS = {
303
318
  // text dependencies; no other language checks a test function's name
304
319
  // against a declaration.
305
320
  nameBoundTestFunctions: null,
321
+ // Methods a type declares to satisfy a standard-library contract it
322
+ // never names (interfaces satisfied implicitly): name -> parameter
323
+ // count. A zero textual use of one is not evidence that it is unused.
324
+ implicitStandardContracts: null,
325
+ // Is this project type a contract a value can satisfy WITHOUT naming it
326
+ // (assigned, passed or returned as the type with no implements clause)?
327
+ // null: types are satisfied by declaration only, or the language has
328
+ // its own model (Go's method sets). A type that satisfies such a
329
+ // contract by its member names keeps the members the contract requires.
330
+ structuralContract: null,
331
+ // Can another file import ANY module-level name of a module, declared
332
+ // or merely imported there, with no export syntax (Python)? Removing
333
+ // such a name, an import included, takes it from its importers.
334
+ moduleNamesImportable: false,
335
+ // Is a directory importable as a package without its package file
336
+ // (Python namespace packages)? Then deleting that file takes away the
337
+ // names it declared, not the package.
338
+ packageFileOptional: false,
339
+ // Module-level names that let a module supply names it does not write
340
+ // (Python: a module `__getattr__`, a rewritten package `__path__`). A
341
+ // package that declares one cannot be shown to lack a submodule.
342
+ moduleSupplyHooks: [],
343
+ // Is a member's type whatever the class's methods assign to it (Python
344
+ // instance attributes)? Then an assignment to a receiver member in any
345
+ // method is part of the class's contract.
346
+ memberTypesFromAssignments: false,
347
+ // Does an async function's anonymous future expose properties of its
348
+ // body to callers (Rust auto traits: Send, Sync)?
349
+ asyncReturnIsOpaque: false,
350
+ // Modifiers that let the compiler run a callable and hand callers its
351
+ // VALUE (C++ constexpr/consteval, Rust `const fn`): the body is then
352
+ // part of what a caller relies on. null: no such callables.
353
+ compileTimeCallableMarkers: null,
354
+ // Callable names the language supplies with no import and no
355
+ // declaration (builtins, globals): a bare call of one always means
356
+ // something. null: every callable name is declared or imported.
357
+ ambientCallables: null,
358
+ // Builtins among `ambientCallables` that never return (Python `exit`),
359
+ // and global objects whose every member returns (`console`).
360
+ ambientNeverCallables: null,
361
+ ambientReturningNamespaces: null,
362
+ // How a declaration says "a call of this never returns" (`never`,
363
+ // `NoReturn`): a type checker ends the caller's path at a call of one,
364
+ // and only at a declared one. []: the language has no such type; null:
365
+ // no return contract is read from a body in this language.
366
+ neverReturnTypes: null,
367
+ // Can a type checker decide a condition from the names in it (Python:
368
+ // `sys.version_info`, `sys.platform`, `TYPE_CHECKING`, constants its
369
+ // configuration defines)? Then a condition that guards part of what a
370
+ // body returns is part of it; elsewhere only a condition that names
371
+ // nothing (`while (true)`) is decided.
372
+ namedConditionsDecidable: false,
373
+ // Do files without module syntax share one global scope (classic
374
+ // JavaScript scripts)? Then a top-level name of one is visible in all.
375
+ scriptGlobalScope: false,
376
+ // Are the members of a class compared and enumerated by SHAPE
377
+ // (TypeScript)? Then the trait answers whether anything with the
378
+ // class's members is a value of it: `(classNode, ignoredLines) =>
379
+ // boolean`, true unless the class itself declares a private or
380
+ // protected instance member (members starting on `ignoredLines` left
381
+ // out). null: a class is its declaration, and its members are reached
382
+ // by name only.
383
+ classComparedByShape: null,
384
+ // How a class member takes part in the class's type: `(classNode,
385
+ // name, line) => { role: 'instance' | 'optional' | 'static', hidden }
386
+ // | null`; hidden: private, protected or `#`.
387
+ classMemberRole: null,
388
+ // Members of an object literal declared as a type, read from syntax:
389
+ // `(root, line) => { names, open } | null` (languages/javascript.js).
390
+ typedLiteralMembers: null,
391
+ // The interface whose members every object has (`Object`): a project
392
+ // that declares one adds members to every literal.
393
+ universalObjectInterface: null,
394
+ // Has the language's checker been told not to report a break, as its
395
+ // own scanner reads comments (`// @ts-ignore` above the line the break
396
+ // is reported on, `# type: ignore` on a line of the reported range, a
397
+ // rule turned off for the file)? `(site) => boolean` with site
398
+ // { lines, root, line, kind: 'arity' | 'import-name' | 'import-module'
399
+ // | 'undefined-name' | 'literal', name, most, memo }. A break at such a
400
+ // site is one the toolchain will not show: check lists it and does not
401
+ // block on it.
402
+ checkSuppressedAt: null,
403
+ // The tests a file declares, as its runner collects them:
404
+ // `(fileEntry, helpers) => { units, inheriting }` where a unit is
405
+ // { kind: 'test' | 'suite', name, suite: [names], line, endLine } plus
406
+ // what a selector needs (core/test-units.js). Null: the language's
407
+ // tests are not read, and nothing is said about them.
408
+ testUnits: null,
409
+ // (fileEntry, helpers) => boolean: does this file hold code the runner
410
+ // asks at run time that may leave tests out (a conftest hook, a TestMain).
411
+ testGate: null,
412
+ // `(fileEntry, projectDeclaresType) => { marked, bases }` or null: can
413
+ // a file hold test code, from the index alone (no tree)? Asked before
414
+ // a file whose name is no test file's is read for the tests in it.
415
+ testCodeGate: null,
416
+ // Which family of runners executes the language's tests; the family's
417
+ // manifests are the evidence a runner is named on. Null: none modeled.
418
+ testRunnerFamily: null,
419
+ // Modules whose import in a test file names its runner: `() => Map` of
420
+ // module name to runner id; null where an import says nothing of it.
421
+ testRunnerModules: null,
422
+ // What a module of the language exports under a name, as far as
423
+ // declaring tests goes: `(fileEntry, helpers, name) => binding | null`.
424
+ // A test file that takes its runner through a project module is read
425
+ // through it. Null: imports are not followed.
426
+ testExport: null,
427
+ // How the language's runners name a test file. A test-path file that
428
+ // declares no test and is not named like one is support code.
429
+ testFileNames: [],
430
+ // Is the import of `module` written on a line one the project's judge
431
+ // resolves (an import statement), not a call it never looks into?
432
+ // `(root, line, module) => boolean`; null: every import of the language
433
+ // is a statement.
434
+ checkedImportAt: null,
435
+ // Does a virtual member change what a type IS to existing code (C++: a
436
+ // class with one is no aggregate, so `T t{1, 2}` stops compiling)?
437
+ virtualMemberChangesShape: false,
306
438
  // Whether a top-level type is declared in a source file named after it
307
439
  // (fix #386): javac requires `public class Widget` in Widget.java, so a
308
440
  // type rename renames that file too.
@@ -350,7 +482,15 @@ const STRUCTURAL_TRAITS = {
350
482
  // class literals. `hintPattern` locates vocabulary spellings whose
351
483
  // enclosing call nodes are inspected (the AST decides); `namespaceLookups` are module-namespace lookups by
352
484
  // name (eval, globals()[k]). `family` groups languages sharing one
353
- // runtime. null = no runtime reflection.
485
+ // runtime. `unnamed` are reflective calls that carry no member name and
486
+ // `codeExecution` calls and constructions that run code built at
487
+ // runtime: both are counted per file with the rest of the vocabulary
488
+ // (fileEntry.reflectionUses / evalUses, what `repo` and the completeness
489
+ // footer disclose) and never matched against names. Such a rule is
490
+ // `{ callee }` (the callee as written; `qualified` when it has a
491
+ // receiver), `{ package }` (a call qualified by a local name the file's
492
+ // imports bind to that module) or `{ construct }` (the constructed
493
+ // class). null = no runtime reflection.
354
494
  reflectionApi: null,
355
495
  // Members every class inherits from the implicit root supertype, keyed by
356
496
  // name with their parameter count (Java Object.toString/equals/...,
@@ -371,6 +511,9 @@ const STRUCTURAL_TRAITS = {
371
511
  };
372
512
  const NOMINAL_TRAITS = {
373
513
  typeSystem: 'nominal',
514
+ // See STRUCTURAL_TRAITS: a declared return type is the whole contract.
515
+ inferredReturnForms: [],
516
+ callableKindFromBody: [],
374
517
  instanceAttributesShadowMethods: false,
375
518
  inherentMethodsPrecedeTraitImpls: false,
376
519
  derefFieldAccess: false,
@@ -381,6 +524,7 @@ const NOMINAL_TRAITS = {
381
524
  hasConstructors: false,
382
525
  fixedConstructorName: null,
383
526
  constructorInheritance: null,
527
+ contextEnterMethods: null,
384
528
  implicitBaseConstruction: null,
385
529
  keywordConstructorDelegation: false,
386
530
  constructorUsesAreTypeReferences: false,
@@ -403,6 +547,7 @@ const NOMINAL_TRAITS = {
403
547
  moduleTypeIdentity: false,
404
548
  standardPathRoots: [],
405
549
  typeNameScoping: null,
550
+ platformTypeForms: null,
406
551
  typeNameSourceCanonical: null,
407
552
  typeNameOwnersAt: null,
408
553
  implicitTypeImport: null,
@@ -516,6 +661,123 @@ const NOMINAL_TRAITS = {
516
661
  // Test functions the toolchain binds to a declared identifier by NAME
517
662
  // (fix #383); see GO_EXAMPLE_NAMES. null: no such convention.
518
663
  nameBoundTestFunctions: null,
664
+ // Methods a type declares to satisfy a standard-library contract it
665
+ // never names (interfaces satisfied implicitly): name -> parameter
666
+ // count. A zero textual use of one is not evidence that it is unused.
667
+ implicitStandardContracts: null,
668
+ // Is this project type a contract a value can satisfy WITHOUT naming it
669
+ // (assigned, passed or returned as the type with no implements clause)?
670
+ // null: types are satisfied by declaration only, or the language has
671
+ // its own model (Go's method sets). A type that satisfies such a
672
+ // contract by its member names keeps the members the contract requires.
673
+ structuralContract: null,
674
+ // Can another file import ANY module-level name of a module, declared
675
+ // or merely imported there, with no export syntax (Python)? Removing
676
+ // such a name, an import included, takes it from its importers.
677
+ moduleNamesImportable: false,
678
+ // Is a directory importable as a package without its package file
679
+ // (Python namespace packages)? Then deleting that file takes away the
680
+ // names it declared, not the package.
681
+ packageFileOptional: false,
682
+ // Module-level names that let a module supply names it does not write
683
+ // (Python: a module `__getattr__`, a rewritten package `__path__`). A
684
+ // package that declares one cannot be shown to lack a submodule.
685
+ moduleSupplyHooks: [],
686
+ // Is a member's type whatever the class's methods assign to it (Python
687
+ // instance attributes)? Then an assignment to a receiver member in any
688
+ // method is part of the class's contract.
689
+ memberTypesFromAssignments: false,
690
+ // Does an async function's anonymous future expose properties of its
691
+ // body to callers (Rust auto traits: Send, Sync)?
692
+ asyncReturnIsOpaque: false,
693
+ // Modifiers that let the compiler run a callable and hand callers its
694
+ // VALUE (C++ constexpr/consteval, Rust `const fn`): the body is then
695
+ // part of what a caller relies on. null: no such callables.
696
+ compileTimeCallableMarkers: null,
697
+ // Callable names the language supplies with no import and no
698
+ // declaration (builtins, globals): a bare call of one always means
699
+ // something. null: every callable name is declared or imported.
700
+ ambientCallables: null,
701
+ // Builtins among `ambientCallables` that never return (Python `exit`),
702
+ // and global objects whose every member returns (`console`).
703
+ ambientNeverCallables: null,
704
+ ambientReturningNamespaces: null,
705
+ // How a declaration says "a call of this never returns" (`never`,
706
+ // `NoReturn`): a type checker ends the caller's path at a call of one,
707
+ // and only at a declared one. []: the language has no such type; null:
708
+ // no return contract is read from a body in this language.
709
+ neverReturnTypes: null,
710
+ // Can a type checker decide a condition from the names in it (Python:
711
+ // `sys.version_info`, `sys.platform`, `TYPE_CHECKING`, constants its
712
+ // configuration defines)? Then a condition that guards part of what a
713
+ // body returns is part of it; elsewhere only a condition that names
714
+ // nothing (`while (true)`) is decided.
715
+ namedConditionsDecidable: false,
716
+ // Do files without module syntax share one global scope (classic
717
+ // JavaScript scripts)? Then a top-level name of one is visible in all.
718
+ scriptGlobalScope: false,
719
+ // Are the members of a class compared and enumerated by SHAPE
720
+ // (TypeScript)? Then the trait answers whether anything with the
721
+ // class's members is a value of it: `(classNode, ignoredLines) =>
722
+ // boolean`, true unless the class itself declares a private or
723
+ // protected instance member (members starting on `ignoredLines` left
724
+ // out). null: a class is its declaration, and its members are reached
725
+ // by name only.
726
+ classComparedByShape: null,
727
+ // How a class member takes part in the class's type: `(classNode,
728
+ // name, line) => { role: 'instance' | 'optional' | 'static', hidden }
729
+ // | null`; hidden: private, protected or `#`.
730
+ classMemberRole: null,
731
+ // Members of an object literal declared as a type, read from syntax:
732
+ // `(root, line) => { names, open } | null` (languages/javascript.js).
733
+ typedLiteralMembers: null,
734
+ // The interface whose members every object has (`Object`): a project
735
+ // that declares one adds members to every literal.
736
+ universalObjectInterface: null,
737
+ // Has the language's checker been told not to report a break, as its
738
+ // own scanner reads comments (`// @ts-ignore` above the line the break
739
+ // is reported on, `# type: ignore` on a line of the reported range, a
740
+ // rule turned off for the file)? `(site) => boolean` with site
741
+ // { lines, root, line, kind: 'arity' | 'import-name' | 'import-module'
742
+ // | 'undefined-name' | 'literal', name, most, memo }. A break at such a
743
+ // site is one the toolchain will not show: check lists it and does not
744
+ // block on it.
745
+ checkSuppressedAt: null,
746
+ // The tests a file declares, as its runner collects them:
747
+ // `(fileEntry, helpers) => { units, inheriting }` where a unit is
748
+ // { kind: 'test' | 'suite', name, suite: [names], line, endLine } plus
749
+ // what a selector needs (core/test-units.js). Null: the language's
750
+ // tests are not read, and nothing is said about them.
751
+ testUnits: null,
752
+ // (fileEntry, helpers) => boolean: does this file hold code the runner
753
+ // asks at run time that may leave tests out (a conftest hook, a TestMain).
754
+ testGate: null,
755
+ // `(fileEntry, projectDeclaresType) => { marked, bases }` or null: can
756
+ // a file hold test code, from the index alone (no tree)? Asked before
757
+ // a file whose name is no test file's is read for the tests in it.
758
+ testCodeGate: null,
759
+ // Which family of runners executes the language's tests; the family's
760
+ // manifests are the evidence a runner is named on. Null: none modeled.
761
+ testRunnerFamily: null,
762
+ // Modules whose import in a test file names its runner: `() => Map` of
763
+ // module name to runner id; null where an import says nothing of it.
764
+ testRunnerModules: null,
765
+ // What a module of the language exports under a name, as far as
766
+ // declaring tests goes: `(fileEntry, helpers, name) => binding | null`.
767
+ // A test file that takes its runner through a project module is read
768
+ // through it. Null: imports are not followed.
769
+ testExport: null,
770
+ // How the language's runners name a test file. A test-path file that
771
+ // declares no test and is not named like one is support code.
772
+ testFileNames: [],
773
+ // Is the import of `module` written on a line one the project's judge
774
+ // resolves (an import statement), not a call it never looks into?
775
+ // `(root, line, module) => boolean`; null: every import of the language
776
+ // is a statement.
777
+ checkedImportAt: null,
778
+ // Does a virtual member change what a type IS to existing code (C++: a
779
+ // class with one is no aggregate, so `T t{1, 2}` stops compiling)?
780
+ virtualMemberChangesShape: false,
519
781
  // A top-level type lives in a file named after it (fix #386, Java).
520
782
  typeNamedSourceFile: false,
521
783
  // Compiler-resolved doc references (fix #390, C# crefs).
@@ -543,6 +805,21 @@ const NOMINAL_TRAITS = {
543
805
  * lower-case letter is a suffix, not a member. Renaming the identifier or
544
806
  * member without the example fails vet ("refers to unknown field or method").
545
807
  */
808
+ // Go satisfies interfaces implicitly, so no `implements` edge exists for
809
+ // compiler/stdlib callbacks. A zero textual usage for one of these exact
810
+ // method shapes is not evidence of deadness (sort.Interface, http.Handler,
811
+ // io.Reader, encoding marshalers, database/sql contracts, errors helpers).
812
+ const GO_STANDARD_CONTRACT_METHODS = new Map([
813
+ ['Len', 0], ['Less', 2], ['Swap', 2], ['ServeHTTP', 2],
814
+ ['Error', 0], ['String', 0], ['Read', 1], ['Write', 1], ['Close', 0],
815
+ ['Seek', 2], ['ReadAt', 2], ['WriteAt', 2], ['ReadByte', 0],
816
+ ['WriteByte', 1], ['ReadRune', 0], ['UnreadByte', 0], ['UnreadRune', 0],
817
+ ['MarshalJSON', 0], ['UnmarshalJSON', 1], ['MarshalText', 0],
818
+ ['UnmarshalText', 1], ['MarshalBinary', 0], ['UnmarshalBinary', 1],
819
+ ['Scan', 1], ['Value', 0], ['LogValue', 0], ['Unwrap', 0],
820
+ ['Is', 1], ['As', 1],
821
+ ]);
822
+
546
823
  const GO_EXAMPLE_NAMES = {
547
824
  kind: 'go-example',
548
825
  prefix: 'Example',
@@ -581,14 +858,57 @@ const JS_PROTOCOL_MEMBERS = protocolMembers([
581
858
  { pattern: /^\[Symbol\.[A-Za-z]+\]$/, member: true },
582
859
  ]);
583
860
  const JS_REFLECTION_API = {
584
- hintPattern: /\bReflect\s*\.\s*(?:get|set|has|deleteProperty)\b|\beval\s*\(/,
861
+ hintPattern: /\b(?:Reflect|eval|Function)\b/,
585
862
  functions: [{ callee: /^(?:globalThis\.)?Reflect\.(?:get|set|has|deleteProperty)$/,
586
863
  nameArg: 1, receiverArg: 0, qualified: true }],
587
864
  computedMembers: true,
588
865
  namespaceLookups: { calls: /^eval$/ },
866
+ // Every other operation of the Reflect namespace (apply, construct,
867
+ // ownKeys, defineProperty, a decorator's Reflect.metadata).
868
+ unnamed: [{ callee: /^(?:globalThis\.)?Reflect\.\w+$/, qualified: true }],
869
+ // `eval` reached through the global object, and `new Function(code)`.
870
+ codeExecution: [
871
+ { callee: /^(?:globalThis|window|self)\.eval$/, qualified: true },
872
+ { construct: /^Function$/ },
873
+ ],
589
874
  family: 'javascript',
590
875
  };
591
876
 
877
+ // Python's builtin callables: names a bare call can mean with nothing
878
+ // declared or imported.
879
+ const PY_AMBIENT_CALLABLES = new Set([
880
+ 'abs', 'aiter', 'all', 'anext', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes',
881
+ 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict',
882
+ 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset',
883
+ 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance',
884
+ 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next',
885
+ 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed',
886
+ 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type',
887
+ 'vars', 'zip', '__import__',
888
+ ]);
889
+ // Global functions of the JavaScript runtimes (ECMAScript, Node, browsers).
890
+ const JS_AMBIENT_CALLABLES = new Set([
891
+ 'parseInt', 'parseFloat', 'isNaN', 'isFinite', 'encodeURI', 'encodeURIComponent', 'decodeURI',
892
+ 'decodeURIComponent', 'escape', 'unescape', 'eval', 'require', 'fetch', 'setTimeout', 'setInterval',
893
+ 'setImmediate', 'clearTimeout', 'clearInterval', 'clearImmediate', 'queueMicrotask', 'structuredClone',
894
+ 'requestAnimationFrame', 'cancelAnimationFrame', 'requestIdleCallback', 'alert', 'confirm', 'prompt',
895
+ 'atob', 'btoa', 'postMessage', 'importScripts', 'close', 'open', 'print', 'stop', 'focus', 'blur',
896
+ 'scroll', 'scrollTo', 'scrollBy', 'getComputedStyle', 'matchMedia', 'reportError', 'describe', 'it',
897
+ 'test', 'expect', 'beforeEach', 'afterEach', 'beforeAll', 'afterAll',
898
+ ]);
899
+
900
+ // Global objects of the JavaScript runtimes whose members all return.
901
+ const JS_RETURNING_NAMESPACES = new Set(['console', 'Math', 'JSON', 'Object', 'Array', 'Reflect', 'Number', 'String']);
902
+
903
+ // A TypeScript interface or object type is satisfied by shape: any class or
904
+ // object with its members is one.
905
+ const TS_STRUCTURAL_CONTRACT = typeDef => typeDef.type === 'interface' || typeDef.type === 'type';
906
+ // A Python class that lists Protocol among its bases is a protocol class:
907
+ // type checkers accept any object with its members (PEP 544). A class that
908
+ // only inherits from a protocol is an implementation, not a protocol. The
909
+ // parser records the fact (`protocolClass`), import aliases resolved.
910
+ const PY_STRUCTURAL_CONTRACT = typeDef => typeDef.protocolClass === true;
911
+
592
912
  // Language configurations
593
913
  const LANGUAGES = {
594
914
  javascript: {
@@ -599,9 +919,20 @@ const LANGUAGES = {
599
919
  treeSitterModule: () => require('tree-sitter-javascript'),
600
920
  traits: {
601
921
  ...STRUCTURAL_TRAITS,
922
+ testUnits: (fileEntry, helpers) => require('./javascript').testUnits(fileEntry, helpers),
923
+ testRunnerModules: () => require('./javascript').TEST_RUNNER_MODULES,
924
+ testExport: (fileEntry, helpers, name) => require('./javascript').testExport(fileEntry, helpers, name),
925
+ testRunnerFamily: 'javascript',
926
+ testFileNames: [/\.(test|spec)\.[cm]?[jt]sx?$/, /(^|\/)(test|spec)\.[cm]?[jt]sx?$/, /[-_]test\.[cm]?[jt]sx?$/, /(^|\/)test-[^/]*\.[cm]?[jt]sx?$/],
602
927
  selfParam: ['this'],
603
928
  reflectionApi: JS_REFLECTION_API,
604
929
  languageProtocolMember: JS_PROTOCOL_MEMBERS,
930
+ structuralContract: TS_STRUCTURAL_CONTRACT,
931
+ ambientCallables: JS_AMBIENT_CALLABLES,
932
+ ambientReturningNamespaces: JS_RETURNING_NAMESPACES,
933
+ neverReturnTypes: [],
934
+ checkedImportAt: (root, line, module) => require('./javascript').checkedImportAt(root, line, false, module),
935
+ scriptGlobalScope: true,
605
936
  storedPromises: true,
606
937
  knownAsyncGlobals: ['fetch'],
607
938
  lenientCallArity: true,
@@ -617,9 +948,25 @@ const LANGUAGES = {
617
948
  treeSitterModule: () => require('tree-sitter-typescript').typescript,
618
949
  traits: {
619
950
  ...STRUCTURAL_TRAITS,
951
+ testUnits: (fileEntry, helpers) => require('./javascript').testUnits(fileEntry, helpers),
952
+ testRunnerModules: () => require('./javascript').TEST_RUNNER_MODULES,
953
+ testExport: (fileEntry, helpers, name) => require('./javascript').testExport(fileEntry, helpers, name),
954
+ testRunnerFamily: 'javascript',
955
+ testFileNames: [/\.(test|spec)\.[cm]?[jt]sx?$/, /(^|\/)(test|spec)\.[cm]?[jt]sx?$/, /[-_]test\.[cm]?[jt]sx?$/, /(^|\/)test-[^/]*\.[cm]?[jt]sx?$/],
620
956
  selfParam: ['this'],
621
957
  reflectionApi: JS_REFLECTION_API,
622
958
  languageProtocolMember: JS_PROTOCOL_MEMBERS,
959
+ classComparedByShape: (classNode, ignoredLines) => !require('./javascript').classHasNominalMember(classNode, ignoredLines),
960
+ classMemberRole: (classNode, name, line) => require('./javascript').classMemberRole(classNode, name, line),
961
+ typedLiteralMembers: (root, line) => require('./javascript').typedLiteralMembers(root, line),
962
+ universalObjectInterface: 'Object',
963
+ checkSuppressedAt: site => require('./javascript').checkSuppressedAt(site),
964
+ checkedImportAt: (root, line, module) => require('./javascript').checkedImportAt(root, line, true, module),
965
+ structuralContract: TS_STRUCTURAL_CONTRACT,
966
+ ambientCallables: JS_AMBIENT_CALLABLES,
967
+ ambientReturningNamespaces: JS_RETURNING_NAMESPACES,
968
+ neverReturnTypes: ['never'],
969
+ scriptGlobalScope: true,
623
970
  storedPromises: true,
624
971
  knownAsyncGlobals: ['fetch'],
625
972
  testFileCandidates: (base, ext) => [`${base}.test${ext}`, `${base}.spec${ext}`, `${base}.test.ts`, `${base}.test.js`, `${base}.spec.ts`, `${base}.spec.js`],
@@ -634,9 +981,25 @@ const LANGUAGES = {
634
981
  treeSitterModule: () => require('tree-sitter-typescript').tsx,
635
982
  traits: {
636
983
  ...STRUCTURAL_TRAITS,
984
+ testUnits: (fileEntry, helpers) => require('./javascript').testUnits(fileEntry, helpers),
985
+ testRunnerModules: () => require('./javascript').TEST_RUNNER_MODULES,
986
+ testExport: (fileEntry, helpers, name) => require('./javascript').testExport(fileEntry, helpers, name),
987
+ testRunnerFamily: 'javascript',
988
+ testFileNames: [/\.(test|spec)\.[cm]?[jt]sx?$/, /(^|\/)(test|spec)\.[cm]?[jt]sx?$/, /[-_]test\.[cm]?[jt]sx?$/, /(^|\/)test-[^/]*\.[cm]?[jt]sx?$/],
637
989
  selfParam: ['this'],
638
990
  reflectionApi: JS_REFLECTION_API,
639
991
  languageProtocolMember: JS_PROTOCOL_MEMBERS,
992
+ classComparedByShape: (classNode, ignoredLines) => !require('./javascript').classHasNominalMember(classNode, ignoredLines),
993
+ classMemberRole: (classNode, name, line) => require('./javascript').classMemberRole(classNode, name, line),
994
+ typedLiteralMembers: (root, line) => require('./javascript').typedLiteralMembers(root, line),
995
+ universalObjectInterface: 'Object',
996
+ checkSuppressedAt: site => require('./javascript').checkSuppressedAt(site),
997
+ checkedImportAt: (root, line, module) => require('./javascript').checkedImportAt(root, line, true, module),
998
+ structuralContract: TS_STRUCTURAL_CONTRACT,
999
+ ambientCallables: JS_AMBIENT_CALLABLES,
1000
+ ambientReturningNamespaces: JS_RETURNING_NAMESPACES,
1001
+ neverReturnTypes: ['never'],
1002
+ scriptGlobalScope: true,
640
1003
  storedPromises: true,
641
1004
  knownAsyncGlobals: ['fetch'],
642
1005
  testFileCandidates: (base, ext) => [`${base}.test${ext}`, `${base}.spec${ext}`, `${base}.test.ts`, `${base}.test.js`, `${base}.spec.ts`, `${base}.spec.js`],
@@ -651,7 +1014,23 @@ const LANGUAGES = {
651
1014
  treeSitterModule: () => require('tree-sitter-python'),
652
1015
  traits: {
653
1016
  ...STRUCTURAL_TRAITS,
1017
+ testUnits: (fileEntry, helpers) => require('./python').testUnits(fileEntry, helpers),
1018
+ testRunnerFamily: 'python',
1019
+ testFileNames: [/^test_[^/]*\.py$/, /_test\.py$/],
1020
+ // `yield` in the body makes the callable a generator.
1021
+ callableKindFromBody: ['generator'],
654
1022
  selfParam: ['self', 'cls'],
1023
+ structuralContract: PY_STRUCTURAL_CONTRACT,
1024
+ moduleNamesImportable: true,
1025
+ moduleSupplyHooks: ['__getattr__', '__path__'],
1026
+ packageFileOptional: true,
1027
+ memberTypesFromAssignments: true,
1028
+ ambientCallables: PY_AMBIENT_CALLABLES,
1029
+ ambientNeverCallables: new Set(['exit', 'quit']),
1030
+ neverReturnTypes: ['NoReturn', 'Never'],
1031
+ namedConditionsDecidable: true,
1032
+ checkSuppressedAt: site => require('./python').checkSuppressedAt(site),
1033
+ checkedImportAt: (root, line, module) => require('./python').checkedImportAt(root, line, module),
655
1034
  // `cls(..)` in a classmethod (or an implicit one), `type(self)(..)`
656
1035
  // and `self.__class__(..)` in an instance method construct the
657
1036
  // method's class through its first parameter (fix #434).
@@ -677,8 +1056,10 @@ const LANGUAGES = {
677
1056
  classesCallableWithoutNew: true,
678
1057
  constructorInheritance: { order: 'c3', classNodes: ['class_definition'], headerField: 'superclasses', keywordNode: 'keyword_argument' },
679
1058
  constructorProtocol: { initializer: '__init__', allocator: '__new__', metaclass: 'metaclass', builtinRoot: 'object',
1059
+ metaclassMethods: ['__call__', '__new__', '__init__'], identityMembers: ['__class__', '__getattribute__', '__getattr__'], identityOverrides: ['__getattribute__', '__setattr__', '__delattr__'],
680
1060
  functionNode: 'function_definition', classNode: 'class_definition',
681
1061
  headerField: 'superclasses', keywordNode: 'keyword_argument' },
1062
+ contextEnterMethods: ['__enter__', '__aenter__'],
682
1063
  // Call sites bind by parameter name (f(x=1)); signatures carry
683
1064
  // keyword-only (`*`) and positional-only (`/`) markers (fix #281).
684
1065
  keywordArguments: true,
@@ -748,9 +1129,12 @@ const LANGUAGES = {
748
1129
  owners: ['Enum', 'IntEnum', 'StrEnum', 'Flag', 'IntFlag', 'ReprEnum'] },
749
1130
  ]),
750
1131
  reflectionApi: {
751
- hintPattern: /\b(?:getattr|setattr|hasattr|delattr|eval)\s*\(|\b(?:globals|vars)\s*\(\s*\)\s*\[/,
1132
+ hintPattern: /\b(?:getattr|setattr|hasattr|delattr|eval|exec|globals|vars)\b/,
752
1133
  functions: [{ callee: /^(?:getattr|setattr|hasattr|delattr)$/, nameArg: 1, receiverArg: 0 }],
753
1134
  namespaceLookups: { calls: /^eval$/, subscriptOf: /^(?:globals|vars)\(\)$/ },
1135
+ // `exec(code)` runs statements; it names nothing a lookup
1136
+ // could be matched against.
1137
+ codeExecution: [{ callee: /^exec$/ }],
754
1138
  },
755
1139
  testFileCandidates: (base, ext) => [`test_${base}.py`, `${base}_test.py`],
756
1140
  testDirs: ['tests'],
@@ -764,6 +1148,10 @@ const LANGUAGES = {
764
1148
  treeSitterModule: () => require('tree-sitter-go'),
765
1149
  traits: {
766
1150
  ...NOMINAL_TRAITS,
1151
+ testUnits: (fileEntry, helpers) => require('./go').testUnits(fileEntry, helpers),
1152
+ testGate: (fileEntry, helpers) => require('./go').testGate(fileEntry, helpers),
1153
+ testRunnerFamily: 'go',
1154
+ testFileNames: [/_test\.go$/],
767
1155
  selfParam: null,
768
1156
  packageScope: 'directory',
769
1157
  nameReferenceFamily: 'go',
@@ -778,9 +1166,13 @@ const LANGUAGES = {
778
1166
  members: [{ member: /^(?:MethodByName|FieldByName)$/, nameArg: 0 }],
779
1167
  membersOnly: true,
780
1168
  formatCalls: { 'fmt.Sprintf': 'percent' },
1169
+ // Every function of the reflect package, under whatever
1170
+ // name the file imports it.
1171
+ unnamed: [{ package: 'reflect' }],
781
1172
  },
782
1173
  testFileCandidates: (base, ext) => [`${base}_test.go`],
783
1174
  nameBoundTestFunctions: GO_EXAMPLE_NAMES,
1175
+ implicitStandardContracts: GO_STANDARD_CONTRACT_METHODS,
784
1176
  // One package-level name declared in files of one package under
785
1177
  // different build constraints is one item (fix #425).
786
1178
  conditionalDefinitions: 'build-constraint',
@@ -794,6 +1186,15 @@ const LANGUAGES = {
794
1186
  treeSitterModule: () => require('tree-sitter-rust'),
795
1187
  traits: {
796
1188
  ...NOMINAL_TRAITS,
1189
+ testUnits: (fileEntry, helpers) => require('./rust').testUnits(fileEntry, helpers),
1190
+ testRunnerFamily: 'rust',
1191
+ testFileNames: [/(^|\/)tests\/[^/]+\.rs$/],
1192
+ // `-> impl Trait` hides the type but leaks the value's auto traits.
1193
+ inferredReturnForms: ['opaque', 'evaluated'],
1194
+ // `async fn` returns an anonymous future whose auto traits
1195
+ // (Send, Sync) come from what the body holds across an await.
1196
+ asyncReturnIsOpaque: true,
1197
+ compileTimeCallableMarkers: ['const'],
797
1198
  selfParam: ['self', '&self', '&mut self', 'mut self'],
798
1199
  inherentMethodsPrecedeTraitImpls: true,
799
1200
  derefFieldAccess: true,
@@ -870,6 +1271,10 @@ const LANGUAGES = {
870
1271
  parseRecovery: () => require('./java').recoverTypeAnnotatedVarargs,
871
1272
  traits: {
872
1273
  ...NOMINAL_TRAITS,
1274
+ testUnits: (fileEntry, helpers) => require('./java').testUnits(fileEntry, helpers),
1275
+ testCodeGate: (fileEntry, projectDeclaresType) => require('./java').testCodeGate(fileEntry, projectDeclaresType),
1276
+ testRunnerFamily: 'java',
1277
+ testFileNames: [/^Test[^/]*\.java$/, /Tests?\.java$/, /TestCase\.java$/, /IT\.java$/],
873
1278
  // A method overrides/implements every supertype's same-signature
874
1279
  // member, an inherited one included (JLS 8.4.8) (fix #426).
875
1280
  memberFillsSupertypeSlots: true,
@@ -958,12 +1363,14 @@ const LANGUAGES = {
958
1363
  possibleViaExternal: { except: JAVA_LANG_NOT_SERIALIZABLE, shape: javaSerializationShape } },
959
1364
  ]),
960
1365
  reflectionApi: {
961
- hintPattern: /\b(?:getMethod|getDeclaredMethod|getField|getDeclaredField)\b/,
1366
+ hintPattern: /\b(?:getMethod|getDeclaredMethod|getField|getDeclaredField|forName)\b/,
962
1367
  members: [{ member: /^(?:getMethod|getDeclaredMethod|getField|getDeclaredField)$/, nameArg: 0 }],
963
1368
  membersOnly: true,
964
1369
  formatCalls: { 'String.format': 'percent' },
965
1370
  selfTypeCalls: ['getClass'],
966
1371
  typeLiteralNodes: ['class_literal'],
1372
+ // A class loaded by its name.
1373
+ unnamed: [{ callee: /^(?:java\.lang\.)?Class\.forName$/, qualified: true }],
967
1374
  },
968
1375
  bareCallReachesMethods: true,
969
1376
  testFileCandidates: (base, ext) => [`${base}Test.java`, `${base}Tests.java`, `${base}TestCase.java`],
@@ -1007,6 +1414,12 @@ const LANGUAGES = {
1007
1414
  treeSitterModule: () => require('tree-sitter-cpp'),
1008
1415
  traits: {
1009
1416
  ...NOMINAL_TRAITS,
1417
+ // `auto` / `decltype(auto)` return types are deduced from the body.
1418
+ // 'instantiated': a template's body is checked against each
1419
+ // caller's arguments.
1420
+ inferredReturnForms: ['placeholder', 'instantiated', 'evaluated'],
1421
+ virtualMemberChangesShape: true,
1422
+ compileTimeCallableMarkers: ['constexpr', 'consteval'],
1010
1423
  // An override overrides every base's virtual of its signature; an
1011
1424
  // inherited member never implements another base's pure virtual
1012
1425
  // (fix #426).
@@ -1076,6 +1489,10 @@ const LANGUAGES = {
1076
1489
  treeSitterModule: () => require('tree-sitter-c-sharp'),
1077
1490
  traits: {
1078
1491
  ...NOMINAL_TRAITS,
1492
+ testUnits: (fileEntry, helpers) => require('./csharp').testUnits(fileEntry, helpers),
1493
+ testCodeGate: (fileEntry, projectDeclaresType) => require('./csharp').testCodeGate(fileEntry, projectDeclaresType),
1494
+ testRunnerFamily: 'dotnet',
1495
+ testFileNames: [/Tests?\.cs$/],
1079
1496
  // Interface mapping takes inherited members (C# spec 18.6.5); a
1080
1497
  // `new` member hides the inherited one, starting a slot of its
1081
1498
  // own (fix #426).
@@ -1110,6 +1527,7 @@ const LANGUAGES = {
1110
1527
  standardPathRoots: ['System'],
1111
1528
  conditionalDefinitions: 'preprocessor',
1112
1529
  typeNameScoping: 'namespace-usings',
1530
+ platformTypeForms: { nullable: 'System.Nullable', tuple: 'System.ValueTuple' },
1113
1531
  constructorArgumentNodes: { delegation: { nodeType: 'constructor_initializer', argsNodeType: 'argument_list' } },
1114
1532
  genericArityIsIdentity: true,
1115
1533
  typeArgumentsFromArgumentsOnly: true,