Skip to content

Commit a642a97

Browse files
author
Trinketer22
committed
Lint
1 parent e9ff132 commit a642a97

File tree

6 files changed

+348
-268
lines changed

6 files changed

+348
-268
lines changed

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

Lines changed: 130 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,34 @@
33

44
import * as lsp from "vscode-languageserver"
55

6-
import type { FuncFile } from "@server/languages/func/psi/FuncFile"
7-
import { Node } from 'web-tree-sitter'
8-
import { UnusedInspection } from "./UnusedInspection"
9-
import { Inspection, InspectionIds } from "./Inspection"
10-
import { RecursiveVisitor } from "@server/visitor/visitor";
11-
import { Func } from "@server/languages/func/psi/Decls";
12-
import { asLspRange } from "@server/utils/position"
13-
import { closestNamedSibling, parentOfType, parentOfTypeWithCb } from "@server/psi/utils"
14-
import { Referent } from "@server/languages/func/psi/Referent"
15-
import { FunCBindingResolver } from "@server/languages/func/psi/BindingResolver";
16-
import { FUNC_PARSED_FILES_CACHE } from "@server/files"
6+
import {Node} from "web-tree-sitter"
177

8+
import type {FuncFile} from "@server/languages/func/psi/FuncFile"
9+
10+
import {RecursiveVisitor} from "@server/visitor/visitor"
11+
import {Func} from "@server/languages/func/psi/Decls"
12+
import {asLspRange} from "@server/utils/position"
13+
import {closestNamedSibling, parentOfType, parentOfTypeWithCb} from "@server/psi/utils"
14+
import {Referent} from "@server/languages/func/psi/Referent"
15+
import {FunCBindingResolver} from "@server/languages/func/psi/BindingResolver"
16+
import {FUNC_PARSED_FILES_CACHE} from "@server/files"
17+
18+
import {UnusedInspection} from "./UnusedInspection"
19+
import {Inspection, InspectionIds} from "./Inspection"
1820

1921
export class UnusedImpureInspection extends UnusedInspection implements Inspection {
20-
public readonly id: "unused-impure" = InspectionIds.UNUSED_IMPURE;
21-
22-
private impureMap: Map<string, Func>;
23-
private dropableMap: Map<string, Func>;
24-
private resultsCache: Map<string, boolean>;
25-
private impureBuiltins: Set<string>;
26-
27-
constructor() {
28-
super();
29-
this.resultsCache = new Map();
30-
this.impureMap = new Map();
31-
this.dropableMap = new Map();
22+
public readonly id: "unused-impure" = InspectionIds.UNUSED_IMPURE
23+
24+
private readonly impureMap: Map<string, Func>
25+
private readonly dropableMap: Map<string, Func>
26+
private readonly resultsCache: Map<string, boolean>
27+
private readonly impureBuiltins: Set<string>
28+
29+
public constructor() {
30+
super()
31+
this.resultsCache = new Map()
32+
this.impureMap = new Map()
33+
this.dropableMap = new Map()
3234
this.impureBuiltins = new Set([
3335
"throw",
3436
"throw_if",
@@ -37,120 +39,143 @@ export class UnusedImpureInspection extends UnusedInspection implements Inspecti
3739
"throw_arg_op",
3840
"throw_arg_unless",
3941
"~dump",
40-
"~strdump"
41-
]);
42+
"~strdump",
43+
])
4244
}
4345

