@slippy-lint/slippy
Version:
A simple but powerful linter for Solidity
61 lines • 2.27 kB
JavaScript
import { Parameters } from "@nomicfoundation/slang/ast";
import { assertNonterminalNode, NonterminalKind, Query, } from "@nomicfoundation/slang/cst";
import * as z from "zod";
import { ignoreLeadingTrivia } from "../slang/trivia.js";
const RETURN_PARAMS_QUERY = Query.create(`
[ReturnsDeclaration
[ParametersDeclaration
@params [Parameters]
]
]`);
const DEFAULT_MIN_PARAMS = 2;
const ConfigSchema = z
.strictObject({
minParams: z.number().default(DEFAULT_MIN_PARAMS),
})
.default({ minParams: DEFAULT_MIN_PARAMS });
export const NamedReturnParams = {
name: "named-return-params",
recommended: true,
parseConfig: (config) => ConfigSchema.parse(config),
create: function (config) {
return new NamedReturnParamsRule(this.name, config);
},
};
class NamedReturnParamsRule {
constructor(name, config) {
this.name = name;
this.config = config;
}
run({ file }) {
const diagnostics = [];
const cursor = file.createTreeCursor();
const matches = cursor.query([RETURN_PARAMS_QUERY]);
for (const match of matches) {
const paramsCursor = match.captures.params[0];
assertNonterminalNode(paramsCursor.node, NonterminalKind.Parameters);
const params = new Parameters(paramsCursor.node);
if (params.items.length < this.config.minParams) {
continue;
}
const textRangeCursor = match.root.spawn();
for (const param of params.items) {
while (textRangeCursor.node.id !== param.cst.id) {
textRangeCursor.goToNextNonterminalWithKind(NonterminalKind.Parameter);
}
ignoreLeadingTrivia(textRangeCursor);
if (param.name === undefined) {
diagnostics.push({
rule: this.name,
sourceId: file.id,
line: textRangeCursor.textRange.start.line,
column: textRangeCursor.textRange.start.column,
message: "Unnamed return parameter",
});
}
}
}
return diagnostics;
}
}
//# sourceMappingURL=named-return-params.js.map