gitnexus 1.6.13-rc.52 → 1.6.13-rc.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_shared/scope-resolution/types.d.ts +1 -1
- package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
- package/dist/core/ingestion/languages/python/builtin-descriptors.d.ts +19 -0
- package/dist/core/ingestion/languages/python/builtin-descriptors.js +314 -0
- package/dist/core/ingestion/languages/python/index.d.ts +5 -7
- package/dist/core/ingestion/languages/python/index.js +5 -7
- package/dist/core/ingestion/languages/python/interpret.js +3 -1
- package/dist/core/ingestion/languages/python/receiver-binding.d.ts +12 -0
- package/dist/core/ingestion/languages/python/receiver-binding.js +112 -21
- package/dist/core/ingestion/languages/python/scope-resolver.js +1 -0
- package/dist/core/ingestion/languages/python/subtype-dispatch.js +4 -13
- package/dist/core/ingestion/method-extractors/configs/python.js +5 -2
- package/dist/core/ingestion/scope-extractor.js +5 -0
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +4 -0
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +1 -1
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +22 -3
- package/dist/storage/parse-cache.js +8 -1
- package/package.json +1 -1
|
@@ -595,7 +595,7 @@ export interface TypeRef {
|
|
|
595
595
|
readonly declaredSpelling?: string;
|
|
596
596
|
/** Anchor for resolving `rawName` — the scope where the annotation/inference was written. */
|
|
597
597
|
readonly declaredAtScope: ScopeId;
|
|
598
|
-
readonly source: 'annotation' | 'parameter-annotation' | 'return-annotation' | 'self' | 'assignment-inferred' | 'constructor-inferred' | 'receiver-propagated';
|
|
598
|
+
readonly source: 'annotation' | 'parameter-annotation' | 'return-annotation' | 'self' | 'decorator-unknown' | 'assignment-inferred' | 'constructor-inferred' | 'receiver-propagated';
|
|
599
599
|
/** Reserved for V2+: generic type arguments (`List<User>` → `[TypeRef('User')]`). V1 ignores. */
|
|
600
600
|
readonly typeArgs?: readonly TypeRef[];
|
|
601
601
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,4FAA4F;AAC5F,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAE7B,0DAA0D;AAC1D,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC;AAE3B;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,WAAW,GACX,OAAO,GACP,UAAU,GACV,OAAO,GACP,YAAY,GACZ,QAAQ,CAAC;AAIb,qFAAqF;AACrF,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,6FAA6F;IAC7F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,gCAAgC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAI7D;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,YAAY,GAAG,kBAAkB,GAAG;IAC9C;;0DAEsD;IACtD,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;CACpC,CAAC;AAEF,KAAK,kBAAkB;AACrB;;;;;;;GAOG;AACD;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;mEAI+D;IAC/D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;IAC5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiDG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IAC9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AACH;;;;;;GAMG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;IAC5D;;8EAE0E;IAC1E,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;+DAE2D;IAC3D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,iDAAiD;IACjD,QAAQ,CAAC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IAC9C,iDAAiD;IACjD,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AACH;;;;;;;;;;GAUG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,wFAAwF;IACxF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;sDACkD;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;kDAC8C;IAC9C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACvC;AACH;;;;;;;;;;GAUG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iCAAiC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,uFAAuF;IACvF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;wFACoF;IACpF,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;;sDAQkD;IAClD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACvC;AACH;;;;;;;;;;;;;;;;;GAiBG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;;;2DAOuD;IACvD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AACH;;;;;;;;;GASG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iFAAiF;IACjF,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;8EAC0E;IAC1E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACvC;AACH;;;;;;;;;;;;;;;;GAgBG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;4EAEwE;IACxE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACvC;AACH;;;;;;;;;;GAUG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;uEAEmE;IACnE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CACvC,CAAC;AAEN;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,wEAAwE;IACxE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;uDACmD;IACnD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC;AAMrC;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;CAC1C;AAED,4DAA4D;AAC5D,MAAM,WAAW,QAAQ;IACvB,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;iEAC6D;IAC7D,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAID;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,2DAA2D;IAC3D,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,wEAAwE;IACxE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC;IAC7B,QAAQ,CAAC,IAAI,EACT,OAAO,GACP,OAAO,GACP,WAAW,GACX,mBAAmB,GACnB,UAAU,GACV,oBAAoB,GACpB,kBAAkB,GAClB,aAAa,CAAC;IAClB,oFAAoF;IACpF,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC;CACpC;AAID;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC;IAC5E,sGAAsG;IACtG,QAAQ,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,sBAAsB,CAAC;CAC9C;AAID;;;;;;;;GAQG;AACH,MAAM,WAAW,OAAO;IACtB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,6FAA6F;IAC7F,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,MAAM,EACX,YAAY,GACZ,sBAAsB,GACtB,mBAAmB,GACnB,MAAM,GACN,qBAAqB,GACrB,sBAAsB,GACtB,qBAAqB,CAAC;IAC1B,iGAAiG;IACjG,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CACxC;AAID;;;;;GAKG;AACH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC,CAAC;IAE9D,yFAAyF;IACzF,QAAQ,CAAC,SAAS,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAEhD;;kDAE8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAC;IAExC,8FAA8F;IAC9F,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEpD;;uEAEmE;IACnE,QAAQ,CAAC,YAAY,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAE5C;;;;;;;;;;;gEAW4D;IAC5D,QAAQ,CAAC,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC9C;AAID;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EACT,OAAO,GACP,aAAa,GACb,QAAQ,GACR,cAAc,GACd,aAAa,GACb,YAAY,GACZ,aAAa,GACb,aAAa,GACb,kBAAkB,GAClB,2BAA2B,CAAC;IAChC,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAC/B,+CAA+C;IAC/C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACjD,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CACpC;AAID;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,IAAI,EACT,MAAM,GACN,MAAM,GACN,OAAO,GACP,gBAAgB,GAChB,UAAU,GACV,YAAY,GACZ,WAAW,GACX,OAAO,CAAC;IACZ;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B;;;8DAG0D;IAC1D,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;CAClD;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC,CAAC;IACnE,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAC,CAAC;CAChE;AAID;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC;AAE1C;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,aAAa,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7C,wDAAwD;IACxD,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC;IACzC,QAAQ,CAAC,sBAAsB,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC5D,gEAAgE;IAChE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;gFAE4E;IAC5E,QAAQ,CAAC,gBAAgB,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACvD"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decide whether a method decorator names one of Python's builtin descriptor
|
|
3
|
+
* types, following CPython's evaluation of the decorator expression.
|
|
4
|
+
*
|
|
5
|
+
* A decorator in a class body is evaluated with LOAD_NAME: the class
|
|
6
|
+
* namespace first, then module globals, then builtins, each as bound at the
|
|
7
|
+
* moment the `def` statement runs. Aliases, dotted names and decorator calls
|
|
8
|
+
* have no known descriptor contract without import resolution, so only bare
|
|
9
|
+
* spellings qualify.
|
|
10
|
+
*/
|
|
11
|
+
import type { SyntaxNode } from '../../utils/ast-helpers.js';
|
|
12
|
+
declare const BUILTIN_DESCRIPTOR_NAMES: readonly ['classmethod', 'staticmethod', 'property'];
|
|
13
|
+
export type BuiltinDescriptor = (typeof BUILTIN_DESCRIPTOR_NAMES)[number];
|
|
14
|
+
/** Decorator expressions, outermost first. Tree-sitter keeps a trailing
|
|
15
|
+
* comment inside the decorator node, so read the expression child only. */
|
|
16
|
+
export declare function decoratorNames(fnNode: SyntaxNode): string[];
|
|
17
|
+
/** Does `expression` denote a builtin descriptor type (or `kind`) at `fnNode`? */
|
|
18
|
+
export declare function isBuiltinDescriptor(fnNode: SyntaxNode, expression: string, kind?: BuiltinDescriptor): boolean;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decide whether a method decorator names one of Python's builtin descriptor
|
|
3
|
+
* types, following CPython's evaluation of the decorator expression.
|
|
4
|
+
*
|
|
5
|
+
* A decorator in a class body is evaluated with LOAD_NAME: the class
|
|
6
|
+
* namespace first, then module globals, then builtins, each as bound at the
|
|
7
|
+
* moment the `def` statement runs. Aliases, dotted names and decorator calls
|
|
8
|
+
* have no known descriptor contract without import resolution, so only bare
|
|
9
|
+
* spellings qualify.
|
|
10
|
+
*/
|
|
11
|
+
const BUILTIN_DESCRIPTOR_NAMES = ['classmethod', 'staticmethod', 'property'];
|
|
12
|
+
const BUILTIN_DESCRIPTORS = new Set(BUILTIN_DESCRIPTOR_NAMES);
|
|
13
|
+
/** Decorator expressions, outermost first. Tree-sitter keeps a trailing
|
|
14
|
+
* comment inside the decorator node, so read the expression child only. */
|
|
15
|
+
export function decoratorNames(fnNode) {
|
|
16
|
+
const parent = fnNode.parent;
|
|
17
|
+
if (parent === null || parent.type !== 'decorated_definition')
|
|
18
|
+
return [];
|
|
19
|
+
const names = [];
|
|
20
|
+
for (const child of parent.namedChildren) {
|
|
21
|
+
if (child.type !== 'decorator')
|
|
22
|
+
continue;
|
|
23
|
+
// An empty name matches nothing, so a malformed decorator stays unknown.
|
|
24
|
+
names.push(child.namedChildren.find((part) => part.type !== 'comment')?.text ?? '');
|
|
25
|
+
}
|
|
26
|
+
return names;
|
|
27
|
+
}
|
|
28
|
+
/** Does `expression` denote a builtin descriptor type (or `kind`) at `fnNode`? */
|
|
29
|
+
export function isBuiltinDescriptor(fnNode, expression, kind) {
|
|
30
|
+
if (kind === undefined ? !BUILTIN_DESCRIPTORS.has(expression) : expression !== kind)
|
|
31
|
+
return false;
|
|
32
|
+
// Decorators are evaluated as the `def` statement runs, so its wrapper is the
|
|
33
|
+
// use site. No statement can rebind the name between stacked decorators.
|
|
34
|
+
const use = fnNode.parent?.type === 'decorated_definition' ? fnNode.parent : fnNode;
|
|
35
|
+
return lookupName(descriptorBindings(fnNode).get(expression) ?? [], use) !== 'shadow';
|
|
36
|
+
}
|
|
37
|
+
const FUNCTION_SCOPES = new Set(['function_definition', 'lambda']);
|
|
38
|
+
const COMPREHENSIONS = new Set([
|
|
39
|
+
'list_comprehension',
|
|
40
|
+
'set_comprehension',
|
|
41
|
+
'dictionary_comprehension',
|
|
42
|
+
'generator_expression',
|
|
43
|
+
]);
|
|
44
|
+
const TARGET_WRAPPERS = new Set([
|
|
45
|
+
'pattern_list',
|
|
46
|
+
'tuple_pattern',
|
|
47
|
+
'list_pattern',
|
|
48
|
+
'list_splat_pattern',
|
|
49
|
+
'dictionary_splat_pattern',
|
|
50
|
+
'as_pattern_target',
|
|
51
|
+
'expression_list',
|
|
52
|
+
'parenthesized_expression',
|
|
53
|
+
]);
|
|
54
|
+
/** Simple statements whose effect always happens once execution reaches them. */
|
|
55
|
+
const SIMPLE_STATEMENTS = new Set([
|
|
56
|
+
'expression_statement',
|
|
57
|
+
'import_statement',
|
|
58
|
+
'import_from_statement',
|
|
59
|
+
'delete_statement',
|
|
60
|
+
]);
|
|
61
|
+
/** Is `node` the `field` child of its parent? */
|
|
62
|
+
function isField(node, field) {
|
|
63
|
+
return node.parent?.childForFieldName(field)?.id === node.id;
|
|
64
|
+
}
|
|
65
|
+
/** Does `statement` import from the `builtins` module? */
|
|
66
|
+
function importsFromBuiltins(statement) {
|
|
67
|
+
return statement?.childForFieldName('module_name')?.text === 'builtins';
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The binding this identifier performs, following the binding constructs of
|
|
71
|
+
* Language Reference 4.2.1, or `null` for a plain read.
|
|
72
|
+
*/
|
|
73
|
+
function bindingOf(identifier) {
|
|
74
|
+
let node = identifier;
|
|
75
|
+
let parent = node.parent;
|
|
76
|
+
while (parent !== null && TARGET_WRAPPERS.has(parent.type)) {
|
|
77
|
+
node = parent;
|
|
78
|
+
parent = node.parent;
|
|
79
|
+
}
|
|
80
|
+
if (parent === null)
|
|
81
|
+
return null;
|
|
82
|
+
const shadow = { node: identifier, effect: 'shadow' };
|
|
83
|
+
switch (parent.type) {
|
|
84
|
+
case 'assignment':
|
|
85
|
+
case 'augmented_assignment':
|
|
86
|
+
case 'for_statement':
|
|
87
|
+
case 'for_in_clause':
|
|
88
|
+
return isField(node, 'left') ? shadow : null;
|
|
89
|
+
case 'named_expression':
|
|
90
|
+
case 'function_definition':
|
|
91
|
+
case 'class_definition':
|
|
92
|
+
case 'default_parameter':
|
|
93
|
+
case 'typed_default_parameter':
|
|
94
|
+
return isField(node, 'name') ? shadow : null;
|
|
95
|
+
case 'as_pattern':
|
|
96
|
+
return isField(node, 'alias') ? shadow : null;
|
|
97
|
+
case 'aliased_import': {
|
|
98
|
+
if (!isField(node, 'alias'))
|
|
99
|
+
return null;
|
|
100
|
+
// `from builtins import staticmethod as staticmethod` binds the builtin.
|
|
101
|
+
const source = parent.childForFieldName('name')?.text;
|
|
102
|
+
return importsFromBuiltins(parent.parent) && source === identifier.text
|
|
103
|
+
? { node: identifier, effect: 'builtin' }
|
|
104
|
+
: shadow;
|
|
105
|
+
}
|
|
106
|
+
case 'typed_parameter':
|
|
107
|
+
return node.type === 'identifier' ? shadow : null;
|
|
108
|
+
case 'parameters':
|
|
109
|
+
case 'lambda_parameters':
|
|
110
|
+
return shadow;
|
|
111
|
+
case 'delete_statement':
|
|
112
|
+
return { node: identifier, effect: 'unbind' };
|
|
113
|
+
case 'type':
|
|
114
|
+
return parent.parent?.type === 'type_parameter' ||
|
|
115
|
+
(parent.parent?.type === 'type_alias_statement' && isField(parent, 'left'))
|
|
116
|
+
? shadow
|
|
117
|
+
: null;
|
|
118
|
+
case 'dotted_name': {
|
|
119
|
+
const owner = parent.parent;
|
|
120
|
+
// `import a.b` binds `a`; `case name:` captures a single name.
|
|
121
|
+
if (owner?.type === 'import_statement')
|
|
122
|
+
return parent.firstNamedChild?.id === node.id ? shadow : null;
|
|
123
|
+
if (owner?.type === 'case_pattern')
|
|
124
|
+
return parent.namedChildCount === 1 ? shadow : null;
|
|
125
|
+
if (owner?.type !== 'import_from_statement' || !isField(parent, 'name'))
|
|
126
|
+
return null;
|
|
127
|
+
return importsFromBuiltins(owner) ? { node: identifier, effect: 'builtin' } : shadow;
|
|
128
|
+
}
|
|
129
|
+
default:
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const bindingsByTree = new WeakMap();
|
|
134
|
+
/** Every binding of a builtin descriptor name in the file, in source order. */
|
|
135
|
+
function descriptorBindings(node) {
|
|
136
|
+
const tree = node.tree;
|
|
137
|
+
const cached = bindingsByTree.get(tree);
|
|
138
|
+
if (cached !== undefined)
|
|
139
|
+
return cached;
|
|
140
|
+
// `global x` / `nonlocal x` bind nothing themselves; they redirect the
|
|
141
|
+
// declaring scope's own bindings of `x` to an outer namespace.
|
|
142
|
+
const redirected = new Map();
|
|
143
|
+
for (const statement of tree.rootNode.descendantsOfType([
|
|
144
|
+
'global_statement',
|
|
145
|
+
'nonlocal_statement',
|
|
146
|
+
])) {
|
|
147
|
+
const scope = scopeOf(statement)?.id;
|
|
148
|
+
const kind = statement.type === 'global_statement' ? 'global' : 'nonlocal';
|
|
149
|
+
for (const name of statement.namedChildren)
|
|
150
|
+
redirected.set(`${name.text}@${scope}`, kind);
|
|
151
|
+
}
|
|
152
|
+
const bindings = new Map();
|
|
153
|
+
const add = (name, binding) => {
|
|
154
|
+
const list = bindings.get(name);
|
|
155
|
+
if (list === undefined)
|
|
156
|
+
bindings.set(name, [binding]);
|
|
157
|
+
else
|
|
158
|
+
list.push(binding);
|
|
159
|
+
};
|
|
160
|
+
for (const found of tree.rootNode.descendantsOfType(['identifier', 'wildcard_import'])) {
|
|
161
|
+
if (found.type === 'wildcard_import') {
|
|
162
|
+
// `from m import *` binds every public name m defines. Unless m is
|
|
163
|
+
// `builtins`, whether that includes a descriptor name is unknown here.
|
|
164
|
+
const effect = importsFromBuiltins(found.parent) ? 'builtin' : 'shadow';
|
|
165
|
+
for (const name of BUILTIN_DESCRIPTORS)
|
|
166
|
+
add(name, { node: found, effect, redirect: null });
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
if (!BUILTIN_DESCRIPTORS.has(found.text))
|
|
170
|
+
continue;
|
|
171
|
+
const binding = bindingOf(found);
|
|
172
|
+
if (binding === null)
|
|
173
|
+
continue;
|
|
174
|
+
const redirect = redirected.get(`${found.text}@${scopeOf(found)?.id}`) ?? null;
|
|
175
|
+
add(found.text, { ...binding, redirect });
|
|
176
|
+
}
|
|
177
|
+
bindingsByTree.set(tree, bindings);
|
|
178
|
+
return bindings;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* The scope that owns names bound at `node`: a function or lambda body, a
|
|
182
|
+
* class body, a comprehension, or the module (`null`). A walrus target skips
|
|
183
|
+
* comprehensions, as PEP 572 binds it in the enclosing scope.
|
|
184
|
+
*/
|
|
185
|
+
function scopeOf(node) {
|
|
186
|
+
const skipComprehensions = node.parent?.type === 'named_expression';
|
|
187
|
+
let child = node;
|
|
188
|
+
for (let parent = node.parent; parent !== null; child = parent, parent = parent.parent) {
|
|
189
|
+
if (FUNCTION_SCOPES.has(parent.type)) {
|
|
190
|
+
if (isField(child, 'body') || isField(child, 'parameters'))
|
|
191
|
+
return parent;
|
|
192
|
+
}
|
|
193
|
+
else if (parent.type === 'class_definition') {
|
|
194
|
+
if (isField(child, 'body'))
|
|
195
|
+
return parent;
|
|
196
|
+
}
|
|
197
|
+
else if (COMPREHENSIONS.has(parent.type) && !skipComprehensions) {
|
|
198
|
+
return parent;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
/** The statement containing `node` that sits directly in `body`. */
|
|
204
|
+
function statementIn(node, body) {
|
|
205
|
+
let current = node;
|
|
206
|
+
while (current.parent !== null && current.parent.id !== body.id)
|
|
207
|
+
current = current.parent;
|
|
208
|
+
return current.parent === null ? null : current;
|
|
209
|
+
}
|
|
210
|
+
/** Can `binding` run before `use` in the same scope, including an earlier
|
|
211
|
+
* iteration of an enclosing loop? */
|
|
212
|
+
function mayRunBefore(binding, use, scope) {
|
|
213
|
+
if (binding.startIndex < use.startIndex)
|
|
214
|
+
return true;
|
|
215
|
+
for (let loop = use.parent; loop !== null && loop.id !== scope?.id; loop = loop.parent) {
|
|
216
|
+
if ((loop.type === 'for_statement' || loop.type === 'while_statement') &&
|
|
217
|
+
binding.startIndex >= loop.startIndex &&
|
|
218
|
+
binding.endIndex <= loop.endIndex) {
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* What a module, class or function namespace holds for the name when
|
|
226
|
+
* execution reaches `use`. A `shadow` that may have run wins. A restoring
|
|
227
|
+
* effect (`builtin`, `unbind`) counts only when it is a simple statement
|
|
228
|
+
* directly in the scope body that runs before `use`, so it runs exactly once
|
|
229
|
+
* in order.
|
|
230
|
+
*/
|
|
231
|
+
function namespaceState(bindings, scope, use) {
|
|
232
|
+
const body = scope === null ? null : scope.childForFieldName('body');
|
|
233
|
+
let state = 'unbind';
|
|
234
|
+
for (const binding of bindings) {
|
|
235
|
+
if (binding.redirect !== null || scopeOf(binding.node)?.id !== scope?.id)
|
|
236
|
+
continue;
|
|
237
|
+
if (!mayRunBefore(binding.node, use, scope))
|
|
238
|
+
continue;
|
|
239
|
+
if (binding.effect === 'shadow') {
|
|
240
|
+
state = 'shadow';
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const statement = statementIn(binding.node, body ?? binding.node.tree.rootNode);
|
|
244
|
+
const ordered = binding.node.startIndex < use.startIndex;
|
|
245
|
+
if (ordered && statement !== null && SIMPLE_STATEMENTS.has(statement.type)) {
|
|
246
|
+
state = binding.effect;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return state;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Resolve the decorator name at `use` as a class body does (Language
|
|
253
|
+
* Reference 4.2.2): the class namespace first, then the innermost enclosing
|
|
254
|
+
* function that binds the name, then module globals, then builtins.
|
|
255
|
+
*/
|
|
256
|
+
function lookupName(bindings, use) {
|
|
257
|
+
// Enclosing scopes, innermost first, ending with the module (`null`).
|
|
258
|
+
const chain = [];
|
|
259
|
+
for (let scope = scopeOf(use); scope !== null; scope = scopeOf(scope))
|
|
260
|
+
chain.push(scope);
|
|
261
|
+
chain.push(null);
|
|
262
|
+
const classScope = chain[0]?.type === 'class_definition' ? chain[0] : null;
|
|
263
|
+
if (classScope !== null) {
|
|
264
|
+
const state = namespaceState(bindings, classScope, use);
|
|
265
|
+
if (state !== 'unbind')
|
|
266
|
+
return state;
|
|
267
|
+
}
|
|
268
|
+
const functions = chain.filter((scope) => scope !== null && FUNCTION_SCOPES.has(scope.type));
|
|
269
|
+
for (const fn of functions) {
|
|
270
|
+
const owned = bindings.some((binding) => binding.redirect === null && scopeOf(binding.node)?.id === fn.id);
|
|
271
|
+
if (!owned)
|
|
272
|
+
continue;
|
|
273
|
+
// Any binding makes the name local to this function, so the class body
|
|
274
|
+
// reads that cell. An unbound cell raises NameError, not the builtin.
|
|
275
|
+
return namespaceState(bindings, fn, use) === 'builtin' ? 'builtin' : 'shadow';
|
|
276
|
+
}
|
|
277
|
+
// A class body inside a function runs whenever that function is called,
|
|
278
|
+
// which can be any time after its top-level statement starts. Module state
|
|
279
|
+
// is therefore read at that statement, and any later module override may
|
|
280
|
+
// also have run first.
|
|
281
|
+
const deferred = functions.length > 0;
|
|
282
|
+
const moduleUse = deferred ? (statementIn(use, use.tree.rootNode) ?? use) : use;
|
|
283
|
+
for (const binding of bindings) {
|
|
284
|
+
if (binding.effect !== 'shadow')
|
|
285
|
+
continue;
|
|
286
|
+
// A nested function can rebind an enclosing function's cell whenever it
|
|
287
|
+
// is called; that order is not modelled, so assume it ran.
|
|
288
|
+
if (binding.redirect === 'nonlocal') {
|
|
289
|
+
const outer = functions[functions.length - 1];
|
|
290
|
+
const inside = outer !== undefined &&
|
|
291
|
+
binding.node.startIndex >= outer.startIndex &&
|
|
292
|
+
binding.node.endIndex <= outer.endIndex;
|
|
293
|
+
if (inside)
|
|
294
|
+
return 'shadow';
|
|
295
|
+
}
|
|
296
|
+
if (binding.redirect === 'global') {
|
|
297
|
+
// The function can only be called once the top-level statement that
|
|
298
|
+
// defines it has run. Whether a call happens is unknown, so a restoring
|
|
299
|
+
// `global` delete is ignored and a rebinding one is assumed.
|
|
300
|
+
const top = statementIn(binding.node, binding.node.tree.rootNode);
|
|
301
|
+
if (deferred || (top !== null && mayRunBefore(top, use, null)))
|
|
302
|
+
return 'shadow';
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (deferred) {
|
|
306
|
+
const laterOverride = bindings.some((binding) => binding.effect === 'shadow' &&
|
|
307
|
+
binding.redirect === null &&
|
|
308
|
+
scopeOf(binding.node) === null &&
|
|
309
|
+
binding.node.startIndex > moduleUse.startIndex);
|
|
310
|
+
if (laterOverride)
|
|
311
|
+
return 'shadow';
|
|
312
|
+
}
|
|
313
|
+
return namespaceState(bindings, null, moduleUse);
|
|
314
|
+
}
|
|
@@ -43,13 +43,11 @@
|
|
|
43
43
|
* and emit a single edge rather than branching. `List[T]` /
|
|
44
44
|
* `Dict[K, V]` strip the outer generic for receiver typing (see
|
|
45
45
|
* `interpret.ts`).
|
|
46
|
-
* 5. **Decorators that rewrite signatures** —
|
|
47
|
-
* `@property`, `@classmethod`, `@staticmethod` are
|
|
48
|
-
* by `receiver-binding.ts`.
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* different callable is followed only through the declared
|
|
52
|
-
* return type.
|
|
46
|
+
* 5. **Decorators that rewrite signatures** — Known descriptor
|
|
47
|
+
* spellings (`@property`, `@classmethod`, `@staticmethod`) are
|
|
48
|
+
* recognized by `receiver-binding.ts`. Unknown decorator expressions
|
|
49
|
+
* leave implicit receiver binding unresolved. Calls through wrappers
|
|
50
|
+
* are followed only through their declared return type.
|
|
53
51
|
* 6. **`typing.TYPE_CHECKING`-guarded imports** — treated like any
|
|
54
52
|
* other `import` for reference resolution. We do not distinguish
|
|
55
53
|
* runtime-visible from type-checker-only imports; this is
|
|
@@ -43,13 +43,11 @@
|
|
|
43
43
|
* and emit a single edge rather than branching. `List[T]` /
|
|
44
44
|
* `Dict[K, V]` strip the outer generic for receiver typing (see
|
|
45
45
|
* `interpret.ts`).
|
|
46
|
-
* 5. **Decorators that rewrite signatures** —
|
|
47
|
-
* `@property`, `@classmethod`, `@staticmethod` are
|
|
48
|
-
* by `receiver-binding.ts`.
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* different callable is followed only through the declared
|
|
52
|
-
* return type.
|
|
46
|
+
* 5. **Decorators that rewrite signatures** — Known descriptor
|
|
47
|
+
* spellings (`@property`, `@classmethod`, `@staticmethod`) are
|
|
48
|
+
* recognized by `receiver-binding.ts`. Unknown decorator expressions
|
|
49
|
+
* leave implicit receiver binding unresolved. Calls through wrappers
|
|
50
|
+
* are followed only through their declared return type.
|
|
53
51
|
* 6. **`typing.TYPE_CHECKING`-guarded imports** — treated like any
|
|
54
52
|
* other `import` for reference resolution. We do not distinguish
|
|
55
53
|
* runtime-visible from type-checker-only imports; this is
|
|
@@ -124,7 +124,9 @@ export function interpretPythonTypeBinding(captures) {
|
|
|
124
124
|
// the variable-annotation and constructor-inferred forms from the
|
|
125
125
|
// classic parameter annotation.
|
|
126
126
|
let source = 'parameter-annotation';
|
|
127
|
-
if (captures['@type-binding.
|
|
127
|
+
if (captures['@type-binding.uncertain-receiver'] !== undefined)
|
|
128
|
+
source = 'decorator-unknown';
|
|
129
|
+
else if (captures['@type-binding.self'] !== undefined)
|
|
128
130
|
source = 'self';
|
|
129
131
|
// `cls` is a self-like receiver; share the source label so downstream
|
|
130
132
|
// `Registry.lookup` Step 2 treats them identically.
|
|
@@ -13,6 +13,13 @@ import type { CaptureMatch } from '../../../../_shared/index.js';
|
|
|
13
13
|
import { type SyntaxNode } from '../../utils/ast-helpers.js';
|
|
14
14
|
/** Static-like descriptors do not inject an instance on attribute access. */
|
|
15
15
|
export declare function isPythonStaticLikeMethod(fnNode: SyntaxNode): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Can the method's parameter list prove its call shape? Only a plain function
|
|
18
|
+
* or one builtin `staticmethod` / `classmethod` wrapper qualifies. Any other
|
|
19
|
+
* decorator may replace the callable, and a descriptor stack can make it
|
|
20
|
+
* uncallable: `staticmethod(classmethod(f))` yields a classmethod object.
|
|
21
|
+
*/
|
|
22
|
+
export declare function hasPythonProvenCallShape(fnNode: SyntaxNode): boolean;
|
|
16
23
|
export interface PythonBoundReceiver {
|
|
17
24
|
readonly kind: 'instance' | 'class';
|
|
18
25
|
readonly parameter: SyntaxNode;
|
|
@@ -34,6 +41,11 @@ export declare function classifyPythonBoundReceiver(fnNode: SyntaxNode): PythonB
|
|
|
34
41
|
* The caller is responsible for guaranteeing `fnNode.type ===
|
|
35
42
|
* 'function_definition'`.
|
|
36
43
|
*/
|
|
44
|
+
/**
|
|
45
|
+
* The first parameter of a class method under an unrecognized decorator.
|
|
46
|
+
* Python may still bind it implicitly, but its receiver kind is unproven.
|
|
47
|
+
*/
|
|
48
|
+
export declare function classifyPythonUncertainReceiver(fnNode: SyntaxNode): PythonBoundReceiver | null;
|
|
37
49
|
export declare function synthesizeReceiverTypeBinding(fnNode: SyntaxNode): CaptureMatch | null;
|
|
38
50
|
/**
|
|
39
51
|
* Synthesize class-scope field bindings for the common Python constructor
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* awareness that Python's runtime depends on.
|
|
11
11
|
*/
|
|
12
12
|
import { nodeToCapture, syntheticCapture } from '../../utils/ast-helpers.js';
|
|
13
|
+
import { decoratorNames, isBuiltinDescriptor } from './builtin-descriptors.js';
|
|
13
14
|
/** Walk up to the enclosing `class_definition`, ignoring the immediate
|
|
14
15
|
* `decorated_definition` wrapper. Returns `null` when the function is
|
|
15
16
|
* free, lambda-bodied, or nested inside another function. */
|
|
@@ -27,26 +28,76 @@ function findEnclosingClassDefinition(node) {
|
|
|
27
28
|
function classDefinitionName(classNode) {
|
|
28
29
|
return classNode.childForFieldName('name')?.text ?? null;
|
|
29
30
|
}
|
|
30
|
-
/**
|
|
31
|
-
*
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
/** Accept a local `@property` accessor chain, skipping only plain unrelated
|
|
32
|
+
* methods. Other intervening class-suite statements may rebind the descriptor,
|
|
33
|
+
* including tuple assignment or control flow. */
|
|
34
|
+
function isLocalPropertyAccessor(fnNode, expression) {
|
|
35
|
+
const methodName = fnNode.childForFieldName('name')?.text;
|
|
36
|
+
if (methodName === undefined ||
|
|
37
|
+
!['getter', 'setter', 'deleter'].some((kind) => expression === `${methodName}.${kind}`))
|
|
35
38
|
return false;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
const wrapper = fnNode.parent;
|
|
40
|
+
const classBody = findEnclosingClassDefinition(fnNode)?.childForFieldName('body');
|
|
41
|
+
if (wrapper?.type !== 'decorated_definition' || classBody === null || classBody === undefined) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
let wrapperIndex = -1;
|
|
45
|
+
for (let i = 0; i < classBody.namedChildCount; i++) {
|
|
46
|
+
const sibling = classBody.namedChild(i);
|
|
47
|
+
if (sibling?.id === wrapper.id) {
|
|
48
|
+
wrapperIndex = i;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
for (let i = wrapperIndex - 1; i >= 0; i--) {
|
|
53
|
+
const sibling = classBody.namedChild(i);
|
|
54
|
+
if (sibling?.type === 'function_definition' &&
|
|
55
|
+
sibling.childForFieldName('name')?.text !== methodName) {
|
|
56
|
+
// A plain function definition binds only its own name in the class suite.
|
|
39
57
|
continue;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
58
|
+
}
|
|
59
|
+
if (sibling?.type !== 'decorated_definition')
|
|
60
|
+
return false;
|
|
61
|
+
let candidate = null;
|
|
62
|
+
for (let j = 0; j < sibling.namedChildCount; j++) {
|
|
63
|
+
const child = sibling.namedChild(j);
|
|
64
|
+
if (child?.type === 'function_definition')
|
|
65
|
+
candidate = child;
|
|
66
|
+
}
|
|
67
|
+
if (candidate?.childForFieldName('name')?.text !== methodName)
|
|
68
|
+
return false;
|
|
69
|
+
const [decorator, ...rest] = decoratorNames(candidate);
|
|
70
|
+
if (decorator === undefined || rest.length > 0)
|
|
71
|
+
return false;
|
|
72
|
+
if (isBuiltinDescriptor(candidate, decorator, 'property'))
|
|
43
73
|
return true;
|
|
74
|
+
if (!['getter', 'setter', 'deleter'].some((kind) => decorator === `${methodName}.${kind}`)) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
44
77
|
}
|
|
45
78
|
return false;
|
|
46
79
|
}
|
|
47
80
|
/** Static-like descriptors do not inject an instance on attribute access. */
|
|
48
81
|
export function isPythonStaticLikeMethod(fnNode) {
|
|
49
|
-
return (fnNode.childForFieldName('name')?.text === '__new__' ||
|
|
82
|
+
return (fnNode.childForFieldName('name')?.text === '__new__' ||
|
|
83
|
+
decoratorNames(fnNode).some((name) => isBuiltinDescriptor(fnNode, name, 'staticmethod')));
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Can the method's parameter list prove its call shape? Only a plain function
|
|
87
|
+
* or one builtin `staticmethod` / `classmethod` wrapper qualifies. Any other
|
|
88
|
+
* decorator may replace the callable, and a descriptor stack can make it
|
|
89
|
+
* uncallable: `staticmethod(classmethod(f))` yields a classmethod object.
|
|
90
|
+
*/
|
|
91
|
+
export function hasPythonProvenCallShape(fnNode) {
|
|
92
|
+
const [decorator, ...rest] = decoratorNames(fnNode);
|
|
93
|
+
if (decorator === undefined)
|
|
94
|
+
return true;
|
|
95
|
+
return (rest.length === 0 &&
|
|
96
|
+
(isBuiltinDescriptor(fnNode, decorator, 'staticmethod') ||
|
|
97
|
+
isBuiltinDescriptor(fnNode, decorator, 'classmethod')));
|
|
98
|
+
}
|
|
99
|
+
function isKnownReceiverDecorator(fnNode, expression) {
|
|
100
|
+
return isBuiltinDescriptor(fnNode, expression) || isLocalPropertyAccessor(fnNode, expression);
|
|
50
101
|
}
|
|
51
102
|
function firstBoundReceiverParameter(parameters) {
|
|
52
103
|
for (let i = 0; i < parameters.namedChildCount; i++) {
|
|
@@ -86,12 +137,17 @@ function firstParameterName(param) {
|
|
|
86
137
|
*/
|
|
87
138
|
export function classifyPythonBoundReceiver(fnNode) {
|
|
88
139
|
const enclosingClass = findEnclosingClassDefinition(fnNode);
|
|
89
|
-
if (enclosingClass === null
|
|
140
|
+
if (enclosingClass === null)
|
|
90
141
|
return null;
|
|
142
|
+
const decorators = decoratorNames(fnNode);
|
|
143
|
+
if (isPythonStaticLikeMethod(fnNode) ||
|
|
144
|
+
decorators.some((name) => !isKnownReceiverDecorator(fnNode, name))) {
|
|
145
|
+
// Python evaluates decorators as expressions. An unrecognized one may
|
|
146
|
+
// replace the function with a class/static descriptor, so its first
|
|
147
|
+
// parameter is not proven to receive an instance.
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
91
150
|
const functionName = fnNode.childForFieldName('name')?.text;
|
|
92
|
-
// Python applies these descriptor kinds implicitly even without decorators.
|
|
93
|
-
// __new__ is static-like (its class argument is explicit), while
|
|
94
|
-
// __init_subclass__ and __class_getitem__ receive the class implicitly.
|
|
95
151
|
const params = fnNode.childForFieldName('parameters');
|
|
96
152
|
if (params === null)
|
|
97
153
|
return null;
|
|
@@ -103,7 +159,9 @@ export function classifyPythonBoundReceiver(fnNode) {
|
|
|
103
159
|
if (name === null || className === null)
|
|
104
160
|
return null;
|
|
105
161
|
return {
|
|
106
|
-
|
|
162
|
+
// Python makes __init_subclass__ and __class_getitem__ implicit
|
|
163
|
+
// classmethods, so they receive the class even without a decorator.
|
|
164
|
+
kind: decorators.includes('classmethod') ||
|
|
107
165
|
functionName === '__init_subclass__' ||
|
|
108
166
|
functionName === '__class_getitem__'
|
|
109
167
|
? 'class'
|
|
@@ -142,10 +200,45 @@ function classifyPythonExplicitNewReceiver(fnNode) {
|
|
|
142
200
|
* The caller is responsible for guaranteeing `fnNode.type ===
|
|
143
201
|
* 'function_definition'`.
|
|
144
202
|
*/
|
|
203
|
+
/**
|
|
204
|
+
* The first parameter of a class method under an unrecognized decorator.
|
|
205
|
+
* Python may still bind it implicitly, but its receiver kind is unproven.
|
|
206
|
+
*/
|
|
207
|
+
export function classifyPythonUncertainReceiver(fnNode) {
|
|
208
|
+
const decorators = decoratorNames(fnNode);
|
|
209
|
+
// Python applies decorators bottom-up. An outer built-in staticmethod
|
|
210
|
+
// guarantees no implicit receiver even when an inner decorator is opaque.
|
|
211
|
+
// The first parameter remains explicit and can keep its annotation.
|
|
212
|
+
const outermost = decorators[0];
|
|
213
|
+
if (outermost !== undefined && isBuiltinDescriptor(fnNode, outermost, 'staticmethod')) {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
if (decorators.every((name) => isKnownReceiverDecorator(fnNode, name)))
|
|
217
|
+
return null;
|
|
218
|
+
const enclosingClass = findEnclosingClassDefinition(fnNode);
|
|
219
|
+
const parameters = fnNode.childForFieldName('parameters');
|
|
220
|
+
const parameter = parameters === null ? null : firstBoundReceiverParameter(parameters);
|
|
221
|
+
const name = parameter === null ? null : firstParameterName(parameter);
|
|
222
|
+
const className = enclosingClass === null ? null : classDefinitionName(enclosingClass);
|
|
223
|
+
if (parameter === null || name === null || className === null)
|
|
224
|
+
return null;
|
|
225
|
+
return { kind: 'instance', parameter, name, className };
|
|
226
|
+
}
|
|
145
227
|
export function synthesizeReceiverTypeBinding(fnNode) {
|
|
146
228
|
const receiver = classifyPythonBoundReceiver(fnNode) ?? classifyPythonExplicitNewReceiver(fnNode);
|
|
147
|
-
if (receiver === null)
|
|
148
|
-
|
|
229
|
+
if (receiver === null) {
|
|
230
|
+
// Keep an uncertain receiver anchored to its enclosing class so the
|
|
231
|
+
// resolver can report the missing member without treating it as `self`.
|
|
232
|
+
const uncertain = classifyPythonUncertainReceiver(fnNode);
|
|
233
|
+
if (uncertain === null)
|
|
234
|
+
return null;
|
|
235
|
+
const { parameter: first, name, className } = uncertain;
|
|
236
|
+
return {
|
|
237
|
+
'@type-binding.uncertain-receiver': nodeToCapture('@type-binding.uncertain-receiver', first),
|
|
238
|
+
'@type-binding.name': syntheticCapture('@type-binding.name', first, name),
|
|
239
|
+
'@type-binding.type': syntheticCapture('@type-binding.type', first, className),
|
|
240
|
+
};
|
|
241
|
+
}
|
|
149
242
|
// Receiver convention: instance methods get `self`, classmethods get `cls`.
|
|
150
243
|
// The capture tag records the descriptor kind; the variable may use any
|
|
151
244
|
// spelling.
|
|
@@ -241,8 +334,6 @@ export function synthesizeConstructorFieldTypeBindings(fnNode) {
|
|
|
241
334
|
return [];
|
|
242
335
|
if (findEnclosingClassDefinition(fnNode) === null)
|
|
243
336
|
return [];
|
|
244
|
-
if (hasDecorator(fnNode, 'staticmethod') || hasDecorator(fnNode, 'classmethod'))
|
|
245
|
-
return [];
|
|
246
337
|
const receiver = synthesizeReceiverTypeBinding(fnNode);
|
|
247
338
|
const receiverName = receiver?.['@type-binding.self']?.text;
|
|
248
339
|
if (receiverName === undefined)
|
|
@@ -50,6 +50,7 @@ const pythonScopeResolver = {
|
|
|
50
50
|
// A free call naming a class constructs it: `Service(db).do_work()` (#2708).
|
|
51
51
|
constructionSyntax: { bare: true },
|
|
52
52
|
language: SupportedLanguages.Python,
|
|
53
|
+
suppressReceiverLookup: (typeRef) => typeRef.source === 'decorator-unknown',
|
|
53
54
|
languageProvider: pythonProvider,
|
|
54
55
|
importEdgeReason: 'python-scope: import',
|
|
55
56
|
resolveImportTarget: (targetRaw, fromFile, allFilePaths, _resolutionConfig, context) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { definitionIdPosition } from '../../scope-resolution/utils/definition-id.js';
|
|
2
|
-
import { classifyPythonBoundReceiver, isPythonStaticLikeMethod } from './receiver-binding.js';
|
|
2
|
+
import { classifyPythonBoundReceiver, hasPythonProvenCallShape, isPythonStaticLikeMethod, } from './receiver-binding.js';
|
|
3
3
|
const simplePositionalCallsByFile = new Map();
|
|
4
4
|
const positionalCapacitiesByFile = new Map();
|
|
5
5
|
const positionKey = (line, column) => `${line}:${column}`;
|
|
@@ -87,19 +87,10 @@ function positionalCapacity(fnNode) {
|
|
|
87
87
|
}
|
|
88
88
|
/** Record a method's exact fixed positional capacity when the AST proves it. */
|
|
89
89
|
export function recordPythonSubtypeMethodShape(filePath, fnNode, mapLine) {
|
|
90
|
-
// An unknown decorator may replace the function or mark it abstract
|
|
91
|
-
//
|
|
92
|
-
|
|
93
|
-
const wrapper = fnNode.parent;
|
|
94
|
-
if (wrapper?.type === 'decorated_definition' &&
|
|
95
|
-
wrapper.namedChildren.some((child) => {
|
|
96
|
-
if (child.type !== 'decorator')
|
|
97
|
-
return false;
|
|
98
|
-
const name = child.firstNamedChild?.text;
|
|
99
|
-
return name !== 'staticmethod' && name !== 'classmethod';
|
|
100
|
-
})) {
|
|
90
|
+
// An unknown decorator may replace the function or mark it abstract, so
|
|
91
|
+
// its parameter list cannot prove a concrete subtype dispatch target.
|
|
92
|
+
if (!hasPythonProvenCallShape(fnNode))
|
|
101
93
|
return;
|
|
102
|
-
}
|
|
103
94
|
const capacity = positionalCapacity(fnNode);
|
|
104
95
|
if (capacity === undefined)
|
|
105
96
|
return;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Verified against tree-sitter-python 0.23.4
|
|
3
3
|
import { SupportedLanguages } from '../../../../_shared/index.js';
|
|
4
4
|
import { hasKeyword } from '../../field-extractors/configs/helpers.js';
|
|
5
|
-
import { classifyPythonBoundReceiver } from '../../languages/python/receiver-binding.js';
|
|
5
|
+
import { classifyPythonBoundReceiver, classifyPythonUncertainReceiver, isPythonStaticLikeMethod, } from '../../languages/python/receiver-binding.js';
|
|
6
6
|
import { extractSimpleTypeName } from '../../type-extractors/shared.js';
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
8
|
// Python helpers
|
|
@@ -92,7 +92,10 @@ function extractPythonParameters(node) {
|
|
|
92
92
|
return [];
|
|
93
93
|
const params = [];
|
|
94
94
|
let isFirst = true;
|
|
95
|
-
|
|
95
|
+
// An opaque decorator leaves the receiver kind unproven, not the slot: keep
|
|
96
|
+
// stripping it so arity matches ordinary bound calls.
|
|
97
|
+
const boundReceiverId = (classifyPythonBoundReceiver(funcNode) ??
|
|
98
|
+
(isPythonStaticLikeMethod(funcNode) ? null : classifyPythonUncertainReceiver(funcNode)))?.parameter.id;
|
|
96
99
|
for (let i = 0; i < paramList.namedChildCount; i++) {
|
|
97
100
|
const param = paramList.namedChild(i);
|
|
98
101
|
if (!param)
|
|
@@ -1009,6 +1009,11 @@ function followChainedRef(start, draftById) {
|
|
|
1009
1009
|
*/
|
|
1010
1010
|
function typeBindingStrength(source) {
|
|
1011
1011
|
switch (source) {
|
|
1012
|
+
// A method decorator may change what the first parameter receives. An
|
|
1013
|
+
// annotation describes intent, not descriptor binding, so it cannot
|
|
1014
|
+
// override this uncertainty for that parameter.
|
|
1015
|
+
case 'decorator-unknown':
|
|
1016
|
+
return 4;
|
|
1012
1017
|
case 'annotation':
|
|
1013
1018
|
return 3;
|
|
1014
1019
|
case 'parameter-annotation':
|
|
@@ -1235,6 +1235,10 @@ export interface ScopeResolver {
|
|
|
1235
1235
|
* return undefined to retain the shared behavior.
|
|
1236
1236
|
*/
|
|
1237
1237
|
readonly resolveReceiverMember?: (ownerDef: SymbolDefinition, memberName: string, callsite: Callsite, scopes: ScopeResolutionIndexes, model: SemanticModel) => ReceiverMemberResolution | undefined;
|
|
1238
|
+
/** Suppress all receiver dispatch when a captured type cannot prove its
|
|
1239
|
+
* runtime binding. Runs before compound and simple receiver lookup; the
|
|
1240
|
+
* caller records a receiver-unresolved outcome. */
|
|
1241
|
+
readonly suppressReceiverLookup?: (typeRef: TypeRef) => boolean;
|
|
1238
1242
|
/**
|
|
1239
1243
|
* Enable the receiver-bound Case 0.5 fallback for explicit `this`
|
|
1240
1244
|
* receivers (`this->m()` / `this.m()`) that resolves against the
|
|
@@ -72,7 +72,7 @@ import { type HeritageTypeArguments } from '../utils/generic-instantiation.js';
|
|
|
72
72
|
import type { ResolutionOutcomeRecorder } from '../resolution-outcome.js';
|
|
73
73
|
import type { ReceiverOrigin } from '../resolution-outcome.js';
|
|
74
74
|
import type { DecodedReceiverChain } from '../../utils/receiver-chain-codec.js';
|
|
75
|
-
type ReceiverBoundProviderSubset = Pick<ScopeResolver, 'isSuperReceiver' | 'isSuperReceiverInContext' | 'fieldFallbackOnMethodLookup' | 'collapseMemberCallsByCallerTarget' | 'elementTypeOf' | 'hoistTypeBindingsToModule' | 'stripReceiverCastExpressions' | 'constructionSyntax' | 'stripTypePreservingDecoration' | 'resolveQualifiedReceiverMember' | 'namespaceReceiverPaths' | 'resolveReceiverMember' | 'resolveThisViaEnclosingClass' | 'resolveMissingReceiverMembersFromSubtypes' | 'missingReceiverSubtypeCandidateCompatibility' | 'arityCompatibility' | 'conversionRankFn' | 'conversionOnlyArgTypePrefixes' | 'constraintCompatibility' | 'isStaticOnly' | 'normalizeTypeArgument' | 'markConstructionSites' | 'namespaceExportsIncludeImportedNames' | 'resolveNamespaceChains'>;
|
|
75
|
+
type ReceiverBoundProviderSubset = Pick<ScopeResolver, 'isSuperReceiver' | 'isSuperReceiverInContext' | 'fieldFallbackOnMethodLookup' | 'collapseMemberCallsByCallerTarget' | 'elementTypeOf' | 'hoistTypeBindingsToModule' | 'stripReceiverCastExpressions' | 'constructionSyntax' | 'stripTypePreservingDecoration' | 'resolveQualifiedReceiverMember' | 'namespaceReceiverPaths' | 'resolveReceiverMember' | 'suppressReceiverLookup' | 'resolveThisViaEnclosingClass' | 'resolveMissingReceiverMembersFromSubtypes' | 'missingReceiverSubtypeCandidateCompatibility' | 'arityCompatibility' | 'conversionRankFn' | 'conversionOnlyArgTypePrefixes' | 'constraintCompatibility' | 'isStaticOnly' | 'normalizeTypeArgument' | 'markConstructionSites' | 'namespaceExportsIncludeImportedNames' | 'resolveNamespaceChains'>;
|
|
76
76
|
/**
|
|
77
77
|
* Is this dropped receiver rooted inside the analyzed program?
|
|
78
78
|
*
|
|
@@ -849,6 +849,27 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
|
|
|
849
849
|
const receiverName = site.explicitReceiver.name;
|
|
850
850
|
const memberName = site.name;
|
|
851
851
|
const siteKey = `${parsed.filePath}:${site.atRange.startLine}:${site.atRange.startCol}`;
|
|
852
|
+
if (provider.suppressReceiverLookup !== undefined) {
|
|
853
|
+
const baseName = decodeReceiverChain(site.receiverChain)?.baseReceiverName ??
|
|
854
|
+
receiverName.split(/[.([\s]/, 1)[0];
|
|
855
|
+
const baseTypeRef = baseName === undefined
|
|
856
|
+
? undefined
|
|
857
|
+
: findReceiverTypeBinding(site.inScope, baseName, scopes);
|
|
858
|
+
if (baseTypeRef !== undefined && provider.suppressReceiverLookup(baseTypeRef)) {
|
|
859
|
+
options.recordResolutionOutcome?.({
|
|
860
|
+
kind: 'suppressed',
|
|
861
|
+
reason: 'receiver-unresolved',
|
|
862
|
+
candidateIds: [],
|
|
863
|
+
phase: 'receiver-bound-calls',
|
|
864
|
+
filePath: parsed.filePath,
|
|
865
|
+
name: site.name,
|
|
866
|
+
range: site.atRange,
|
|
867
|
+
siteKind: site.kind,
|
|
868
|
+
});
|
|
869
|
+
handledSites.add(siteKey);
|
|
870
|
+
continue;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
852
873
|
// ── owned-but-unbound receiver ───────────────────────────────
|
|
853
874
|
// The language declared this scope REBINDS the receiver and gave
|
|
854
875
|
// it no type — a JS/TS ordinary `function`, whose `this` comes
|
|
@@ -1871,9 +1892,7 @@ export function emitReceiverBoundCalls(graph, scopes, parsedFiles, nodeLookup, h
|
|
|
1871
1892
|
if (picked === undefined) {
|
|
1872
1893
|
// This runtime subtype has no proven binding. Preserve
|
|
1873
1894
|
// partial coverage even when a sibling supplies a target.
|
|
1874
|
-
|
|
1875
|
-
missingMemberSubtypeIds.add(subtype.nodeId);
|
|
1876
|
-
}
|
|
1895
|
+
missingMemberSubtypeIds.add(subtype.nodeId);
|
|
1877
1896
|
continue;
|
|
1878
1897
|
}
|
|
1879
1898
|
subtypeTargets.set(picked.nodeId, picked);
|
|
@@ -800,7 +800,14 @@ import { copyV8CacheIfPresent, tryLoadV8Cache, writeV8CacheFile } from './v8-sid
|
|
|
800
800
|
// would retain that capacity and could emit a false concrete call target.
|
|
801
801
|
// v119 (#3396): Python subtype method capacities now omit receiverless ordinary
|
|
802
802
|
// methods. Warm v118 ParsedFiles would replay a false compatible target.
|
|
803
|
-
|
|
803
|
+
// v120 (#3394): decorated Python method receiver bindings now distinguish
|
|
804
|
+
// unproven decorators from instance receivers. Warm v119 ParsedFiles would
|
|
805
|
+
// replay a fabricated `self` binding or lack the uncertainty marker entirely.
|
|
806
|
+
// v121 (#3399 follow-up): Python decorator identity now ignores trailing
|
|
807
|
+
// comments, honors rebinding of builtin descriptor names visible where the
|
|
808
|
+
// decorator is evaluated, and withholds subtype capacity from descriptor
|
|
809
|
+
// stacks. Warm v120 captures carry the old verdicts.
|
|
810
|
+
const SCHEMA_BUMP = 121;
|
|
804
811
|
const GITNEXUS_PKG_VERSION = (() => {
|
|
805
812
|
try {
|
|
806
813
|
// package.json sits at gitnexus/package.json — two levels up from
|
package/package.json
CHANGED