Skip to content

Commit ec909b5

Browse files
author
Trinketer22
committed
Make use of binding resolver
1 parent ed728a0 commit ec909b5

File tree

1 file changed

+35
-19
lines changed

1 file changed

+35
-19
lines changed

server/src/languages/func/inspections/UnusedImpure.ts

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import { UnusedInspection } from "./UnusedInspection"
99
import { Inspection, InspectionIds } from "./Inspection"
1010
import { RecursiveVisitor } from "@server/visitor/visitor";
1111
import { Func } from "@server/languages/func/psi/Decls";
12-
import { convertTy, typeOf } from "@server/languages/func/types/infer";
1312
import { asLspRange } from "@server/utils/position"
1413
import { closestNamedSibling, parentOfType, parentOfTypeWithCb } from "@server/psi/utils"
1514
import { Referent } from "@server/languages/func/psi/Referent"
15+
import { FunCBindingResolver } from "../psi/BindingResolver"
1616

1717

1818
export class UnusedImpureInspection extends UnusedInspection implements Inspection {
@@ -26,27 +26,40 @@ export class UnusedImpureInspection extends UnusedInspection implements Inspecti
2626
impureMap.set(f.name(true), f);
2727
}
2828
});
29+
const bindResolver = new FunCBindingResolver(file);
2930
RecursiveVisitor.visit(file.rootNode, (node): boolean => {
31+
let droppableDef: Func | undefined;
32+
3033
if (node.type == "function_application") {
31-
const funcIdentifier = node.children.find(n => n?.type === "identifier")
34+
const funcIdentifier = node.childForFieldName("callee");
35+
if (funcIdentifier) {
36+
droppableDef = impureMap.get(funcIdentifier.text);
37+
}
38+
} else if (node.type == "method_call") {
39+
const funcIdentifier = node.childForFieldName("method_name");
3240
if (funcIdentifier) {
33-
const droppableDef = impureMap.get(funcIdentifier.text);
34-
if (droppableDef && this.checkCallWillDrop(node, droppableDef, file)) {
35-
const range = asLspRange(node);
36-
diagnostics.push({
37-
severity: lsp.DiagnosticSeverity.Error,
38-
range,
39-
message: "This call will be dropped due to lack of impure specifier!",
40-
source: "func"
41-
})
41+
const methodName = funcIdentifier.text;
42+
droppableDef = impureMap.get(methodName);
43+
if (!droppableDef) {
44+
droppableDef = impureMap.get("~" + methodName);
4245
}
4346
}
4447
}
48+
49+
if (droppableDef && this.checkCallWillDrop(node, droppableDef, file, bindResolver)) {
50+
const range = asLspRange(node);
51+
diagnostics.push({
52+
severity: lsp.DiagnosticSeverity.Error,
53+
range,
54+
message: "This call will be dropped due to lack of impure specifier!",
55+
source: "func"
56+
})
57+
}
4558
return true;
4659
})
4760
}
4861

49-
private checkCallWillDrop(node: Node, definition: Func, file: FuncFile) {
62+
private checkCallWillDrop(node: Node, definition: Func, file: FuncFile, bindResolver: FunCBindingResolver) {
5063
const returnExp = definition.returnType();
5164
if (returnExp !== null) {
5265
// If return type of a function is empty tensor - check no more.
@@ -65,31 +78,33 @@ export class UnusedImpureInspection extends UnusedInspection implements Inspecti
6578
"if_statement",
6679
"while_statement",
6780
"do_while_statement",
68-
"repeat_statement"
81+
"repeat_statement",
82+
"return_statement"
6983
);
7084
// If call is in the block_statement of any kind, it will be a child of expression_statement
7185
// Otherwise it is in condition block of if/while/do while
7286
// Or in arguments clause of other function_application/method_call
7387
if (!expressionParent || expressionParent.parent.type !== "expression_statement") {
88+
// If expression is in condition or return statement it will not be dropped
7489
return false;
7590
}
7691

7792
// We are in the expression expression_statement
7893
// Closest previous sibling got to be lvalue expression
7994
// (identifier/tensor_expression/tuple_expression)
80-
const lValue = closestNamedSibling(expressionParent.origin, 'prev', (sibling) => sibling.type !== "comment");
95+
const resolvedBinding = bindResolver.resolve(expressionParent.parent);
8196
// If no lvalue, non-impure call will drop
82-
if (!lValue) {
97+
if (resolvedBinding.bindings.size == 0) {
8398
return true;
8499
}
85100
// If no identifiers referenced in lvalue, means those are whole type and will be dropped
86-
const affectedIdentifiers = lValue.descendantsOfType("identifier");
101+
// const affectedIdentifiers = resolvedBinding.bindings.values()
87102

88-
for (let refValue of affectedIdentifiers) {
103+
for (let refValue of resolvedBinding.bindings.values()) {
89104
if (!refValue) {
90105
continue;
91106
}
92-
const references = new Referent(refValue, file).findReferences({}) // we need at least one reference
107+
const references = new Referent(refValue.identifier, file).findReferences({}) // we need at least one reference
93108
// Has to be referenced in call, conditional or return statement;
94109
for (let ref of references) {
95110
const parent = parentOfType(ref.node,
@@ -99,7 +114,8 @@ export class UnusedImpureInspection extends UnusedInspection implements Inspecti
99114
"if_statement",
100115
"while_statement",
101116
"do_while_statement",
102-
"repeat_statement"
117+
"repeat_statement",
118+
"return_statement"
103119
)
104120
if (parent && parent.type !== "expression_statement") {
105121
return false;

0 commit comments

Comments
 (0)