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.
- package/.claude/skills/ucn/SKILL.md +35 -12
- package/.claude/skills/ucn/references/commands.md +18 -14
- package/.claude/skills/ucn/references/resolution-rules.md +4 -0
- package/.claude/skills/ucn/references/trust-contract.md +4 -4
- package/CHANGELOG.md +474 -0
- package/README.md +69 -29
- package/cli/flags.js +184 -0
- package/cli/index.js +137 -324
- package/core/account.js +44 -87
- package/core/analysis.js +273 -107
- package/core/ast-analysis.js +2 -0
- package/core/bridge.js +14 -0
- package/core/cache.js +101 -16
- package/core/callers.js +352 -70
- package/core/capture.js +331 -0
- package/core/change-kinds.js +888 -0
- package/core/check.js +1117 -139
- package/core/command-contracts.js +7 -6
- package/core/constructed-class.js +1195 -0
- package/core/contract-membership.js +142 -0
- package/core/deadcode.js +362 -84
- package/core/deletion.js +401 -0
- package/core/discovery.js +104 -9
- package/core/entrypoints.js +12 -6
- package/core/evidence-bands.js +68 -0
- package/core/evidence-bands.json +44 -0
- package/core/execute.js +172 -161
- package/core/hot-summary.js +241 -0
- package/core/index-ir.js +3 -1
- package/core/ir.js +5 -1
- package/core/member-signatures.js +789 -0
- package/core/output/analysis-ext.js +20 -10
- package/core/output/analysis.js +98 -60
- package/core/output/check.js +98 -37
- package/core/output/doctor.js +34 -1
- package/core/output/find.js +2 -1
- package/core/output/lines.js +63 -3
- package/core/output/public.js +29 -11
- package/core/output/refactoring.js +32 -0
- package/core/output/reporting.js +15 -2
- package/core/output/search.js +11 -2
- package/core/output/tracing.js +35 -7
- package/core/output-budget.js +124 -57
- package/core/parallel-build.js +3 -3
- package/core/project.js +106 -23
- package/core/provenance-type.js +12 -5
- package/core/public-command.js +35 -9
- package/core/python-modules.js +6 -0
- package/core/reflection.js +151 -23
- package/core/registry.js +623 -72
- package/core/reporting.js +69 -34
- package/core/review-items.js +75 -0
- package/core/search.js +89 -128
- package/core/shared.js +0 -45
- package/core/snapshot.js +350 -0
- package/core/source-universe.js +707 -0
- package/core/test-units.js +3624 -0
- package/core/tracing.js +150 -96
- package/core/verify.js +27 -11
- package/languages/adapter.js +8 -3
- package/languages/c-family.js +12 -0
- package/languages/csharp.js +634 -0
- package/languages/go.js +120 -0
- package/languages/index.js +422 -4
- package/languages/java.js +712 -0
- package/languages/javascript.js +1460 -2
- package/languages/lexical-scope.js +68 -0
- package/languages/python.js +1672 -1
- package/languages/rust.js +91 -0
- package/mcp/server.js +44 -110
- package/package.json +10 -5
package/languages/index.js
CHANGED
|
@@ -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.
|
|
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: /\
|
|
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
|
|
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,
|