Skip to content

Commit 5e7702e

Browse files
authored
fix(deducer): avoid retrieving declarations for non-infrastructure call nodes (#329)
Previously, the deducer attempted to retrieve all call node declarations and match them against custom infrastructure functions. This method was flawed as functions with multiple declarations caused the deducer to fail. To address this, we now first verify that a call node pertains to a custom infrastructure function by comparing function names. Only then do we fetch the call node's declaration, effectively bypassing the collection of extraneous call node declarations.
1 parent 787d5af commit 5e7702e

File tree

3 files changed

+27
-6
lines changed

3 files changed

+27
-6
lines changed

.changeset/wild-planets-report.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@plutolang/pyright-deducer": patch
3+
---
4+
5+
fix(deducer): avoid retrieving declarations for non-infrastructure call nodes
6+
7+
Previously, the deducer attempted to retrieve all call node declarations and match them against custom infrastructure functions. This method was flawed as functions with multiple declarations caused the deducer to fail. To address this, we now first verify that a call node pertains to a custom infrastructure function by comparing function names. Only then do we fetch the call node's declaration, effectively bypassing the collection of extraneous call node declarations.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Scope } from "pyright-internal/dist/analyzer/scope";
2-
import { ParseNode } from "pyright-internal/dist/parser/parseNodes";
2+
import { FunctionNode } from "pyright-internal/dist/parser/parseNodes";
33
import { SourceFile } from "pyright-internal/dist/analyzer/sourceFile";
44

55
export interface CustomInfraFn {
6-
readonly topNode: ParseNode;
6+
readonly topNode: FunctionNode;
77
readonly hierarchy: Scope[];
88
readonly sourceFile: SourceFile;
99
}

components/deducers/python-pyright/src/index.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,12 +210,22 @@ export default class PyrightDeducer extends core.Deducer {
210210
}
211211

212212
const fnName = statement.leftExpression;
213+
214+
// First, check if the function name is same as one custom infrastructure function name.
215+
const infraFn = customInfraFns.find((fn) => fn.topNode.name.value === fnName.value);
216+
if (!infraFn) {
217+
continue;
218+
}
219+
220+
// Find the declaration of the called function.
213221
const decls = this.typeEvaluator!.getDeclarationsForNameNode(fnName);
214-
assert(decls?.length === 1, "The function name must be declared only once.");
222+
assert(
223+
decls?.length === 1,
224+
`The function name \`${fnName.value}\` must be declared only once.`
225+
);
215226

216-
const customInfraFn = customInfraFns.find((fn) => fn.topNode.id === decls[0].node.id);
217-
if (customInfraFn) {
218-
// This call node is a call to a custom infrastructure function.
227+
// Second, check if the call node is calling the found custom infrastructure function.
228+
if (infraFn.topNode.id === decls[0].node.id) {
219229
customInfraFnCallNodes.push({
220230
callNode: statement,
221231
functionNode: decls[0].node as FunctionNode,
@@ -365,6 +375,10 @@ function findCandidateInfraFns(
365375
const topNode = ScopeUtils.findTopNodeInScope(node, scopeHierarchy[0]);
366376
assert(topNode, `No top node found in scope.`);
367377
if (!customInfraFns.has(topNode.id)) {
378+
assert(
379+
topNode.nodeType === ParseNodeType.Function,
380+
`The custom infra fn must be a function.`
381+
);
368382
customInfraFns.set(topNode.id, { topNode, sourceFile, hierarchy: scopeHierarchy });
369383
}
370384
}

0 commit comments

Comments
 (0)