44-
private getCallDef(call: Node, mode: 'dropable' | 'impure' = 'dropable') {
45-
let callDef: Func | undefined;
46-
const lookupMap = mode == 'dropable' ? this.dropableMap : this.impureMap;
47-
const callType = call.type;
46+
private getCallDef(call: Node, mode: "dropable" | "impure" = "dropable"): Func | undefined {
47+
let callDef: Func | undefined
48+
const lookupMap = mode == "dropable" ? this.dropableMap : this.impureMap
49+
const callType = call.type
4850
if (callType == "function_application") {
49-
const funcIdentifier = call.childForFieldName("callee");
51+
const funcIdentifier = call.childForFieldName("callee")
5052
if (funcIdentifier) {
51-
callDef = lookupMap.get(funcIdentifier.text);
53+
callDef = lookupMap.get(funcIdentifier.text)
5254
}
5355
} else if (callType == "method_call") {
54-
const funcIdentifier = call.childForFieldName("method_name");
56+
const funcIdentifier = call.childForFieldName("method_name")
5557
if (funcIdentifier) {
56-
const methodName = funcIdentifier.text;
57-
callDef = lookupMap.get(methodName);
58-
if (!callDef) {
59-
callDef = lookupMap.get("~" + methodName);
60-
}
58+
const methodName = funcIdentifier.text
59+
callDef = lookupMap.get(methodName)
60+
callDef ??= lookupMap.get("~" + methodName)
6161
}
6262
} else {
63-
throw new Error(`Unsupported call type ${call}`)
63+
throw new Error(`Unsupported call type ${call.toString()}`)
6464
}
6565

66-
return callDef;
66+
return callDef
6767
}
68-
private isImpureBuiltIn(call: Node) {
68+
private isImpureBuiltIn(call: Node): boolean {
69+
let calleeName: Node | null
6970
switch (call.type) {
70-
case "function_application":
71-
return this.impureBuiltins.has(call.childForFieldName("callee")!.text);
72-
case "method_call":
73-
return this.impureBuiltins.has(call.childForFieldName("method_name")!.text);
71+
case "function_application": {
72+
calleeName = call.childForFieldName("callee")
73+
if (calleeName) {
74+
return this.impureBuiltins.has(calleeName.text)
75+
}
76+
break
77+
}
78+
case "method_call": {
79+
calleeName = call.childForFieldName("method_name")
80+
if (calleeName) {
81+
return this.impureBuiltins.has(calleeName.text)
82+
}
83+
}
7484
}
75-
return false;
85+
return false
7686
}
7787

78-
private isCall(call: Node) {
79-
return call.type == "function_application" || call.type == "method_call";
88+
private isCall(call: Node): boolean {
89+
return call.type == "function_application" || call.type == "method_call"
8090
}
8191

82-
private setCache(node: Node, result: boolean) {
83-
const cacheKey = [node.startPosition.row, node.startPosition.column, node.endPosition.row, node.endPosition.column].join(':');
84-
this.resultsCache.set(cacheKey, result);
92+
private setCache(node: Node, result: boolean): void {
93+
const cacheKey = [
94+
node.startPosition.row,
95+
node.startPosition.column,
96+
node.endPosition.row,
97+
node.endPosition.column,
98+
].join(":")
99+
this.resultsCache.set(cacheKey, result)
85100
}
86-
private getCache(node: Node) {
87-
const cacheKey = [node.startPosition.row, node.startPosition.column, node.endPosition.row, node.endPosition.column].join(':');
88-
return this.resultsCache.get(cacheKey);
101+
private getCache(node: Node): boolean | undefined {
102+
const cacheKey = [
103+
node.startPosition.row,
104+
node.startPosition.column,
105+
node.endPosition.row,
106+
node.endPosition.column,
107+
].join(":")
108+
return this.resultsCache.get(cacheKey)
89109
}
90110

91111
protected checkFile(file: FuncFile, diagnostics: lsp.Diagnostic[]): void {
92112
// Populate impure functions map
93113
FUNC_PARSED_FILES_CACHE.forEach(parsedFile => {
94114
parsedFile.getFunctions().forEach(f => {
95115
if (f.isImpure) {
96-
this.impureMap.set(f.name(true), f);
116+
this.impureMap.set(f.name(true), f)
97117
} else {
98-
this.dropableMap.set(f.name(true), f);
118+
this.dropableMap.set(f.name(true), f)
99119
}
100-
});
120+
})
101121
})
102-
const bindResolver = new FunCBindingResolver(file);
122+
const bindResolver = new FunCBindingResolver(file)
103123
RecursiveVisitor.visit(file.rootNode, (node): boolean => {
104124
if (!this.isCall(node)) {
105-
return true;
125+
return true
106126
}
107-
let willDrop = false;
127+
let willDrop = false
108128
// Skip impure builtins calls
109129
if (this.isImpureBuiltIn(node)) {
110-
return true;
130+
return true
111131
}
112132
// const droppableDef = this.getCallDef(node)
113133
if (this.checkCallWillDrop(node, file, bindResolver)) {
114-
willDrop = true;
115-
const range = asLspRange(node);
134+
willDrop = true
135+
const range = asLspRange(node)
116136
diagnostics.push({
117137
severity: lsp.DiagnosticSeverity.Error,
118-
code: 'unused-impure',
138+
code: "unused-impure",
119139
range,
120140
message: "This call will be dropped due to lack of impure specifier!",
121-
source: "func"
141+
source: "func",
122142
})
123143
}
124-
this.setCache(node, willDrop);
125-
return true;
144+
this.setCache(node, willDrop)
145+
return true
126146
})
127147
}
128148

129-
private checkCallWillDrop(node: Node, file: FuncFile, bindResolver: FunCBindingResolver) {
130-
const cachedRes = this.getCache(node);
149+
private checkCallWillDrop(
150+
node: Node,
151+
file: FuncFile,
152+
bindResolver: FunCBindingResolver,
153+
): boolean {
154+
const cachedRes = this.getCache(node)
131155
if (cachedRes !== undefined) {
132-
return cachedRes;
156+
return cachedRes
133157
}
134158

135-
const definition = this.getCallDef(node, 'dropable')
159+
const definition = this.getCallDef(node, "dropable")
136160

137161
if (!definition) {
138162
// If no dropable def found, check that impure is implicit just in case
139-
const willDrop = !(this.getCallDef(node, 'impure') || this.isImpureBuiltIn(node))
140-
this.setCache(node, willDrop);
141-
return willDrop;
163+
const willDrop = !(this.getCallDef(node, "impure") ?? this.isImpureBuiltIn(node))
164+
this.setCache(node, willDrop)
165+
return willDrop
142166
}
143167

144-
const returnExp = definition.returnType();
168+
const returnExp = definition.returnType()
145169
if (returnExp !== null) {
146170
// If return type of a function is empty tensor - check no more.
147-
if (returnExp.node.text == '()') {
148-
return true;
171+
if (returnExp.node.text == "()") {
172+
return true
149173
}
150174
}
151-
const expressionParent = parentOfTypeWithCb<{ parent: Node, origin: Node }>(node,
175+
const expressionParent = parentOfTypeWithCb<{parent: Node; origin: Node}>(
176+
node,
152177
(parent, origin) => {
153-
return { parent, origin }
178+
return {parent, origin}
154179
},
155180
"expression_statement",
156181
"return_statement",
@@ -160,13 +185,13 @@ export class UnusedImpureInspection extends UnusedInspection implements Inspecti
160185
"while_statement",
161186
"do_while_statement",
162187
"repeat_statement",
163-
"return_statement"
164-
);
188+
"return_statement",
189+
)
165190
if (!expressionParent) {
166191
// Could happen in incomplete code
167-
return false;
192+
return false
168193
}
169-
const parentType = expressionParent.parent.type;
194+
const parentType = expressionParent.parent.type
170195
// If call is in the block_statement of any kind, it will be a child of expression_statement
171196
// Otherwise it is in condition block of if/while/do while
172197
// Or in arguments clause of other function_application/method_call
@@ -175,58 +200,62 @@ export class UnusedImpureInspection extends UnusedInspection implements Inspecti
175200
return this.checkCallWillDrop(expressionParent.parent, file, bindResolver)
176201
}
177202
// If expression is in condition or return statement it will not be dropped
178-
return false;
203+
return false
179204
}
180205

181206
// We are in the expression expression_statement
182207
// Bind the values from the expression
183-
const resolvedBinding = bindResolver.resolve(expressionParent.parent);
208+
const resolvedBinding = bindResolver.resolve(expressionParent.parent)
184209
// If no lvalue, non-impure call will drop
185-
if (resolvedBinding.bindings.size == 0) {
186-
return true;
210+
if (resolvedBinding.bindings.size === 0) {
211+
return true
187212
}
188213
// If no identifiers referenced in lvalue, means those are whole type and will be dropped
189214
// const affectedIdentifiers = resolvedBinding.bindings.values()
190215

191-
for (let boundValue of resolvedBinding.bindings.values()) {
216+
for (const boundValue of resolvedBinding.bindings.values()) {
192217
// Find references to the bound variables from below the current expression.
193-
const references = new Referent(boundValue.identifier, file).findReferences({ limit: Infinity }).filter(
194-
ref => ref.node.startIndex >= expressionParent.parent.endIndex
195-
);
218+
const references = new Referent(boundValue.identifier, file)
219+
.findReferences({limit: Infinity})
220+
.filter(ref => ref.node.startIndex >= expressionParent.parent.endIndex)
196221
// Has to be referenced in non impure call, conditional or return statement to not drop
197-
for (let ref of references) {
198-
const parent = parentOfType(ref.node,
222+
for (const ref of references) {
223+
const parent = parentOfType(
224+
ref.node,
199225
"expression_statement", // But don't go above expression_statement
200226
"function_application",
201227
"method_call",
202228
"if_statement",
203229
"while_statement",
204230
"do_while_statement",
205231
"repeat_statement",
206-
"return_statement"
232+
"return_statement",
207233
)
208234
if (!parent) {
209-
continue;
235+
continue
210236
}
211237
if (parent.type !== "expression_statement") {
212-
let willDrop = false;
238+
let willDrop = false
213239
if (this.isCall(parent)) {
214240
willDrop = this.checkCallWillDrop(parent, file, bindResolver)
215-
this.setCache(parent, willDrop);
241+
this.setCache(parent, willDrop)
216242
}
217-
return willDrop;
243+
return willDrop
218244
}
219245
// Check reference in method call
220-
const refSibling = closestNamedSibling(ref.node, 'next', (sibl => sibl.type == "method_call"))
246+
const refSibling = closestNamedSibling(
247+
ref.node,
248+
"next",
249+
sibl => sibl.type == "method_call",
250+
)
221251
if (refSibling) {
222252
// If this is a droppable call, go to next ref, else expression is not droppable
223253
if (!this.checkCallWillDrop(refSibling, file, bindResolver)) {
224-
return false;
254+
return false
225255
}
226256
}
227257
}
228258
}
229-
return true;
259+
return true
230260
}
231261
}
232-

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import * as lsp from "vscode-languageserver"
22

3-
import { connection } from "@server/connection"
4-
import { getDocumentSettings } from "@server/settings/settings"
5-
import { FuncFile } from "@server/languages/func/psi/FuncFile"
6-
import { UnusedParameterInspection } from "@server/languages/func/inspections/UnusedParameterInspection"
7-
import { UnusedVariableInspection } from "@server/languages/func/inspections/UnusedVariableInspection"
8-
import { UnusedImportInspection } from "@server/languages/func/inspections/UnusedImportInspection"
9-
import { UnusedTypeParameterInspection } from "@server/languages/func/inspections/UnusedTypeParameterInspection"
10-
import { UnusedImpureInspection } from "./UnusedImpure"
3+
import {connection} from "@server/connection"
4+
import {getDocumentSettings} from "@server/settings/settings"
5+
import {FuncFile} from "@server/languages/func/psi/FuncFile"
6+
import {UnusedParameterInspection} from "@server/languages/func/inspections/UnusedParameterInspection"
7+
import {UnusedVariableInspection} from "@server/languages/func/inspections/UnusedVariableInspection"
8+
import {UnusedImportInspection} from "@server/languages/func/inspections/UnusedImportInspection"
9+
import {UnusedTypeParameterInspection} from "@server/languages/func/inspections/UnusedTypeParameterInspection"
10+
11+
import {UnusedImpureInspection} from "./UnusedImpure"
1112

1213
export async function runFuncInspections(
1314
uri: string,
@@ -25,7 +26,6 @@ export async function runFuncInspections(
2526
const settings = await getDocumentSettings(uri)
2627
const diagnostics: lsp.Diagnostic[] = []
2728

28-
2929
for (const inspection of inspections) {
3030
if (settings.func.inspections.disabled.includes(inspection.id)) {
3131
continue

0 commit comments

Comments
 (0)