ucn 5.5.3 → 5.6.1

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 (77) hide show
  1. package/.claude/skills/ucn/SKILL.md +37 -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 +485 -0
  6. package/README.md +66 -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 +274 -108
  11. package/core/ast-analysis.js +2 -0
  12. package/core/bridge.js +14 -0
  13. package/core/cache.js +103 -16
  14. package/core/call-fit.js +130 -0
  15. package/core/callers.js +353 -71
  16. package/core/capture.js +363 -0
  17. package/core/change-kinds.js +1107 -0
  18. package/core/check.js +1150 -139
  19. package/core/command-contracts.js +8 -7
  20. package/core/constructed-class.js +1195 -0
  21. package/core/contract-membership.js +142 -0
  22. package/core/deadcode.js +455 -106
  23. package/core/deletion.js +421 -0
  24. package/core/discovery.js +104 -9
  25. package/core/entrypoint-toml.js +110 -0
  26. package/core/entrypoints.js +12 -6
  27. package/core/evidence-bands.js +68 -0
  28. package/core/evidence-bands.json +44 -0
  29. package/core/execute.js +172 -161
  30. package/core/hot-summary.js +241 -0
  31. package/core/index-ir.js +5 -3
  32. package/core/ir.js +6 -2
  33. package/core/member-signatures.js +789 -0
  34. package/core/outgoing-check.js +116 -0
  35. package/core/output/analysis-ext.js +20 -10
  36. package/core/output/analysis.js +98 -60
  37. package/core/output/check.js +101 -37
  38. package/core/output/doctor.js +34 -1
  39. package/core/output/find.js +2 -1
  40. package/core/output/lines.js +63 -3
  41. package/core/output/public.js +29 -11
  42. package/core/output/refactoring.js +32 -0
  43. package/core/output/reporting.js +19 -2
  44. package/core/output/search.js +14 -2
  45. package/core/output/tracing.js +36 -8
  46. package/core/output-budget.js +146 -61
  47. package/core/parallel-build.js +3 -3
  48. package/core/project.js +106 -23
  49. package/core/provenance-type.js +12 -5
  50. package/core/public-command.js +35 -9
  51. package/core/python-binding-identity.js +707 -0
  52. package/core/python-modules.js +6 -0
  53. package/core/reflection.js +248 -31
  54. package/core/registry.js +623 -72
  55. package/core/reporting.js +69 -34
  56. package/core/review-items.js +75 -0
  57. package/core/runtime-entrypoints.js +159 -0
  58. package/core/search.js +148 -164
  59. package/core/shared.js +0 -45
  60. package/core/snapshot.js +350 -0
  61. package/core/source-universe.js +707 -0
  62. package/core/test-units.js +3698 -0
  63. package/core/tracing.js +270 -658
  64. package/core/verify.js +63 -22
  65. package/languages/adapter.js +8 -3
  66. package/languages/c-family.js +12 -0
  67. package/languages/csharp.js +634 -0
  68. package/languages/go.js +120 -0
  69. package/languages/index.js +466 -4
  70. package/languages/java.js +712 -0
  71. package/languages/javascript.js +1498 -6
  72. package/languages/lexical-scope.js +68 -0
  73. package/languages/python.js +1708 -3
  74. package/languages/rust.js +209 -104
  75. package/languages/static-js.js +88 -0
  76. package/mcp/server.js +44 -110
  77. package/package.json +11 -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,
