@slippy-lint/slippy
Version:
A simple but powerful linter for Solidity
101 lines • 4.77 kB
JavaScript
import { ConstantDefinition, ContractDefinition, EnumDefinition, ErrorDefinition, EventDefinition, FunctionDefinition, InterfaceDefinition, LibraryDefinition, ModifierDefinition, StateVariableDefinition, StructDefinition, UserDefinedValueTypeDefinition, VariableDeclarationStatement, } from "@nomicfoundation/slang/ast";
import { assertNonterminalNode, NonterminalKind, } from "@nomicfoundation/slang/cst";
import * as z from "zod";
import { AssertionError } from "../errors.js";
const DEFAULT_DENYLIST = ["I", "l", "O"];
const Schema = z.array(z.string()).default(DEFAULT_DENYLIST);
export const IdDenylist = {
name: "id-denylist",
recommended: true,
parseConfig: (config) => {
return Schema.parse(config);
},
create: function (config) {
return new IdDenylistRule(this.name, config);
},
};
class IdDenylistRule {
constructor(name, config) {
this.name = name;
this.config = config;
}
run({ file }) {
const diagnostics = [];
const cursor = file.createTreeCursor();
while (cursor.goToNextNonterminalWithKinds([
NonterminalKind.ContractDefinition,
NonterminalKind.InterfaceDefinition,
NonterminalKind.LibraryDefinition,
NonterminalKind.StructDefinition,
NonterminalKind.EnumDefinition,
NonterminalKind.ConstantDefinition,
NonterminalKind.StateVariableDefinition,
NonterminalKind.FunctionDefinition,
NonterminalKind.ModifierDefinition,
NonterminalKind.EventDefinition,
NonterminalKind.UserDefinedValueTypeDefinition,
NonterminalKind.ErrorDefinition,
NonterminalKind.VariableDeclarationStatement,
])) {
assertNonterminalNode(cursor.node);
let nameNode;
if (cursor.node.kind === NonterminalKind.ContractDefinition) {
nameNode = new ContractDefinition(cursor.node).name;
}
else if (cursor.node.kind === NonterminalKind.InterfaceDefinition) {
nameNode = new InterfaceDefinition(cursor.node).name;
}
else if (cursor.node.kind === NonterminalKind.LibraryDefinition) {
nameNode = new LibraryDefinition(cursor.node).name;
}
else if (cursor.node.kind === NonterminalKind.StructDefinition) {
nameNode = new StructDefinition(cursor.node).name;
}
else if (cursor.node.kind === NonterminalKind.EnumDefinition) {
nameNode = new EnumDefinition(cursor.node).name;
}
else if (cursor.node.kind === NonterminalKind.ConstantDefinition) {
nameNode = new ConstantDefinition(cursor.node).name;
}
else if (cursor.node.kind === NonterminalKind.StateVariableDefinition) {
nameNode = new StateVariableDefinition(cursor.node).name;
}
else if (cursor.node.kind === NonterminalKind.FunctionDefinition) {
nameNode = new FunctionDefinition(cursor.node).name.variant;
}
else if (cursor.node.kind === NonterminalKind.ModifierDefinition) {
nameNode = new ModifierDefinition(cursor.node).name;
}
else if (cursor.node.kind === NonterminalKind.EventDefinition) {
nameNode = new EventDefinition(cursor.node).name;
}
else if (cursor.node.kind === NonterminalKind.UserDefinedValueTypeDefinition) {
nameNode = new UserDefinedValueTypeDefinition(cursor.node).name;
}
else if (cursor.node.kind === NonterminalKind.ErrorDefinition) {
nameNode = new ErrorDefinition(cursor.node).name;
}
else if (cursor.node.kind === NonterminalKind.VariableDeclarationStatement) {
nameNode = new VariableDeclarationStatement(cursor.node).name;
}
else {
throw new AssertionError(`Unexpected node kind: ${cursor.node.kind}`);
}
const contractName = nameNode.unparse();
while (cursor.node.id !== nameNode.id && cursor.goToNext()) {
// continue until we reach the name node
}
if (this.config.includes(contractName)) {
diagnostics.push({
rule: this.name,
message: `Identifier '${contractName}' is restricted`,
sourceId: file.id,
line: cursor.textRange.start.line,
column: cursor.textRange.start.column,
});
}
}
return diagnostics;
}
}
//# sourceMappingURL=id-denylist.js.map