@suss/adapter-python 0.5.0 → 0.5.2
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/index.cjs +150 -22
- package/dist/index.d.cts +20 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +150 -22
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -666,6 +666,82 @@ function classifyDecorator(decoratorNode, scope) {
|
|
|
666
666
|
}
|
|
667
667
|
return { ...resolveCallee(expr, scope), args: [], keywordArgs: {}, range };
|
|
668
668
|
}
|
|
669
|
+
function unwrapDecorator(decoratorNode, scope, ownModule, moduleDef) {
|
|
670
|
+
const expr = decoratorNode.namedChild(0);
|
|
671
|
+
if (expr === null || expr.type !== "call") {
|
|
672
|
+
return null;
|
|
673
|
+
}
|
|
674
|
+
const callee = field(expr, "function");
|
|
675
|
+
if (callee === null || callee.type !== "identifier") {
|
|
676
|
+
return null;
|
|
677
|
+
}
|
|
678
|
+
const wrapper = wrapperBehind(callee.text, scope, ownModule, moduleDef);
|
|
679
|
+
if (wrapper === null) {
|
|
680
|
+
return null;
|
|
681
|
+
}
|
|
682
|
+
const inner = singleReturnedCall(wrapper.node);
|
|
683
|
+
if (inner === null) {
|
|
684
|
+
return null;
|
|
685
|
+
}
|
|
686
|
+
const innerCallee = field(inner, "function");
|
|
687
|
+
if (innerCallee === null || innerCallee.type !== "attribute") {
|
|
688
|
+
return null;
|
|
689
|
+
}
|
|
690
|
+
if (!passesParametersThrough(wrapper.node, inner)) {
|
|
691
|
+
return null;
|
|
692
|
+
}
|
|
693
|
+
const resolved = resolveCallee(innerCallee, wrapper.module.moduleScope);
|
|
694
|
+
if (resolved.importedName === null) {
|
|
695
|
+
return null;
|
|
696
|
+
}
|
|
697
|
+
const argumentList = field(expr, "arguments");
|
|
698
|
+
const { args, keywordArgs } = argumentList?.type === "argument_list" ? readCallArguments(argumentList) : { args: [], keywordArgs: {} };
|
|
699
|
+
return {
|
|
700
|
+
...resolved,
|
|
701
|
+
args,
|
|
702
|
+
keywordArgs,
|
|
703
|
+
range: rangeOf(decoratorNode),
|
|
704
|
+
objectModule: wrapper.module
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
function wrapperBehind(name, scope, ownModule, moduleDef) {
|
|
708
|
+
const binding = resolveName(scope, name);
|
|
709
|
+
if (binding?.kind === "functionDef") {
|
|
710
|
+
return { node: binding.node, module: ownModule };
|
|
711
|
+
}
|
|
712
|
+
if (binding?.kind === "importFrom") {
|
|
713
|
+
return moduleDef(
|
|
714
|
+
{ module: binding.module, relativeLevel: binding.relativeLevel },
|
|
715
|
+
binding.importedName
|
|
716
|
+
);
|
|
717
|
+
}
|
|
718
|
+
return null;
|
|
719
|
+
}
|
|
720
|
+
function singleReturnedCall(def) {
|
|
721
|
+
const body = field(def, "body");
|
|
722
|
+
if (body === null) {
|
|
723
|
+
return null;
|
|
724
|
+
}
|
|
725
|
+
const statements = body.namedChildren.filter(
|
|
726
|
+
(child) => child !== null && child.type !== "comment"
|
|
727
|
+
);
|
|
728
|
+
if (statements.length !== 1 || statements[0]?.type !== "return_statement") {
|
|
729
|
+
return null;
|
|
730
|
+
}
|
|
731
|
+
const returned = statements[0].namedChildren[0];
|
|
732
|
+
return returned !== null && returned?.type === "call" ? returned : null;
|
|
733
|
+
}
|
|
734
|
+
function passesParametersThrough(def, inner) {
|
|
735
|
+
const params = field(def, "parameters");
|
|
736
|
+
const names = (params?.namedChildren ?? []).filter((child) => child?.type === "identifier").map((child) => child.text);
|
|
737
|
+
const argumentList = field(inner, "arguments");
|
|
738
|
+
const positional = (argumentList?.namedChildren ?? []).filter(
|
|
739
|
+
(child) => child !== null && child.type !== "keyword_argument"
|
|
740
|
+
);
|
|
741
|
+
return positional.length === names.length && positional.every(
|
|
742
|
+
(argument, at) => argument.type === "identifier" && argument.text === names[at]
|
|
743
|
+
);
|
|
744
|
+
}
|
|
669
745
|
|
|
670
746
|
// src/discovery.ts
|
|
671
747
|
var import_behavioral_ir = require("@suss/behavioral-ir");
|
|
@@ -994,12 +1070,26 @@ function argsOf(call) {
|
|
|
994
1070
|
function calleeText(call) {
|
|
995
1071
|
return field(call, "function")?.text ?? call.text;
|
|
996
1072
|
}
|
|
1073
|
+
function withoutChainLinks(calls) {
|
|
1074
|
+
const isLink = /* @__PURE__ */ new Set();
|
|
1075
|
+
for (const call of calls) {
|
|
1076
|
+
const callee = field(call, "function");
|
|
1077
|
+
if (callee === null || callee.type !== "attribute") {
|
|
1078
|
+
continue;
|
|
1079
|
+
}
|
|
1080
|
+
const object2 = field(callee, "object");
|
|
1081
|
+
if (object2 !== null && object2.type === "call") {
|
|
1082
|
+
isLink.add(object2.id);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
return calls.filter((call) => !isLink.has(call.id));
|
|
1086
|
+
}
|
|
997
1087
|
function invocationEffects(definitionNode) {
|
|
998
1088
|
const body = field(definitionNode, "body");
|
|
999
1089
|
if (body === null) {
|
|
1000
1090
|
return [];
|
|
1001
1091
|
}
|
|
1002
|
-
const calls = bodyCalls(body);
|
|
1092
|
+
const calls = withoutChainLinks(bodyCalls(body));
|
|
1003
1093
|
if (calls.length === 0) {
|
|
1004
1094
|
return [];
|
|
1005
1095
|
}
|
|
@@ -17163,33 +17253,51 @@ function discoverUnits(root, module2, options) {
|
|
|
17163
17253
|
}
|
|
17164
17254
|
const { definition, decorators } = stripDecorators(stmt);
|
|
17165
17255
|
for (const decoratorNode of decorators) {
|
|
17166
|
-
const
|
|
17167
|
-
|
|
17168
|
-
|
|
17256
|
+
const direct = classifyDecorator(decoratorNode, module2.moduleScope);
|
|
17257
|
+
const classifications = direct.module !== null && acceptedByAnyPattern(direct.module, options) ? [direct] : [
|
|
17258
|
+
unwrapDecorator(
|
|
17259
|
+
decoratorNode,
|
|
17260
|
+
module2.moduleScope,
|
|
17261
|
+
module2,
|
|
17262
|
+
(spec, name) => options.routerIndex?.moduleDef(
|
|
17263
|
+
options.absoluteFile ?? options.filePath,
|
|
17264
|
+
spec,
|
|
17265
|
+
name
|
|
17266
|
+
) ?? null
|
|
17267
|
+
)
|
|
17268
|
+
].filter(
|
|
17269
|
+
(candidate) => candidate !== null
|
|
17169
17270
|
);
|
|
17170
|
-
|
|
17171
|
-
|
|
17172
|
-
|
|
17173
|
-
|
|
17174
|
-
|
|
17175
|
-
for (const
|
|
17176
|
-
|
|
17177
|
-
|
|
17178
|
-
|
|
17179
|
-
|
|
17180
|
-
|
|
17181
|
-
|
|
17182
|
-
|
|
17183
|
-
|
|
17184
|
-
|
|
17185
|
-
|
|
17186
|
-
|
|
17271
|
+
for (const classification of classifications) {
|
|
17272
|
+
if (classification.module === null) {
|
|
17273
|
+
continue;
|
|
17274
|
+
}
|
|
17275
|
+
const decoratorModule = classification.module;
|
|
17276
|
+
for (const pack of options.packs) {
|
|
17277
|
+
for (const pattern of pack.discovery) {
|
|
17278
|
+
units.push(
|
|
17279
|
+
...unitsFor(
|
|
17280
|
+
pattern,
|
|
17281
|
+
pack,
|
|
17282
|
+
decoratorModule,
|
|
17283
|
+
classification,
|
|
17284
|
+
definition,
|
|
17285
|
+
module2,
|
|
17286
|
+
options
|
|
17287
|
+
)
|
|
17288
|
+
);
|
|
17289
|
+
}
|
|
17187
17290
|
}
|
|
17188
17291
|
}
|
|
17189
17292
|
}
|
|
17190
17293
|
}
|
|
17191
17294
|
return units;
|
|
17192
17295
|
}
|
|
17296
|
+
function acceptedByAnyPattern(module2, options) {
|
|
17297
|
+
return options.packs.some(
|
|
17298
|
+
(pack) => pack.discovery.some((pattern) => pattern.importModule.includes(module2))
|
|
17299
|
+
);
|
|
17300
|
+
}
|
|
17193
17301
|
function unitsFor(pattern, pack, decoratorModule, classification, definition, module2, options) {
|
|
17194
17302
|
if (!pattern.importModule.includes(decoratorModule)) {
|
|
17195
17303
|
return [];
|
|
@@ -17367,7 +17475,7 @@ function readRouterPrefix(pattern, classification, module2, options, range) {
|
|
|
17367
17475
|
}
|
|
17368
17476
|
const resolution = options.routerIndex.resolve(
|
|
17369
17477
|
pattern,
|
|
17370
|
-
module2,
|
|
17478
|
+
classification.objectModule ?? module2,
|
|
17371
17479
|
classification.objectName
|
|
17372
17480
|
);
|
|
17373
17481
|
if (resolution.kind === "abstain") {
|
|
@@ -18112,7 +18220,26 @@ function buildRouterIndex(files, packs, resolverOptions) {
|
|
|
18112
18220
|
}
|
|
18113
18221
|
}
|
|
18114
18222
|
}
|
|
18223
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
18224
|
+
for (const file2 of files) {
|
|
18225
|
+
byFile.set(file2.file, file2);
|
|
18226
|
+
}
|
|
18115
18227
|
return {
|
|
18228
|
+
moduleDef(fromFile, spec, name) {
|
|
18229
|
+
const resolution = resolveModule(fromFile, spec, resolverOptions);
|
|
18230
|
+
if (resolution.status !== "resolved") {
|
|
18231
|
+
return null;
|
|
18232
|
+
}
|
|
18233
|
+
const bound = byFile.get(resolution.file);
|
|
18234
|
+
if (bound === void 0) {
|
|
18235
|
+
return null;
|
|
18236
|
+
}
|
|
18237
|
+
const binding = bound.module.moduleScope.bindings.get(name);
|
|
18238
|
+
if (binding?.kind !== "functionDef") {
|
|
18239
|
+
return null;
|
|
18240
|
+
}
|
|
18241
|
+
return { node: binding.node, module: bound.module };
|
|
18242
|
+
},
|
|
18116
18243
|
resolve(pattern, module2, objectName) {
|
|
18117
18244
|
const index = byPattern.get(pattern);
|
|
18118
18245
|
if (index === void 0) {
|
|
@@ -19001,6 +19128,7 @@ async function extractPythonProject(options) {
|
|
|
19001
19128
|
const rawUnits = discoverUnits(root, moduleBinding, {
|
|
19002
19129
|
packs: options.packs,
|
|
19003
19130
|
filePath: displayPath,
|
|
19131
|
+
absoluteFile: file2,
|
|
19004
19132
|
routerIndex,
|
|
19005
19133
|
gapHandling,
|
|
19006
19134
|
...storagePatterns.length > 0 ? {
|
package/dist/index.d.cts
CHANGED
|
@@ -146,6 +146,12 @@ interface DecoratorClassification {
|
|
|
146
146
|
keywordArgs: Record<string, DecoratorArg>;
|
|
147
147
|
/** Where the decorator is written. Anything we read out of its arguments uses this as its provenance. */
|
|
148
148
|
range: Range;
|
|
149
|
+
/**
|
|
150
|
+
* The module the decorator's object lives in, when the decorator was read
|
|
151
|
+
* through a project wrapper written in another file. The router prefix is
|
|
152
|
+
* resolved there, since that is where the namespace is constructed.
|
|
153
|
+
*/
|
|
154
|
+
objectModule?: ModuleBinding;
|
|
149
155
|
}
|
|
150
156
|
declare function classifyDecorator(decoratorNode: Node, scope: Scope): DecoratorClassification;
|
|
151
157
|
|
|
@@ -417,6 +423,18 @@ type RoutePrefixResolution = {
|
|
|
417
423
|
};
|
|
418
424
|
interface RouterIndex {
|
|
419
425
|
resolve(pattern: PythonDiscoveryPattern, module: ModuleBinding, objectName: string): RoutePrefixResolution;
|
|
426
|
+
/**
|
|
427
|
+
* The module-level def a name in another module refers to, with that
|
|
428
|
+
* module's own bindings, so a decorator written through a project wrapper
|
|
429
|
+
* can be read where the wrapper is written.
|
|
430
|
+
*/
|
|
431
|
+
moduleDef(fromFile: string, spec: {
|
|
432
|
+
module: string;
|
|
433
|
+
relativeLevel: number;
|
|
434
|
+
}, name: string): {
|
|
435
|
+
node: Node;
|
|
436
|
+
module: ModuleBinding;
|
|
437
|
+
} | null;
|
|
420
438
|
}
|
|
421
439
|
interface RouterIndexOptions extends ModuleResolverOptions {
|
|
422
440
|
/** The project's facts, so a loop over a call can be settled by the rules. */
|
|
@@ -448,6 +466,8 @@ interface DiscoveryOptions {
|
|
|
448
466
|
gapHandling?: ExtractorOptions["gapHandling"];
|
|
449
467
|
/** What a pack needs to say a call talks to the database. Absent when no pack does. */
|
|
450
468
|
storage?: StorageLookup | undefined;
|
|
469
|
+
/** The file's absolute path, which module resolution wants; `filePath` may be shortened for display. */
|
|
470
|
+
absoluteFile?: string | undefined;
|
|
451
471
|
}
|
|
452
472
|
declare function discoverUnits(root: Node, module: ModuleBinding, options: DiscoveryOptions): RawCodeStructure[];
|
|
453
473
|
|
package/dist/index.d.ts
CHANGED
|
@@ -146,6 +146,12 @@ interface DecoratorClassification {
|
|
|
146
146
|
keywordArgs: Record<string, DecoratorArg>;
|
|
147
147
|
/** Where the decorator is written. Anything we read out of its arguments uses this as its provenance. */
|
|
148
148
|
range: Range;
|
|
149
|
+
/**
|
|
150
|
+
* The module the decorator's object lives in, when the decorator was read
|
|
151
|
+
* through a project wrapper written in another file. The router prefix is
|
|
152
|
+
* resolved there, since that is where the namespace is constructed.
|
|
153
|
+
*/
|
|
154
|
+
objectModule?: ModuleBinding;
|
|
149
155
|
}
|
|
150
156
|
declare function classifyDecorator(decoratorNode: Node, scope: Scope): DecoratorClassification;
|
|
151
157
|
|
|
@@ -417,6 +423,18 @@ type RoutePrefixResolution = {
|
|
|
417
423
|
};
|
|
418
424
|
interface RouterIndex {
|
|
419
425
|
resolve(pattern: PythonDiscoveryPattern, module: ModuleBinding, objectName: string): RoutePrefixResolution;
|
|
426
|
+
/**
|
|
427
|
+
* The module-level def a name in another module refers to, with that
|
|
428
|
+
* module's own bindings, so a decorator written through a project wrapper
|
|
429
|
+
* can be read where the wrapper is written.
|
|
430
|
+
*/
|
|
431
|
+
moduleDef(fromFile: string, spec: {
|
|
432
|
+
module: string;
|
|
433
|
+
relativeLevel: number;
|
|
434
|
+
}, name: string): {
|
|
435
|
+
node: Node;
|
|
436
|
+
module: ModuleBinding;
|
|
437
|
+
} | null;
|
|
420
438
|
}
|
|
421
439
|
interface RouterIndexOptions extends ModuleResolverOptions {
|
|
422
440
|
/** The project's facts, so a loop over a call can be settled by the rules. */
|
|
@@ -448,6 +466,8 @@ interface DiscoveryOptions {
|
|
|
448
466
|
gapHandling?: ExtractorOptions["gapHandling"];
|
|
449
467
|
/** What a pack needs to say a call talks to the database. Absent when no pack does. */
|
|
450
468
|
storage?: StorageLookup | undefined;
|
|
469
|
+
/** The file's absolute path, which module resolution wants; `filePath` may be shortened for display. */
|
|
470
|
+
absoluteFile?: string | undefined;
|
|
451
471
|
}
|
|
452
472
|
declare function discoverUnits(root: Node, module: ModuleBinding, options: DiscoveryOptions): RawCodeStructure[];
|
|
453
473
|
|
package/dist/index.js
CHANGED
|
@@ -612,6 +612,82 @@ function classifyDecorator(decoratorNode, scope) {
|
|
|
612
612
|
}
|
|
613
613
|
return { ...resolveCallee(expr, scope), args: [], keywordArgs: {}, range };
|
|
614
614
|
}
|
|
615
|
+
function unwrapDecorator(decoratorNode, scope, ownModule, moduleDef) {
|
|
616
|
+
const expr = decoratorNode.namedChild(0);
|
|
617
|
+
if (expr === null || expr.type !== "call") {
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
620
|
+
const callee = field(expr, "function");
|
|
621
|
+
if (callee === null || callee.type !== "identifier") {
|
|
622
|
+
return null;
|
|
623
|
+
}
|
|
624
|
+
const wrapper = wrapperBehind(callee.text, scope, ownModule, moduleDef);
|
|
625
|
+
if (wrapper === null) {
|
|
626
|
+
return null;
|
|
627
|
+
}
|
|
628
|
+
const inner = singleReturnedCall(wrapper.node);
|
|
629
|
+
if (inner === null) {
|
|
630
|
+
return null;
|
|
631
|
+
}
|
|
632
|
+
const innerCallee = field(inner, "function");
|
|
633
|
+
if (innerCallee === null || innerCallee.type !== "attribute") {
|
|
634
|
+
return null;
|
|
635
|
+
}
|
|
636
|
+
if (!passesParametersThrough(wrapper.node, inner)) {
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
639
|
+
const resolved = resolveCallee(innerCallee, wrapper.module.moduleScope);
|
|
640
|
+
if (resolved.importedName === null) {
|
|
641
|
+
return null;
|
|
642
|
+
}
|
|
643
|
+
const argumentList = field(expr, "arguments");
|
|
644
|
+
const { args, keywordArgs } = argumentList?.type === "argument_list" ? readCallArguments(argumentList) : { args: [], keywordArgs: {} };
|
|
645
|
+
return {
|
|
646
|
+
...resolved,
|
|
647
|
+
args,
|
|
648
|
+
keywordArgs,
|
|
649
|
+
range: rangeOf(decoratorNode),
|
|
650
|
+
objectModule: wrapper.module
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
function wrapperBehind(name, scope, ownModule, moduleDef) {
|
|
654
|
+
const binding = resolveName(scope, name);
|
|
655
|
+
if (binding?.kind === "functionDef") {
|
|
656
|
+
return { node: binding.node, module: ownModule };
|
|
657
|
+
}
|
|
658
|
+
if (binding?.kind === "importFrom") {
|
|
659
|
+
return moduleDef(
|
|
660
|
+
{ module: binding.module, relativeLevel: binding.relativeLevel },
|
|
661
|
+
binding.importedName
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
return null;
|
|
665
|
+
}
|
|
666
|
+
function singleReturnedCall(def) {
|
|
667
|
+
const body = field(def, "body");
|
|
668
|
+
if (body === null) {
|
|
669
|
+
return null;
|
|
670
|
+
}
|
|
671
|
+
const statements = body.namedChildren.filter(
|
|
672
|
+
(child) => child !== null && child.type !== "comment"
|
|
673
|
+
);
|
|
674
|
+
if (statements.length !== 1 || statements[0]?.type !== "return_statement") {
|
|
675
|
+
return null;
|
|
676
|
+
}
|
|
677
|
+
const returned = statements[0].namedChildren[0];
|
|
678
|
+
return returned !== null && returned?.type === "call" ? returned : null;
|
|
679
|
+
}
|
|
680
|
+
function passesParametersThrough(def, inner) {
|
|
681
|
+
const params = field(def, "parameters");
|
|
682
|
+
const names = (params?.namedChildren ?? []).filter((child) => child?.type === "identifier").map((child) => child.text);
|
|
683
|
+
const argumentList = field(inner, "arguments");
|
|
684
|
+
const positional = (argumentList?.namedChildren ?? []).filter(
|
|
685
|
+
(child) => child !== null && child.type !== "keyword_argument"
|
|
686
|
+
);
|
|
687
|
+
return positional.length === names.length && positional.every(
|
|
688
|
+
(argument, at) => argument.type === "identifier" && argument.text === names[at]
|
|
689
|
+
);
|
|
690
|
+
}
|
|
615
691
|
|
|
616
692
|
// src/discovery.ts
|
|
617
693
|
import { dispatchByType, restBinding } from "@suss/behavioral-ir";
|
|
@@ -950,12 +1026,26 @@ function argsOf(call) {
|
|
|
950
1026
|
function calleeText(call) {
|
|
951
1027
|
return field(call, "function")?.text ?? call.text;
|
|
952
1028
|
}
|
|
1029
|
+
function withoutChainLinks(calls) {
|
|
1030
|
+
const isLink = /* @__PURE__ */ new Set();
|
|
1031
|
+
for (const call of calls) {
|
|
1032
|
+
const callee = field(call, "function");
|
|
1033
|
+
if (callee === null || callee.type !== "attribute") {
|
|
1034
|
+
continue;
|
|
1035
|
+
}
|
|
1036
|
+
const object2 = field(callee, "object");
|
|
1037
|
+
if (object2 !== null && object2.type === "call") {
|
|
1038
|
+
isLink.add(object2.id);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
return calls.filter((call) => !isLink.has(call.id));
|
|
1042
|
+
}
|
|
953
1043
|
function invocationEffects(definitionNode) {
|
|
954
1044
|
const body = field(definitionNode, "body");
|
|
955
1045
|
if (body === null) {
|
|
956
1046
|
return [];
|
|
957
1047
|
}
|
|
958
|
-
const calls = bodyCalls(body);
|
|
1048
|
+
const calls = withoutChainLinks(bodyCalls(body));
|
|
959
1049
|
if (calls.length === 0) {
|
|
960
1050
|
return [];
|
|
961
1051
|
}
|
|
@@ -17119,33 +17209,51 @@ function discoverUnits(root, module, options) {
|
|
|
17119
17209
|
}
|
|
17120
17210
|
const { definition, decorators } = stripDecorators(stmt);
|
|
17121
17211
|
for (const decoratorNode of decorators) {
|
|
17122
|
-
const
|
|
17123
|
-
|
|
17124
|
-
|
|
17212
|
+
const direct = classifyDecorator(decoratorNode, module.moduleScope);
|
|
17213
|
+
const classifications = direct.module !== null && acceptedByAnyPattern(direct.module, options) ? [direct] : [
|
|
17214
|
+
unwrapDecorator(
|
|
17215
|
+
decoratorNode,
|
|
17216
|
+
module.moduleScope,
|
|
17217
|
+
module,
|
|
17218
|
+
(spec, name) => options.routerIndex?.moduleDef(
|
|
17219
|
+
options.absoluteFile ?? options.filePath,
|
|
17220
|
+
spec,
|
|
17221
|
+
name
|
|
17222
|
+
) ?? null
|
|
17223
|
+
)
|
|
17224
|
+
].filter(
|
|
17225
|
+
(candidate) => candidate !== null
|
|
17125
17226
|
);
|
|
17126
|
-
|
|
17127
|
-
|
|
17128
|
-
|
|
17129
|
-
|
|
17130
|
-
|
|
17131
|
-
for (const
|
|
17132
|
-
|
|
17133
|
-
|
|
17134
|
-
|
|
17135
|
-
|
|
17136
|
-
|
|
17137
|
-
|
|
17138
|
-
|
|
17139
|
-
|
|
17140
|
-
|
|
17141
|
-
|
|
17142
|
-
|
|
17227
|
+
for (const classification of classifications) {
|
|
17228
|
+
if (classification.module === null) {
|
|
17229
|
+
continue;
|
|
17230
|
+
}
|
|
17231
|
+
const decoratorModule = classification.module;
|
|
17232
|
+
for (const pack of options.packs) {
|
|
17233
|
+
for (const pattern of pack.discovery) {
|
|
17234
|
+
units.push(
|
|
17235
|
+
...unitsFor(
|
|
17236
|
+
pattern,
|
|
17237
|
+
pack,
|
|
17238
|
+
decoratorModule,
|
|
17239
|
+
classification,
|
|
17240
|
+
definition,
|
|
17241
|
+
module,
|
|
17242
|
+
options
|
|
17243
|
+
)
|
|
17244
|
+
);
|
|
17245
|
+
}
|
|
17143
17246
|
}
|
|
17144
17247
|
}
|
|
17145
17248
|
}
|
|
17146
17249
|
}
|
|
17147
17250
|
return units;
|
|
17148
17251
|
}
|
|
17252
|
+
function acceptedByAnyPattern(module, options) {
|
|
17253
|
+
return options.packs.some(
|
|
17254
|
+
(pack) => pack.discovery.some((pattern) => pattern.importModule.includes(module))
|
|
17255
|
+
);
|
|
17256
|
+
}
|
|
17149
17257
|
function unitsFor(pattern, pack, decoratorModule, classification, definition, module, options) {
|
|
17150
17258
|
if (!pattern.importModule.includes(decoratorModule)) {
|
|
17151
17259
|
return [];
|
|
@@ -17323,7 +17431,7 @@ function readRouterPrefix(pattern, classification, module, options, range) {
|
|
|
17323
17431
|
}
|
|
17324
17432
|
const resolution = options.routerIndex.resolve(
|
|
17325
17433
|
pattern,
|
|
17326
|
-
module,
|
|
17434
|
+
classification.objectModule ?? module,
|
|
17327
17435
|
classification.objectName
|
|
17328
17436
|
);
|
|
17329
17437
|
if (resolution.kind === "abstain") {
|
|
@@ -18068,7 +18176,26 @@ function buildRouterIndex(files, packs, resolverOptions) {
|
|
|
18068
18176
|
}
|
|
18069
18177
|
}
|
|
18070
18178
|
}
|
|
18179
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
18180
|
+
for (const file2 of files) {
|
|
18181
|
+
byFile.set(file2.file, file2);
|
|
18182
|
+
}
|
|
18071
18183
|
return {
|
|
18184
|
+
moduleDef(fromFile, spec, name) {
|
|
18185
|
+
const resolution = resolveModule(fromFile, spec, resolverOptions);
|
|
18186
|
+
if (resolution.status !== "resolved") {
|
|
18187
|
+
return null;
|
|
18188
|
+
}
|
|
18189
|
+
const bound = byFile.get(resolution.file);
|
|
18190
|
+
if (bound === void 0) {
|
|
18191
|
+
return null;
|
|
18192
|
+
}
|
|
18193
|
+
const binding = bound.module.moduleScope.bindings.get(name);
|
|
18194
|
+
if (binding?.kind !== "functionDef") {
|
|
18195
|
+
return null;
|
|
18196
|
+
}
|
|
18197
|
+
return { node: binding.node, module: bound.module };
|
|
18198
|
+
},
|
|
18072
18199
|
resolve(pattern, module, objectName) {
|
|
18073
18200
|
const index = byPattern.get(pattern);
|
|
18074
18201
|
if (index === void 0) {
|
|
@@ -18957,6 +19084,7 @@ async function extractPythonProject(options) {
|
|
|
18957
19084
|
const rawUnits = discoverUnits(root, moduleBinding, {
|
|
18958
19085
|
packs: options.packs,
|
|
18959
19086
|
filePath: displayPath,
|
|
19087
|
+
absoluteFile: file2,
|
|
18960
19088
|
routerIndex,
|
|
18961
19089
|
gapHandling,
|
|
18962
19090
|
...storagePatterns.length > 0 ? {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/adapter-python",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Python language adapter for suss — parses source with tree-sitter (WASM), resolves names with a lexical binder, and emits raw extractions for the suss pipeline.",
|
|
6
6
|
"keywords": [
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
"typecheck": "tsc --noEmit"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@suss/behavioral-ir": "0.5.
|
|
51
|
-
"@suss/datalog": "0.5.
|
|
52
|
-
"@suss/extractor": "0.5.
|
|
50
|
+
"@suss/behavioral-ir": "0.5.2",
|
|
51
|
+
"@suss/datalog": "0.5.2",
|
|
52
|
+
"@suss/extractor": "0.5.2",
|
|
53
53
|
"web-tree-sitter": "^0.26.11"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|