@@ -131,6 +139,7 @@ const STRUCTURAL_TRAITS = {
131
139
  physicalCallTokenSyntax: true,
132
140
  scopeAlternativeBindings: false,
133
141
  nameReferenceFamily: 'js',
142
+ discardIdentifierNames: [],
134
143
  staticValueImportSyntax: null,
135
144
  implicitEnumCaseLabels: false,
136
145
  valuePatternConstants: false,
@@ -154,6 +163,10 @@ const STRUCTURAL_TRAITS = {
154
163
  // 'namespace-usings' (C#: enclosing namespaces, then using directives,
155
164
  // global usings and project-file <Using> items), or null.
156
165
  typeNameScoping: null,
166
+ // The platform's generic types a language writes with a syntax of its
167
+ // own: { nullable, tuple }, each the type's qualified name (C#:
168
+ // `System.Nullable<T>` is `T?`). Two spellings of one type.
169
+ platformTypeForms: null,
157
170
  typeNameSourceCanonical: null,
158
171
  typeNameOwnersAt: null,
159
172
  implementationOwnerSyntax: null,
@@ -184,6 +197,13 @@ const STRUCTURAL_TRAITS = {
184
197
  memberHidingModifier: null,
185
198
  virtualMemberModifiers: null,
186
199
  hasArityOverloads: false,
200
+ // Bounded literal proofs for changed project calls; absent means unknown.
201
+ checkLiteralArguments: null,
202
+ checkDirectiveComment: null,
203
+ checkFileDirectiveComment: null,
204
+ checkDirectiveTarget: null,
205
+ checkDirectiveBarrier: null,
206
+ checkTypedComment: null,
187
207
  userDefinedConversions: null,
188
208
  overloadPhases: null,
189
209
  overloadFileSymbols: false,
@@ -256,6 +276,9 @@ const STRUCTURAL_TRAITS = {
256
276
  constructorArgumentNodes: { delegation: { nodeType: 'call_expression', argsField: 'arguments' } },
257
277
  functionalTypeConstruction: false,
258
278
  constructorInheritance: { order: 'single', classNodes: ['class_declaration', 'class'], headerNode: 'class_heritage' },
279
+ // Methods whose result a context-manager statement binds (`with X() as
280
+ // v` binds `X().__enter__()`), or null when the language has none.
281
+ contextEnterMethods: null,
259
282
  implicitBaseConstruction: null,
260
283
  // Whether a constructor delegation is spelled by a keyword (`this(..)`,
261
284
  // `super(..)`, `base(..)`) rather than by the type's name (C++
@@ -303,6 +326,123 @@ const STRUCTURAL_TRAITS = {
303
326
  // text dependencies; no other language checks a test function's name
304
327
  // against a declaration.
305
328
  nameBoundTestFunctions: null,
329
+ // Methods a type declares to satisfy a standard-library contract it
330
+ // never names (interfaces satisfied implicitly): name -> parameter
331
+ // count. A zero textual use of one is not evidence that it is unused.
332
+ implicitStandardContracts: null,
333
+ // Is this project type a contract a value can satisfy WITHOUT naming it
334
+ // (assigned, passed or returned as the type with no implements clause)?
335
+ // null: types are satisfied by declaration only, or the language has
336
+ // its own model (Go's method sets). A type that satisfies such a
337
+ // contract by its member names keeps the members the contract requires.
338
+ structuralContract: null,
339
+ // Can another file import ANY module-level name of a module, declared
340
+ // or merely imported there, with no export syntax (Python)? Removing
341
+ // such a name, an import included, takes it from its importers.
342
+ moduleNamesImportable: false,
343
+ // Is a directory importable as a package without its package file
344
+ // (Python namespace packages)? Then deleting that file takes away the
345
+ // names it declared, not the package.
346
+ packageFileOptional: false,
347
+ // Module-level names that let a module supply names it does not write
348
+ // (Python: a module `__getattr__`, a rewritten package `__path__`). A
349
+ // package that declares one cannot be shown to lack a submodule.
350
+ moduleSupplyHooks: [],
351
+ // Is a member's type whatever the class's methods assign to it (Python
352
+ // instance attributes)? Then an assignment to a receiver member in any
353
+ // method is part of the class's contract.
354
+ memberTypesFromAssignments: false,
355
+ // Does an async function's anonymous future expose properties of its
356
+ // body to callers (Rust auto traits: Send, Sync)?
357
+ asyncReturnIsOpaque: false,
358
+ // Modifiers that let the compiler run a callable and hand callers its
359
+ // VALUE (C++ constexpr/consteval, Rust `const fn`): the body is then
360
+ // part of what a caller relies on. null: no such callables.
361
+ compileTimeCallableMarkers: null,
362
+ // Callable names the language supplies with no import and no
363
+ // declaration (builtins, globals): a bare call of one always means
364
+ // something. null: every callable name is declared or imported.
365
+ ambientCallables: null,
366
+ // Builtins among `ambientCallables` that never return (Python `exit`),
367
+ // and global objects whose every member returns (`console`).
368
+ ambientNeverCallables: null,
369
+ ambientReturningNamespaces: null,
370
+ // How a declaration says "a call of this never returns" (`never`,
371
+ // `NoReturn`): a type checker ends the caller's path at a call of one,
372
+ // and only at a declared one. []: the language has no such type; null:
373
+ // no return contract is read from a body in this language.
374
+ neverReturnTypes: null,
375
+ // Can a type checker decide a condition from the names in it (Python:
376
+ // `sys.version_info`, `sys.platform`, `TYPE_CHECKING`, constants its
377
+ // configuration defines)? Then a condition that guards part of what a
378
+ // body returns is part of it; elsewhere only a condition that names
379
+ // nothing (`while (true)`) is decided.
380
+ namedConditionsDecidable: false,
381
+ // Do files without module syntax share one global scope (classic
382
+ // JavaScript scripts)? Then a top-level name of one is visible in all.
383
+ scriptGlobalScope: false,
384
+ // Are the members of a class compared and enumerated by SHAPE
385
+ // (TypeScript)? Then the trait answers whether anything with the
386
+ // class's members is a value of it: `(classNode, ignoredLines) =>
387
+ // boolean`, true unless the class itself declares a private or
388
+ // protected instance member (members starting on `ignoredLines` left
389
+ // out). null: a class is its declaration, and its members are reached
390
+ // by name only.
391
+ classComparedByShape: null,
392
+ // How a class member takes part in the class's type: `(classNode,
393
+ // name, line) => { role: 'instance' | 'optional' | 'static', hidden }
394
+ // | null`; hidden: private, protected or `#`.
395
+ classMemberRole: null,
396
+ // Members of an object literal declared as a type, read from syntax:
397
+ // `(root, line) => { names, open } | null` (languages/javascript.js).
398
+ typedLiteralMembers: null,
399
+ // The interface whose members every object has (`Object`): a project
400
+ // that declares one adds members to every literal.
401
+ universalObjectInterface: null,
402
+ // Has the language's checker been told not to report a break, as its
403
+ // own scanner reads comments (`// @ts-ignore` above the line the break
404
+ // is reported on, `# type: ignore` on a line of the reported range, a
405
+ // rule turned off for the file)? `(site) => boolean` with site
406
+ // { lines, root, line, kind: 'arity' | 'import-name' | 'import-module'
407
+ // | 'undefined-name' | 'literal', name, most, memo }. A break at such a
408
+ // site is one the toolchain will not show: check lists it and does not
409
+ // block on it.
410
+ checkSuppressedAt: null,
411
+ // The tests a file declares, as its runner collects them:
412
+ // `(fileEntry, helpers) => { units, inheriting }` where a unit is
413
+ // { kind: 'test' | 'suite', name, suite: [names], line, endLine } plus
414
+ // what a selector needs (core/test-units.js). Null: the language's
415
+ // tests are not read, and nothing is said about them.
416
+ testUnits: null,
417
+ // (fileEntry, helpers) => boolean: does this file hold code the runner
418
+ // asks at run time that may leave tests out (a conftest hook, a TestMain).
419
+ testGate: null,
420
+ // `(fileEntry, projectDeclaresType) => { marked, bases }` or null: can
421
+ // a file hold test code, from the index alone (no tree)? Asked before
422
+ // a file whose name is no test file's is read for the tests in it.
423
+ testCodeGate: null,
424
+ // Which family of runners executes the language's tests; the family's
425
+ // manifests are the evidence a runner is named on. Null: none modeled.
426
+ testRunnerFamily: null,
427
+ // Modules whose import in a test file names its runner: `() => Map` of
428
+ // module name to runner id; null where an import says nothing of it.
429
+ testRunnerModules: null,
430
+ // What a module of the language exports under a name, as far as
431
+ // declaring tests goes: `(fileEntry, helpers, name) => binding | null`.
432
+ // A test file that takes its runner through a project module is read
433
+ // through it. Null: imports are not followed.
434
+ testExport: null,
435
+ // How the language's runners name a test file. A test-path file that
436
+ // declares no test and is not named like one is support code.
437
+ testFileNames: [],
438
+ // Is the import of `module` written on a line one the project's judge
439
+ // resolves (an import statement), not a call it never looks into?
440
+ // `(root, line, module) => boolean`; null: every import of the language
441
+ // is a statement.
442
+ checkedImportAt: null,
443
+ // Does a virtual member change what a type IS to existing code (C++: a
444
+ // class with one is no aggregate, so `T t{1, 2}` stops compiling)?
445
+ virtualMemberChangesShape: false,
306
446
  // Whether a top-level type is declared in a source file named after it
307
447
  // (fix #386): javac requires `public class Widget` in Widget.java, so a
308
448
  // type rename renames that file too.
@@ -350,7 +490,15 @@ const STRUCTURAL_TRAITS = {
350
490
  // class literals. `hintPattern` locates vocabulary spellings whose
351
491
  // enclosing call nodes are inspected (the AST decides); `namespaceLookups` are module-namespace lookups by
352
492
  // name (eval, globals()[k]). `family` groups languages sharing one
353
- // runtime. null = no runtime reflection.
493
+ // runtime. `unnamed` are reflective calls that carry no member name and
494
+ // `codeExecution` calls and constructions that run code built at
495
+ // runtime: both are counted per file with the rest of the vocabulary
496
+ // (fileEntry.reflectionUses / evalUses, what `repo` and the completeness
497
+ // footer disclose) and never matched against names. Such a rule is
498
+ // `{ callee }` (the callee as written; `qualified` when it has a
499
+ // receiver), `{ package }` (a call qualified by a local name the file's
500
+ // imports bind to that module) or `{ construct }` (the constructed
501
+ // class). null = no runtime reflection.
354
502
  reflectionApi: null,
355
503
  // Members every class inherits from the implicit root supertype, keyed by
356
504
  // name with their parameter count (Java Object.toString/equals/...,
@@ -371,6 +519,9 @@ const STRUCTURAL_TRAITS = {
371
519
  };
372
520
  const NOMINAL_TRAITS = {
373
521
  typeSystem: 'nominal',
522
+ // See STRUCTURAL_TRAITS: a declared return type is the whole contract.
523
+ inferredReturnForms: [],
524
+ callableKindFromBody: [],
374
525
  instanceAttributesShadowMethods: false,
375
526
  inherentMethodsPrecedeTraitImpls: false,
376
527
  derefFieldAccess: false,
@@ -381,6 +532,7 @@ const NOMINAL_TRAITS = {
381
532
  hasConstructors: false,
382
533
  fixedConstructorName: null,
383
534
  constructorInheritance: null,
535
+ contextEnterMethods: null,
384
536
  implicitBaseConstruction: null,
385
537
  keywordConstructorDelegation: false,
386
538
  constructorUsesAreTypeReferences: false,
@@ -393,6 +545,7 @@ const NOMINAL_TRAITS = {
393
545
  physicalCallTokenSyntax: true,
394
546
  scopeAlternativeBindings: false,
395
547
  nameReferenceFamily: null,
548
+ discardIdentifierNames: [],
396
549
  staticValueImportSyntax: null,
397
550
  implicitEnumCaseLabels: false,
398
551
  valuePatternConstants: false,
@@ -403,6 +556,7 @@ const NOMINAL_TRAITS = {
403
556
  moduleTypeIdentity: false,
404
557
  standardPathRoots: [],
405
558
  typeNameScoping: null,
559
+ platformTypeForms: null,
406
560
  typeNameSourceCanonical: null,
407
561
  typeNameOwnersAt: null,
408
562
  implicitTypeImport: null,
@@ -444,6 +598,13 @@ const NOMINAL_TRAITS = {
444
598
  // the caller contract: a pinned overload is only confirmed when the call
445
599
  // site provably binds it.
446
600
  hasArityOverloads: false,
601
+ // Bounded literal proofs for changed project calls; absent means unknown.
602
+ checkLiteralArguments: null,
603
+ checkDirectiveComment: null,
604
+ checkFileDirectiveComment: null,
605
+ checkDirectiveTarget: null,
606
+ checkDirectiveBarrier: null,
607
+ checkTypedComment: null,
447
608
  // User-defined conversions keep otherwise incompatible argument types
448
609
  // possible; selecting an overload still needs a positive conversion proof.
449
610
  userDefinedConversions: null,
@@ -516,6 +677,123 @@ const NOMINAL_TRAITS = {
516
677
  // Test functions the toolchain binds to a declared identifier by NAME
517
678
  // (fix #383); see GO_EXAMPLE_NAMES. null: no such convention.
518
679
  nameBoundTestFunctions: null,
680
+ // Methods a type declares to satisfy a standard-library contract it
681
+ // never names (interfaces satisfied implicitly): name -> parameter
682
+ // count. A zero textual use of one is not evidence that it is unused.
683
+ implicitStandardContracts: null,
684
+ // Is this project type a contract a value can satisfy WITHOUT naming it
685
+ // (assigned, passed or returned as the type with no implements clause)?
686
+ // null: types are satisfied by declaration only, or the language has
687
+ // its own model (Go's method sets). A type that satisfies such a
688
+ // contract by its member names keeps the members the contract requires.
689
+ structuralContract: null,
690
+ // Can another file import ANY module-level name of a module, declared
691
+ // or merely imported there, with no export syntax (Python)? Removing
692
+ // such a name, an import included, takes it from its importers.
693
+ moduleNamesImportable: false,
694
+ // Is a directory importable as a package without its package file
695
+ // (Python namespace packages)? Then deleting that file takes away the
696
+ // names it declared, not the package.
697
+ packageFileOptional: false,
698
+ // Module-level names that let a module supply names it does not write
699
+ // (Python: a module `__getattr__`, a rewritten package `__path__`). A
700
+ // package that declares one cannot be shown to lack a submodule.
701
+ moduleSupplyHooks: [],
702
+ // Is a member's type whatever the class's methods assign to it (Python
703
+ // instance attributes)? Then an assignment to a receiver member in any
704
+ // method is part of the class's contract.
705
+ memberTypesFromAssignments: false,
706
+ // Does an async function's anonymous future expose properties of its
707
+ // body to callers (Rust auto traits: Send, Sync)?
708
+ asyncReturnIsOpaque: false,
709
+ // Modifiers that let the compiler run a callable and hand callers its
710
+ // VALUE (C++ constexpr/consteval, Rust `const fn`): the body is then
711
+ // part of what a caller relies on. null: no such callables.
712
+ compileTimeCallableMarkers: null,
713
+ // Callable names the language supplies with no import and no
714
+ // declaration (builtins, globals): a bare call of one always means
715
+ // something. null: every callable name is declared or imported.
716
+ ambientCallables: null,
717
+ // Builtins among `ambientCallables` that never return (Python `exit`),
718
+ // and global objects whose every member returns (`console`).
719
+ ambientNeverCallables: null,
720
+ ambientReturningNamespaces: null,
721
+ // How a declaration says "a call of this never returns" (`never`,
722
+ // `NoReturn`): a type checker ends the caller's path at a call of one,
723
+ // and only at a declared one. []: the language has no such type; null:
724
+ // no return contract is read from a body in this language.
725
+ neverReturnTypes: null,
726
+ // Can a type checker decide a condition from the names in it (Python:
727
+ // `sys.version_info`, `sys.platform`, `TYPE_CHECKING`, constants its
728
+ // configuration defines)? Then a condition that guards part of what a
729
+ // body returns is part of it; elsewhere only a condition that names
730
+ // nothing (`while (true)`) is decided.
731
+ namedConditionsDecidable: false,
732
+ // Do files without module syntax share one global scope (classic
733
+ // JavaScript scripts)? Then a top-level name of one is visible in all.
734
+ scriptGlobalScope: false,
735
+ // Are the members of a class compared and enumerated by SHAPE
736
+ // (TypeScript)? Then the trait answers whether anything with the
737
+ // class's members is a value of it: `(classNode, ignoredLines) =>
738
+ // boolean`, true unless the class itself declares a private or
739
+ // protected instance member (members starting on `ignoredLines` left
740
+ // out). null: a class is its declaration, and its members are reached
741
+ // by name only.
742
+ classComparedByShape: null,
743
+ // How a class member takes part in the class's type: `(classNode,
744
+ // name, line) => { role: 'instance' | 'optional' | 'static', hidden }
745
+ // | null`; hidden: private, protected or `#`.
746
+ classMemberRole: null,
747
+ // Members of an object literal declared as a type, read from syntax:
748
+ // `(root, line) => { names, open } | null` (languages/javascript.js).
749
+ typedLiteralMembers: null,
750
+ // The interface whose members every object has (`Object`): a project
751
+ // that declares one adds members to every literal.
752
+ universalObjectInterface: null,
753
+ // Has the language's checker been told not to report a break, as its
754
+ // own scanner reads comments (`// @ts-ignore` above the line the break
755
+ // is reported on, `# type: ignore` on a line of the reported range, a
756
+ // rule turned off for the file)? `(site) => boolean` with site
757
+ // { lines, root, line, kind: 'arity' | 'import-name' | 'import-module'
758
+ // | 'undefined-name' | 'literal', name, most, memo }. A break at such a
759
+ // site is one the toolchain will not show: check lists it and does not
760
+ // block on it.
761
+ checkSuppressedAt: null,
762
+ // The tests a file declares, as its runner collects them:
763
+ // `(fileEntry, helpers) => { units, inheriting }` where a unit is
764
+ // { kind: 'test' | 'suite', name, suite: [names], line, endLine } plus
765
+ // what a selector needs (core/test-units.js). Null: the language's
766
+ // tests are not read, and nothing is said about them.
767
+ testUnits: null,
768
+ // (fileEntry, helpers) => boolean: does this file hold code the runner
769
+ // asks at run time that may leave tests out (a conftest hook, a TestMain).
770
+ testGate: null,
771
+ // `(fileEntry, projectDeclaresType) => { marked, bases }` or null: can
772
+ // a file hold test code, from the index alone (no tree)? Asked before
773
+ // a file whose name is no test file's is read for the tests in it.
774
+ testCodeGate: null,
775
+ // Which family of runners executes the language's tests; the family's
776
+ // manifests are the evidence a runner is named on. Null: none modeled.
777
+ testRunnerFamily: null,
778
+ // Modules whose import in a test file names its runner: `() => Map` of
779
+ // module name to runner id; null where an import says nothing of it.
780
+ testRunnerModules: null,
781
+ // What a module of the language exports under a name, as far as
782
+ // declaring tests goes: `(fileEntry, helpers, name) => binding | null`.
783
+ // A test file that takes its runner through a project module is read
784
+ // through it. Null: imports are not followed.
785
+ testExport: null,
786
+ // How the language's runners name a test file. A test-path file that
787
+ // declares no test and is not named like one is support code.
788
+ testFileNames: [],
789
+ // Is the import of `module` written on a line one the project's judge
790
+ // resolves (an import statement), not a call it never looks into?
791
+ // `(root, line, module) => boolean`; null: every import of the language
792
+ // is a statement.
793
+ checkedImportAt: null,
794
+ // Does a virtual member change what a type IS to existing code (C++: a
795
+ // class with one is no aggregate, so `T t{1, 2}` stops compiling)?
796
+ virtualMemberChangesShape: false,
519
797
  // A top-level type lives in a file named after it (fix #386, Java).
520
798
  typeNamedSourceFile: false,
521
799
  // Compiler-resolved doc references (fix #390, C# crefs).
@@ -543,6 +821,21 @@ const NOMINAL_TRAITS = {
543
821
  * lower-case letter is a suffix, not a member. Renaming the identifier or
544
822
  * member without the example fails vet ("refers to unknown field or method").
545
823
  */
824
+ // Go satisfies interfaces implicitly, so no `implements` edge exists for
825
+ // compiler/stdlib callbacks. A zero textual usage for one of these exact
826
+ // method shapes is not evidence of deadness (sort.Interface, http.Handler,
827
+ // io.Reader, encoding marshalers, database/sql contracts, errors helpers).
828
+ const GO_STANDARD_CONTRACT_METHODS = new Map([
829
+ ['Len', 0], ['Less', 2], ['Swap', 2], ['ServeHTTP', 2],
830
+ ['Error', 0], ['String', 0], ['Read', 1], ['Write', 1], ['Close', 0],
831
+ ['Seek', 2], ['ReadAt', 2], ['WriteAt', 2], ['ReadByte', 0],
832
+ ['WriteByte', 1], ['ReadRune', 0], ['UnreadByte', 0], ['UnreadRune', 0],
833
+ ['MarshalJSON', 0], ['UnmarshalJSON', 1], ['MarshalText', 0],
834
+ ['UnmarshalText', 1], ['MarshalBinary', 0], ['UnmarshalBinary', 1],
835
+ ['Scan', 1], ['Value', 0], ['LogValue', 0], ['Unwrap', 0],
836
+ ['Is', 1], ['As', 1],
837
+ ]);
838
+
546
839
  const GO_EXAMPLE_NAMES = {
547
840
  kind: 'go-example',
548
841
  prefix: 'Example',
@@ -581,14 +874,57 @@ const JS_PROTOCOL_MEMBERS = protocolMembers([
581
874
  { pattern: /^\[Symbol\.[A-Za-z]+\]$/, member: true },
582
875
  ]);
583
876
  const JS_REFLECTION_API = {
584
- hintPattern: /\bReflect\s*\.\s*(?:get|set|has|deleteProperty)\b|\beval\s*\(/,
877
+ hintPattern: /\b(?:Reflect|eval|Function)\b/,
585
878
  functions: [{ callee: /^(?:globalThis\.)?Reflect\.(?:get|set|has|deleteProperty)$/,
586
879
  nameArg: 1, receiverArg: 0, qualified: true }],
587
880
  computedMembers: true,
588
881
  namespaceLookups: { calls: /^eval$/ },
882
+ // Every other operation of the Reflect namespace (apply, construct,
883
+ // ownKeys, defineProperty, a decorator's Reflect.metadata).
884
+ unnamed: [{ callee: /^(?:globalThis\.)?Reflect\.\w+$/, qualified: true }],
885
+ // `eval` reached through the global object, and `new Function(code)`.
886
+ codeExecution: [
887
+ { callee: /^(?:globalThis|window|self)\.eval$/, qualified: true },
888
+ { construct: /^Function$/ },
889
+ ],
589
890
  family: 'javascript',
590
891
  };
591
892
 
893
+ // Python's builtin callables: names a bare call can mean with nothing
894
+ // declared or imported.
895
+ const PY_AMBIENT_CALLABLES = new Set([
896
+ 'abs', 'aiter', 'all', 'anext', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes',
897
+ 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict',
898
+ 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset',
899
+ 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance',
900
+ 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next',
901
+ 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed',
902
+ 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type',
903
+ 'vars', 'zip', '__import__',
904
+ ]);
905
+ // Global functions of the JavaScript runtimes (ECMAScript, Node, browsers).
906
+ const JS_AMBIENT_CALLABLES = new Set([
907
+ 'parseInt', 'parseFloat', 'isNaN', 'isFinite', 'encodeURI', 'encodeURIComponent', 'decodeURI',
908
+ 'decodeURIComponent', 'escape', 'unescape', 'eval', 'require', 'fetch', 'setTimeout', 'setInterval',
909
+ 'setImmediate', 'clearTimeout', 'clearInterval', 'clearImmediate', 'queueMicrotask', 'structuredClone',
910
+ 'requestAnimationFrame', 'cancelAnimationFrame', 'requestIdleCallback', 'alert', 'confirm', 'prompt',
911
+ 'atob', 'btoa', 'postMessage', 'importScripts', 'close', 'open', 'print', 'stop', 'focus', 'blur',
912
+ 'scroll', 'scrollTo', 'scrollBy', 'getComputedStyle', 'matchMedia', 'reportError', 'describe', 'it',
913
+ 'test', 'expect', 'beforeEach', 'afterEach', 'beforeAll', 'afterAll',
914
+ ]);
915
+
916
+ // Global objects of the JavaScript runtimes whose members all return.
917
+ const JS_RETURNING_NAMESPACES = new Set(['console', 'Math', 'JSON', 'Object', 'Array', 'Reflect', 'Number', 'String']);
918
+
919
+ // A TypeScript interface or object type is satisfied by shape: any class or
920
+ // object with its members is one.
921
+ const TS_STRUCTURAL_CONTRACT = typeDef => typeDef.type === 'interface' || typeDef.type === 'type';
922
+ // A Python class that lists Protocol among its bases is a protocol class:
923
+ // type checkers accept any object with its members (PEP 544). A class that
924
+ // only inherits from a protocol is an implementation, not a protocol. The
925
+ // parser records the fact (`protocolClass`), import aliases resolved.
926
+ const PY_STRUCTURAL_CONTRACT = typeDef => typeDef.protocolClass === true;
927
+
592
928
  // Language configurations
593
929
  const LANGUAGES = {
594
930
  javascript: {
@@ -599,9 +935,25 @@ const LANGUAGES = {
599
935
  treeSitterModule: () => require('tree-sitter-javascript'),
600
936
  traits: {
601
937
  ...STRUCTURAL_TRAITS,
938
+ checkTypedComment: text => /@ts-check\b|@(?:param|type|returns?)\s*\{/.test(text),
939
+ checkDirectiveComment: text => require('./javascript').checkDirectiveComment(text),
940
+ checkFileDirectiveComment: text => require('./javascript').checkFileDirectiveComment(text),
941
+ checkDirectiveTarget: 'next-line',
942
+ checkDirectiveBarrier: text => text.startsWith('/*'),
943
+ testUnits: (fileEntry, helpers) => require('./javascript').testUnits(fileEntry, helpers),
944
+ testRunnerModules: () => require('./javascript').TEST_RUNNER_MODULES,
945
+ testExport: (fileEntry, helpers, name) => require('./javascript').testExport(fileEntry, helpers, name),
946
+ testRunnerFamily: 'javascript',
947
+ testFileNames: [/\.(test|spec)\.[cm]?[jt]sx?$/, /(^|\/)(test|spec)\.[cm]?[jt]sx?$/, /[-_]test\.[cm]?[jt]sx?$/, /(^|\/)test-[^/]*\.[cm]?[jt]sx?$/],
602
948
  selfParam: ['this'],
603
949
  reflectionApi: JS_REFLECTION_API,
604
950
  languageProtocolMember: JS_PROTOCOL_MEMBERS,
951
+ structuralContract: TS_STRUCTURAL_CONTRACT,
952
+ ambientCallables: JS_AMBIENT_CALLABLES,
953
+ ambientReturningNamespaces: JS_RETURNING_NAMESPACES,
954
+ neverReturnTypes: [],
955
+ checkedImportAt: (root, line, module) => require('./javascript').checkedImportAt(root, line, false, module),
956
+ scriptGlobalScope: true,
605
957
  storedPromises: true,
606
958
  knownAsyncGlobals: ['fetch'],
607
959
  lenientCallArity: true,
@@ -617,9 +969,30 @@ const LANGUAGES = {
617
969
  treeSitterModule: () => require('tree-sitter-typescript').typescript,
618
970
  traits: {
619
971
  ...STRUCTURAL_TRAITS,
972
+ checkLiteralArguments: { smallInteger: ['number'], string: ['string'], boolean: ['boolean'] },
973
+ checkDirectiveComment: text => require('./javascript').checkDirectiveComment(text),
974
+ checkFileDirectiveComment: text => require('./javascript').checkFileDirectiveComment(text),
975
+ checkDirectiveTarget: 'next-line',
976
+ checkDirectiveBarrier: text => text.startsWith('/*'),
977
+ testUnits: (fileEntry, helpers) => require('./javascript').testUnits(fileEntry, helpers),
978
+ testRunnerModules: () => require('./javascript').TEST_RUNNER_MODULES,
979
+ testExport: (fileEntry, helpers, name) => require('./javascript').testExport(fileEntry, helpers, name),
980
+ testRunnerFamily: 'javascript',
981
+ testFileNames: [/\.(test|spec)\.[cm]?[jt]sx?$/, /(^|\/)(test|spec)\.[cm]?[jt]sx?$/, /[-_]test\.[cm]?[jt]sx?$/, /(^|\/)test-[^/]*\.[cm]?[jt]sx?$/],
620
982
  selfParam: ['this'],
621
983
  reflectionApi: JS_REFLECTION_API,
622
984
  languageProtocolMember: JS_PROTOCOL_MEMBERS,
985
+ classComparedByShape: (classNode, ignoredLines) => !require('./javascript').classHasNominalMember(classNode, ignoredLines),
986
+ classMemberRole: (classNode, name, line) => require('./javascript').classMemberRole(classNode, name, line),
987
+ typedLiteralMembers: (root, line) => require('./javascript').typedLiteralMembers(root, line),
988
+ universalObjectInterface: 'Object',
989
+ checkSuppressedAt: site => require('./javascript').checkSuppressedAt(site),
990
+ checkedImportAt: (root, line, module) => require('./javascript').checkedImportAt(root, line, true, module),
991
+ structuralContract: TS_STRUCTURAL_CONTRACT,
992
+ ambientCallables: JS_AMBIENT_CALLABLES,
993
+ ambientReturningNamespaces: JS_RETURNING_NAMESPACES,
994
+ neverReturnTypes: ['never'],
995
+ scriptGlobalScope: true,
623
996
  storedPromises: true,
624
997
  knownAsyncGlobals: ['fetch'],
625
998
  testFileCandidates: (base, ext) => [`${base}.test${ext}`, `${base}.spec${ext}`, `${base}.test.ts`, `${base}.test.js`, `${base}.spec.ts`, `${base}.spec.js`],
@@ -634,9 +1007,30 @@ const LANGUAGES = {
634
1007
  treeSitterModule: () => require('tree-sitter-typescript').tsx,
635
1008
  traits: {
636
1009
  ...STRUCTURAL_TRAITS,
1010
+ checkLiteralArguments: { smallInteger: ['number'], string: ['string'], boolean: ['boolean'] },
1011
+ checkDirectiveComment: text => require('./javascript').checkDirectiveComment(text),
1012
+ checkFileDirectiveComment: text => require('./javascript').checkFileDirectiveComment(text),
1013
+ checkDirectiveTarget: 'next-line',
1014
+ checkDirectiveBarrier: text => text.startsWith('/*'),
1015
+ testUnits: (fileEntry, helpers) => require('./javascript').testUnits(fileEntry, helpers),
1016
+ testRunnerModules: () => require('./javascript').TEST_RUNNER_MODULES,
1017
+ testExport: (fileEntry, helpers, name) => require('./javascript').testExport(fileEntry, helpers, name),
1018
+ testRunnerFamily: 'javascript',
1019
+ testFileNames: [/\.(test|spec)\.[cm]?[jt]sx?$/, /(^|\/)(test|spec)\.[cm]?[jt]sx?$/, /[-_]test\.[cm]?[jt]sx?$/, /(^|\/)test-[^/]*\.[cm]?[jt]sx?$/],
637
1020
  selfParam: ['this'],
638
1021
  reflectionApi: JS_REFLECTION_API,
639
1022
  languageProtocolMember: JS_PROTOCOL_MEMBERS,
1023
+ classComparedByShape: (classNode, ignoredLines) => !require('./javascript').classHasNominalMember(classNode, ignoredLines),
1024
+ classMemberRole: (classNode, name, line) => require('./javascript').classMemberRole(classNode, name, line),
1025
+ typedLiteralMembers: (root, line) => require('./javascript').typedLiteralMembers(root, line),
1026
+ universalObjectInterface: 'Object',
1027
+ checkSuppressedAt: site => require('./javascript').checkSuppressedAt(site),
1028
+ checkedImportAt: (root, line, module) => require('./javascript').checkedImportAt(root, line, true, module),
1029
+ structuralContract: TS_STRUCTURAL_CONTRACT,
1030
+ ambientCallables: JS_AMBIENT_CALLABLES,
1031
+ ambientReturningNamespaces: JS_RETURNING_NAMESPACES,
1032
+ neverReturnTypes: ['never'],
1033
+ scriptGlobalScope: true,
640
1034
  storedPromises: true,
641
1035
  knownAsyncGlobals: ['fetch'],
642
1036
  testFileCandidates: (base, ext) => [`${base}.test${ext}`, `${base}.spec${ext}`, `${base}.test.ts`, `${base}.test.js`, `${base}.spec.ts`, `${base}.spec.js`],
@@ -651,7 +1045,26 @@ const LANGUAGES = {
651
1045
  treeSitterModule: () => require('tree-sitter-python'),
652
1046
  traits: {
653
1047
  ...STRUCTURAL_TRAITS,
1048
+ checkLiteralArguments: { smallInteger: ['int', 'float'], string: ['str'], boolean: ['bool'] },
1049
+ checkDirectiveComment: text => require('./python').checkDirectiveComment(text),
1050
+ checkFileDirectiveComment: text => require('./python').checkFileDirectiveComment(text),
1051
+ testUnits: (fileEntry, helpers) => require('./python').testUnits(fileEntry, helpers),
1052
+ testRunnerFamily: 'python',
1053
+ testFileNames: [/^test_[^/]*\.py$/, /_test\.py$/],
1054
+ // `yield` in the body makes the callable a generator.
1055
+ callableKindFromBody: ['generator'],
654
1056
  selfParam: ['self', 'cls'],
1057
+ structuralContract: PY_STRUCTURAL_CONTRACT,
1058
+ moduleNamesImportable: true,
1059
+ moduleSupplyHooks: ['__getattr__', '__path__'],
1060
+ packageFileOptional: true,
1061
+ memberTypesFromAssignments: true,
1062
+ ambientCallables: PY_AMBIENT_CALLABLES,
1063
+ ambientNeverCallables: new Set(['exit', 'quit']),
1064
+ neverReturnTypes: ['NoReturn', 'Never'],
1065
+ namedConditionsDecidable: true,
1066
+ checkSuppressedAt: site => require('./python').checkSuppressedAt(site),
1067
+ checkedImportAt: (root, line, module) => require('./python').checkedImportAt(root, line, module),
655
1068
  // `cls(..)` in a classmethod (or an implicit one), `type(self)(..)`
656
1069
  // and `self.__class__(..)` in an instance method construct the
657
1070
  // method's class through its first parameter (fix #434).
@@ -677,8 +1090,10 @@ const LANGUAGES = {
677
1090
  classesCallableWithoutNew: true,
678
1091
  constructorInheritance: { order: 'c3', classNodes: ['class_definition'], headerField: 'superclasses', keywordNode: 'keyword_argument' },
679
1092
  constructorProtocol: { initializer: '__init__', allocator: '__new__', metaclass: 'metaclass', builtinRoot: 'object',
1093
+ metaclassMethods: ['__call__', '__new__', '__init__'], identityMembers: ['__class__', '__getattribute__', '__getattr__'], identityOverrides: ['__getattribute__', '__setattr__', '__delattr__'],
680
1094
  functionNode: 'function_definition', classNode: 'class_definition',
681
1095
  headerField: 'superclasses', keywordNode: 'keyword_argument' },
1096
+ contextEnterMethods: ['__enter__', '__aenter__'],
682
1097
  // Call sites bind by parameter name (f(x=1)); signatures carry
683
1098
  // keyword-only (`*`) and positional-only (`/`) markers (fix #281).
684
1099
  keywordArguments: true,
@@ -748,9 +1163,13 @@ const LANGUAGES = {
748
1163
  owners: ['Enum', 'IntEnum', 'StrEnum', 'Flag', 'IntFlag', 'ReprEnum'] },
749
1164
  ]),
750
1165
  reflectionApi: {
751
- hintPattern: /\b(?:getattr|setattr|hasattr|delattr|eval)\s*\(|\b(?:globals|vars)\s*\(\s*\)\s*\[/,
1166
+ pythonBindingIdentity: true,
1167
+ hintPattern: /\b(?:getattr|setattr|hasattr|delattr|eval|exec|globals|vars|patch|MonkeyPatch)\b/,
752
1168
  functions: [{ callee: /^(?:getattr|setattr|hasattr|delattr)$/, nameArg: 1, receiverArg: 0 }],
753
1169
  namespaceLookups: { calls: /^eval$/, subscriptOf: /^(?:globals|vars)\(\)$/ },
1170
+ // `exec(code)` runs statements; it names nothing a lookup
1171
+ // could be matched against.
1172
+ codeExecution: [{ callee: /^exec$/ }],
754
1173
  },
755
1174
  testFileCandidates: (base, ext) => [`test_${base}.py`, `${base}_test.py`],
756
1175
  testDirs: ['tests'],
@@ -764,9 +1183,15 @@ const LANGUAGES = {
764
1183
  treeSitterModule: () => require('tree-sitter-go'),
765
1184
  traits: {
766
1185
  ...NOMINAL_TRAITS,
1186
+ checkLiteralArguments: { smallInteger: ['int', 'int8', 'int16', 'int32', 'int64', 'uint', 'uint8', 'uint16', 'uint32', 'uint64', 'uintptr', 'float32', 'float64'], string: ['string'], boolean: ['bool'] },
1187
+ testUnits: (fileEntry, helpers) => require('./go').testUnits(fileEntry, helpers),
1188
+ testGate: (fileEntry, helpers) => require('./go').testGate(fileEntry, helpers),
1189
+ testRunnerFamily: 'go',
1190
+ testFileNames: [/_test\.go$/],
767
1191
  selfParam: null,
768
1192
  packageScope: 'directory',
769
1193
  nameReferenceFamily: 'go',
1194
+ discardIdentifierNames: ['_'],
770
1195
  closedQueryBodies: ['function_declaration', 'method_declaration', 'func_literal'],
771
1196
  hasReceiverPackageCalls: true,
772
1197
  exportVisibility: 'capitalization',
@@ -778,9 +1203,13 @@ const LANGUAGES = {
778
1203
  members: [{ member: /^(?:MethodByName|FieldByName)$/, nameArg: 0 }],
779
1204
  membersOnly: true,
780
1205
  formatCalls: { 'fmt.Sprintf': 'percent' },
1206
+ // Every function of the reflect package, under whatever
1207
+ // name the file imports it.
1208
+ unnamed: [{ package: 'reflect' }],
781
1209
  },
782
1210
  testFileCandidates: (base, ext) => [`${base}_test.go`],
783
1211
  nameBoundTestFunctions: GO_EXAMPLE_NAMES,
1212
+ implicitStandardContracts: GO_STANDARD_CONTRACT_METHODS,
784
1213
  // One package-level name declared in files of one package under
785
1214
  // different build constraints is one item (fix #425).
786
1215
  conditionalDefinitions: 'build-constraint',
@@ -794,6 +1223,16 @@ const LANGUAGES = {
794
1223
  treeSitterModule: () => require('tree-sitter-rust'),
795
1224
  traits: {
796
1225
  ...NOMINAL_TRAITS,
1226
+ checkLiteralArguments: { smallInteger: ['i8', 'i16', 'i32', 'i64', 'i128', 'isize', 'u8', 'u16', 'u32', 'u64', 'u128', 'usize'], string: ['&str'], boolean: ['bool'] },
1227
+ testUnits: (fileEntry, helpers) => require('./rust').testUnits(fileEntry, helpers),
1228
+ testRunnerFamily: 'rust',
1229
+ testFileNames: [/(^|\/)tests\/[^/]+\.rs$/],
1230
+ // `-> impl Trait` hides the type but leaks the value's auto traits.
1231
+ inferredReturnForms: ['opaque', 'evaluated'],
1232
+ // `async fn` returns an anonymous future whose auto traits
1233
+ // (Send, Sync) come from what the body holds across an await.
1234
+ asyncReturnIsOpaque: true,
1235
+ compileTimeCallableMarkers: ['const'],
797
1236
  selfParam: ['self', '&self', '&mut self', 'mut self'],
798
1237
  inherentMethodsPrecedeTraitImpls: true,
799
1238
  derefFieldAccess: true,
@@ -870,6 +1309,10 @@ const LANGUAGES = {
870
1309
  parseRecovery: () => require('./java').recoverTypeAnnotatedVarargs,
871
1310
  traits: {
872
1311
  ...NOMINAL_TRAITS,
1312
+ testUnits: (fileEntry, helpers) => require('./java').testUnits(fileEntry, helpers),
1313
+ testCodeGate: (fileEntry, projectDeclaresType) => require('./java').testCodeGate(fileEntry, projectDeclaresType),
1314
+ testRunnerFamily: 'java',
1315
+ testFileNames: [/^Test[^/]*\.java$/, /Tests?\.java$/, /TestCase\.java$/, /IT\.java$/],
873
1316
  // A method overrides/implements every supertype's same-signature
874
1317
  // member, an inherited one included (JLS 8.4.8) (fix #426).
875
1318
  memberFillsSupertypeSlots: true,
@@ -958,12 +1401,14 @@ const LANGUAGES = {
958
1401
  possibleViaExternal: { except: JAVA_LANG_NOT_SERIALIZABLE, shape: javaSerializationShape } },
959
1402
  ]),
960
1403
  reflectionApi: {
961
- hintPattern: /\b(?:getMethod|getDeclaredMethod|getField|getDeclaredField)\b/,
1404
+ hintPattern: /\b(?:getMethod|getDeclaredMethod|getField|getDeclaredField|forName)\b/,
962
1405
  members: [{ member: /^(?:getMethod|getDeclaredMethod|getField|getDeclaredField)$/, nameArg: 0 }],
963
1406
  membersOnly: true,
964
1407
  formatCalls: { 'String.format': 'percent' },
965
1408
  selfTypeCalls: ['getClass'],
966
1409
  typeLiteralNodes: ['class_literal'],
1410
+ // A class loaded by its name.
1411
+ unnamed: [{ callee: /^(?:java\.lang\.)?Class\.forName$/, qualified: true }],
967
1412
  },
968
1413
  bareCallReachesMethods: true,
969
1414
  testFileCandidates: (base, ext) => [`${base}Test.java`, `${base}Tests.java`, `${base}TestCase.java`],
@@ -977,6 +1422,7 @@ const LANGUAGES = {
977
1422
  treeSitterModule: () => require('tree-sitter-c'),
978
1423
  traits: {
979
1424
  ...NOMINAL_TRAITS,
1425
+ checkLiteralArguments: { smallInteger: ['int', 'short', 'long', 'long long', 'unsigned', 'unsigned int', 'unsigned short', 'unsigned long', 'unsigned long long', 'float', 'double'] },
980
1426
  selfParam: null,
981
1427
  packageScope: 'file',
982
1428
  nameReferenceFamily: 'c',
@@ -1007,6 +1453,12 @@ const LANGUAGES = {
1007
1453
  treeSitterModule: () => require('tree-sitter-cpp'),
1008
1454
  traits: {
1009
1455
  ...NOMINAL_TRAITS,
1456
+ // `auto` / `decltype(auto)` return types are deduced from the body.
1457
+ // 'instantiated': a template's body is checked against each
1458
+ // caller's arguments.
1459
+ inferredReturnForms: ['placeholder', 'instantiated', 'evaluated'],
1460
+ virtualMemberChangesShape: true,
1461
+ compileTimeCallableMarkers: ['constexpr', 'consteval'],
1010
1462
  // An override overrides every base's virtual of its signature; an
1011
1463
  // inherited member never implements another base's pure virtual
1012
1464
  // (fix #426).
@@ -1076,6 +1528,10 @@ const LANGUAGES = {
1076
1528
  treeSitterModule: () => require('tree-sitter-c-sharp'),
1077
1529
  traits: {
1078
1530
  ...NOMINAL_TRAITS,
1531
+ testUnits: (fileEntry, helpers) => require('./csharp').testUnits(fileEntry, helpers),
1532
+ testCodeGate: (fileEntry, projectDeclaresType) => require('./csharp').testCodeGate(fileEntry, projectDeclaresType),
1533
+ testRunnerFamily: 'dotnet',
1534
+ testFileNames: [/Tests?\.cs$/],
1079
1535
  // Interface mapping takes inherited members (C# spec 18.6.5); a
1080
1536
  // `new` member hides the inherited one, starting a slot of its
1081
1537
  // own (fix #426).
@@ -1110,6 +1566,7 @@ const LANGUAGES = {
1110
1566
  standardPathRoots: ['System'],
1111
1567
  conditionalDefinitions: 'preprocessor',
1112
1568
  typeNameScoping: 'namespace-usings',
1569
+ platformTypeForms: { nullable: 'System.Nullable', tuple: 'System.ValueTuple' },
1113
1570
  constructorArgumentNodes: { delegation: { nodeType: 'constructor_initializer', argsNodeType: 'argument_list' } },
1114
1571
  genericArityIsIdentity: true,
1115
1572
  typeArgumentsFromArgumentsOnly: true,
@@ -1178,6 +1635,11 @@ const LANGUAGES = {
1178
1635
  treeSitterModule: () => require('tree-sitter-html'),
1179
1636
  traits: {
1180
1637
  ...STRUCTURAL_TRAITS,
1638
+ checkTypedComment: text => /@ts-check\b|@(?:param|type|returns?)\s*\{/.test(text),
1639
+ checkDirectiveComment: text => require('./javascript').checkDirectiveComment(text),
1640
+ checkFileDirectiveComment: text => require('./javascript').checkFileDirectiveComment(text),
1641
+ checkDirectiveTarget: 'next-line',
1642
+ checkDirectiveBarrier: text => text.startsWith('/*'),
1181
1643
  lenientCallArity: true,
1182
1644
  // Embedded scripts supply their own parse trees.
1183
1645
  physicalCallTokenSyntax: false,