eslint-plugin-sonarjs
Version:
SonarJS rules for ESLint
64 lines (63 loc) • 3.05 kB
JavaScript
/*
* SonarQube JavaScript Plugin
* Copyright (C) 2011-2025 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the Sonar Source-Available License for more details.
*
* You should have received a copy of the Sonar Source-Available License
* along with this program; if not, see https://sonarsource.com/license/ssal/
*/
// https://sonarsource.github.io/rspec/#/rspec/S3513/javascript
Object.defineProperty(exports, "__esModule", { value: true });
exports.rule = void 0;
const index_js_1 = require("../helpers/index.js");
const meta_js_1 = require("./meta.js");
const MESSAGE = "Use the rest syntax to declare this function's arguments.";
const SECONDARY_MESSAGE = 'Replace this reference to "arguments".';
exports.rule = {
meta: (0, index_js_1.generateMeta)(meta_js_1.meta, undefined, true),
create(context) {
return {
// Ignore root scope containing global variables
'Program:exit': (node) => context.sourceCode
.getScope(node)
.childScopes.forEach(child => checkArgumentsUsageInScopeRecursively(context, child)),
};
},
};
function checkArgumentsUsageInScopeRecursively(context, scope) {
scope.variables
.filter(variable => variable.name === 'arguments')
.forEach(variable => checkArgumentsVariableWithoutDefinition(context, variable));
scope.childScopes.forEach(child => checkArgumentsUsageInScopeRecursively(context, child));
}
function checkArgumentsVariableWithoutDefinition(context, variable) {
// if variable is a parameter, variable.defs contains one ParameterDefinition with a type: 'Parameter'
// if variable is a local variable, variable.defs contains one Definition with a type: 'Variable'
// but if variable is the function arguments, variable.defs is just empty without other hint
const isLocalVariableOrParameter = variable.defs.length > 0;
const references = variable.references.filter(ref => !isFollowedByLengthProperty(ref));
if (!isLocalVariableOrParameter && references.length > 0) {
const firstReference = references[0];
const secondaryLocations = references.slice(1).map(ref => ref.identifier);
(0, index_js_1.report)(context, {
node: firstReference.identifier,
message: MESSAGE,
}, secondaryLocations.map(node => (0, index_js_1.toSecondaryLocation)(node, SECONDARY_MESSAGE)));
}
}
function isFollowedByLengthProperty(reference) {
const parent = reference.identifier.parent;
return (!!parent &&
parent.type === 'MemberExpression' &&
parent.property.type === 'Identifier' &&
parent.property.name === 'length');
}
;