mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-06 02:49:56 +00:00
parent
52581cd4e9
commit
3d09c85ee3
2 changed files with 47 additions and 1 deletions
|
|
@ -2344,6 +2344,7 @@ export function emitReceiverBoundCalls(
|
|||
const ambiguousCandidateIds = new Set<string>();
|
||||
const unknownCompatibilityCandidateIds = new Set<string>();
|
||||
const incompleteInheritanceSubtypeIds = new Set<string>();
|
||||
const missingMemberSubtypeIds = new Set<string>();
|
||||
const visitedSubtypeIds = new Set<string>([ownerDef.nodeId]);
|
||||
const subtypeQueue = [ownerDef.nodeId];
|
||||
let subtypeHead = 0;
|
||||
|
|
@ -2449,7 +2450,15 @@ export function emitReceiverBoundCalls(
|
|||
// indexed MRO, leaving this subtype's target unproven.
|
||||
incompleteInheritanceSubtypeIds.add(subtype.nodeId);
|
||||
}
|
||||
if (subtypeAmbiguous || picked === undefined) continue;
|
||||
if (subtypeAmbiguous) continue;
|
||||
if (picked === undefined) {
|
||||
// This runtime subtype has no proven binding. Preserve
|
||||
// partial coverage even when a sibling supplies a target.
|
||||
if (!incompleteInheritanceSubtypeIds.has(subtype.nodeId)) {
|
||||
missingMemberSubtypeIds.add(subtype.nodeId);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
subtypeTargets.set(picked.nodeId, picked);
|
||||
}
|
||||
}
|
||||
|
|
@ -2473,6 +2482,7 @@ export function emitReceiverBoundCalls(
|
|||
...ambiguousCandidateIds,
|
||||
...unknownCompatibilityCandidateIds,
|
||||
...incompleteInheritanceSubtypeIds,
|
||||
...missingMemberSubtypeIds,
|
||||
]),
|
||||
MAX_INTERFACE_DISPATCH_FANOUT,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1354,6 +1354,42 @@ describe('Python mixin self-dispatch', () => {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('Python incomplete inheritance', () => {
|
||||
it('records a missing subtype alongside a valid sibling target', async () => {
|
||||
const repoDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gn-python-missing-subtype-'));
|
||||
try {
|
||||
writeFixtureRepo(repoDir, {
|
||||
'case.py': `class Mixin:
|
||||
def dispatch(self):
|
||||
return self.hook()
|
||||
|
||||
class HasHook(Mixin):
|
||||
def hook(self):
|
||||
pass
|
||||
|
||||
class MissingHook(Mixin):
|
||||
pass
|
||||
`,
|
||||
});
|
||||
const result = await runPipelineFromRepo(repoDir, () => {});
|
||||
const calls = getRelationships(result, 'CALLS').filter(
|
||||
(edge) => edge.source === 'dispatch' && edge.target === 'hook',
|
||||
);
|
||||
expect(calls.map((edge) => edge.rel.targetId)).toEqual([
|
||||
expect.stringContaining('HasHook.hook'),
|
||||
]);
|
||||
expect(
|
||||
getResolutionOutcomes(result).some(
|
||||
(outcome) =>
|
||||
outcome.name === 'hook' &&
|
||||
outcome.reason === 'receiver-unresolved' &&
|
||||
outcome.candidateIds.some((id) => id.endsWith(':Class:MissingHook')),
|
||||
),
|
||||
).toBe(true);
|
||||
} finally {
|
||||
fs.rmSync(repoDir, { recursive: true, force: true });
|
||||
}
|
||||
}, 60000);
|
||||
|
||||
it('ignores a self-named external base without losing the class for its children', async () => {
|
||||
const repoDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gn-python-self-parent-'));
|
||||
try {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue