New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

eslint-plugin-sonarjs

Package Overview
Dependencies
Maintainers
6
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-sonarjs - npm Package Compare versions

Comparing version 0.8.0-125 to 0.9.0

lib/rules/elseif-without-else.d.ts

8

lib/index.d.ts

@@ -1,5 +0,7 @@

import { Linter } from "eslint";
declare const sonarjsRuleModules: any;
import { TSESLint } from '@typescript-eslint/experimental-utils';
declare const sonarjsRuleModules: {
[key: string]: any;
};
declare const configs: {
recommended: Linter.Config & {
recommended: TSESLint.Linter.Config & {
plugins: string[];

@@ -6,0 +8,0 @@ };

@@ -5,27 +5,35 @@ "use strict";

const sonarjsRules = [
["cognitive-complexity", "error"],
["max-switch-cases", "error"],
["no-all-duplicated-branches", "error"],
["no-collapsible-if", "error"],
["no-collection-size-mischeck", "error"],
["no-duplicate-string", "error"],
["no-duplicated-branches", "error"],
["no-element-overwrite", "error"],
["no-extra-arguments", "error"],
["no-identical-conditions", "error"],
["no-identical-functions", "error"],
["no-identical-expressions", "error"],
["no-inverted-boolean-check", "error"],
["no-one-iteration-loop", "error"],
["no-redundant-boolean", "error"],
["no-redundant-jump", "error"],
["no-same-line-conditional", "error"],
["no-small-switch", "error"],
["no-unused-collection", "error"],
["no-use-of-empty-return-value", "error"],
["no-useless-catch", "error"],
["prefer-immediate-return", "error"],
["prefer-object-literal", "error"],
["prefer-single-boolean-return", "error"],
["prefer-while", "error"],
'cognitive-complexity',
'elseif-without-else',
'generator-without-yield',
'max-switch-cases',
'no-all-duplicated-branches',
'no-collapsible-if',
'no-collection-size-mischeck',
'no-duplicate-string',
'no-duplicated-branches',
'no-element-overwrite',
'no-empty-collection',
'no-extra-arguments',
'no-gratuitous-expressions',
'no-identical-conditions',
'no-identical-expressions',
'no-identical-functions',
'no-ignored-return',
'no-inverted-boolean-check',
'no-nested-switch',
'no-nested-template-literals',
'no-one-iteration-loop',
'no-redundant-boolean',
'no-redundant-jump',
'no-same-line-conditional',
'no-small-switch',
'no-unused-collection',
'no-use-of-empty-return-value',
'no-useless-catch',
'non-existent-operator',
'prefer-immediate-return',
'prefer-object-literal',
'prefer-single-boolean-return',
'prefer-while',
];

@@ -35,7 +43,10 @@ const sonarjsRuleModules = {};

const configs = {
recommended: { plugins: ["sonarjs"], rules: {} },
recommended: { plugins: ['sonarjs'], rules: {} },
};
exports.configs = configs;
sonarjsRules.forEach(rule => (sonarjsRuleModules[rule[0]] = require(`./rules/${rule[0]}`)));
sonarjsRules.forEach(rule => (configs.recommended.rules[`sonarjs/${rule[0]}`] = rule[1]));
sonarjsRules.forEach(rule => {
sonarjsRuleModules[rule] = require(`./rules/${rule}`);
const { meta: { docs: { recommended }, }, } = sonarjsRuleModules[rule];
configs.recommended.rules[`sonarjs/${rule}`] = recommended === false ? 'off' : recommended;
});
//# sourceMappingURL=index.js.map

@@ -1,3 +0,4 @@

import { Rule } from "eslint";
declare const rule: Rule.RuleModule;
import { Rule } from '../utils/types';
declare type Options = [number, 'metric'];
declare const rule: Rule.RuleModule<string, Options>;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,14 +21,21 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-3776
// https://sonarsource.github.io/rspec/#/rspec/S3776
const nodes_1 = require("../utils/nodes");
const locations_1 = require("../utils/locations");
const docs_url_1 = require("../utils/docs-url");
const DEFAULT_THRESHOLD = 15;
const rule = {
meta: {
type: "suggestion",
type: 'suggestion',
docs: {
description: 'Cognitive Complexity of functions should not be too high',
category: 'Best Practices',
recommended: 'error',
url: docs_url_1.default(__filename),
},
schema: [
{ type: "integer", minimum: 0 },
{ type: 'integer', minimum: 0 },
{
// internal parameter
enum: ["sonar-runtime", "metric"],
enum: ['sonar-runtime', 'metric'],
},

@@ -39,3 +46,3 @@ ],

const threshold = getThreshold();
const isFileComplexity = context.options.includes("metric");
const isFileComplexity = context.options.includes('metric');
/** Complexity of the file */

@@ -58,4 +65,4 @@ let fileComplexity = 0;

},
init(_node) {
this.nameStartsWithCapital = nameStartsWithCapital(_node);
init(node) {
this.nameStartsWithCapital = nameStartsWithCapital(node);
this.returnsJsx = false;

@@ -74,9 +81,9 @@ },

return {
":function": (node) => {
':function': (node) => {
onEnterFunction(node);
},
":function:exit"(node) {
':function:exit'(node) {
onLeaveFunction(node);
},
"*"(node) {
'*'(node) {
if (nestingNodes.has(node)) {

@@ -86,3 +93,3 @@ nesting++;

},
"*:exit"(node) {
'*:exit'(node) {
if (nestingNodes.has(node)) {

@@ -96,3 +103,3 @@ nesting--;

},
"Program:exit"(node) {
'Program:exit'(node) {
if (isFileComplexity) {

@@ -175,6 +182,6 @@ // as issues are the only communication channel of a rule

});
checkFunction(totalComplexity, locations_1.getMainFunctionTokenLocation(node, nodes_1.getParent(context), context));
checkFunction(totalComplexity, locations_1.getMainFunctionTokenLocation(node, node.parent, context));
}
else {
checkFunction(topLevelOwnComplexity, locations_1.getMainFunctionTokenLocation(node, nodes_1.getParent(context), context));
checkFunction(topLevelOwnComplexity, locations_1.getMainFunctionTokenLocation(node, node.parent, context));
secondLevelFunctions.forEach(secondLevelFunction => {

@@ -189,6 +196,6 @@ checkFunction(secondLevelFunction.complexityIfThisSecondaryIsTopLevel, locations_1.getMainFunctionTokenLocation(secondLevelFunction.node, secondLevelFunction.parent, context));

node,
parent: nodes_1.getParent(context),
parent: node.parent,
complexityIfNested,
complexityIfThisSecondaryIsTopLevel: complexityIfNotNested,
loc: locations_1.getMainFunctionTokenLocation(node, nodes_1.getParent(context), context),
loc: locations_1.getMainFunctionTokenLocation(node, node.parent, context),
});

@@ -202,3 +209,3 @@ }

function visitIfStatement(ifStatement) {
const parent = nodes_1.getParent(context);
const { parent } = ifStatement;
const { loc: ifLoc } = locations_1.getFirstToken(ifStatement, context);

@@ -250,3 +257,5 @@ // if the current `if` statement is `else if`, do not count it in structural complexity

// top level function
if (enclosingFunctions.length === 1 && argument && argument.type === "JSXElement") {
if (enclosingFunctions.length === 1 &&
argument &&
['JSXElement', 'JSXFragment'].includes(argument.type)) {
reactFunctionalComponent.returnsJsx = true;

@@ -263,4 +272,4 @@ }

}
const parent = nodes_1.getParent(context);
if (parent && parent.type === "VariableDeclarator" && parent.id.type === "Identifier") {
const { parent } = node;
if (parent && parent.type === 'VariableDeclarator' && parent.id.type === 'Identifier') {
return checkFirstLetter(parent.id.name);

@@ -286,3 +295,7 @@ }

consideredLogicalExpressions.add(node);
return [...flattenLogicalExpression(node.left), node, ...flattenLogicalExpression(node.right)];
return [
...flattenLogicalExpression(node.left),
node,
...flattenLogicalExpression(node.right),
];
}

@@ -334,3 +347,3 @@ return [];

const { complexity, location } = complexityPoint;
const message = complexity === 1 ? "+1" : `+${complexity} (incl. ${complexity - 1} for nesting)`;
const message = complexity === 1 ? '+1' : `+${complexity} (incl. ${complexity - 1} for nesting)`;
return locations_1.issueLocation(location, undefined, message);

@@ -337,0 +350,0 @@ });

@@ -1,3 +0,4 @@

import { Rule } from "eslint";
declare const rule: Rule.RuleModule;
import { Rule } from '../utils/types';
declare type Options = [number];
declare const rule: Rule.RuleModule<string, Options>;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,4 +21,5 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-1479
const MESSAGE = "Reduce the number of non-empty switch cases from {{numSwitchCases}} to at most {{maxSwitchCases}}.";
// https://sonarsource.github.io/rspec/#/rspec/S1479
const docs_url_1 = require("../utils/docs-url");
const MESSAGE = 'Reduce the number of non-empty switch cases from {{numSwitchCases}} to at most {{maxSwitchCases}}.';
const DEFAULT_MAX_SWITCH_CASES = 30;

@@ -28,6 +29,12 @@ let maxSwitchCases = DEFAULT_MAX_SWITCH_CASES;

meta: {
type: "suggestion",
type: 'suggestion',
docs: {
description: '"switch" statements should not have too many "case" clauses',
category: 'Best Practices',
recommended: 'error',
url: docs_url_1.default(__filename),
},
schema: [
{
type: "integer",
type: 'integer',
minimum: 0,

@@ -41,3 +48,5 @@ },

}
return { SwitchStatement: (node) => visitSwitchStatement(node, context) };
return {
SwitchStatement: (node) => visitSwitchStatement(node, context),
};
},

@@ -52,3 +61,6 @@ };

loc: switchKeyword.loc,
data: { numSwitchCases: nonEmptyCases.length.toString(), maxSwitchCases: maxSwitchCases.toString() },
data: {
numSwitchCases: nonEmptyCases.length.toString(),
maxSwitchCases: maxSwitchCases.toString(),
},
});

@@ -55,0 +67,0 @@ }

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,6 +21,7 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-3923
// https://sonarsource.github.io/rspec/#/rspec/S3923
const nodes_1 = require("../utils/nodes");
const equivalence_1 = require("../utils/equivalence");
const conditions_1 = require("../utils/conditions");
const docs_url_1 = require("../utils/docs-url");
const MESSAGE = "Remove this conditional structure or edit its code blocks so that they're not all the same.";

@@ -30,3 +31,9 @@ const MESSAGE_CONDITIONAL_EXPRESSION = 'This conditional operation returns the same value whether the condition is "true" or "false".';

meta: {
type: "problem",
type: 'problem',
docs: {
description: 'All branches in a conditional structure should not have exactly the same implementation',
category: 'Possible Errors',
recommended: 'error',
url: docs_url_1.default(__filename),
},
},

@@ -38,4 +45,3 @@ create(context) {

// don't visit `else if` statements
const parent = nodes_1.getParent(context);
if (!nodes_1.isIfStatement(parent)) {
if (!nodes_1.isIfStatement(node.parent)) {
const { branches, endsWithElse } = conditions_1.collectIfBranches(ifStmt);

@@ -42,0 +48,0 @@ if (endsWithElse && allDuplicated(branches)) {

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,12 +21,19 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-1066
// https://sonarsource.github.io/rspec/#/rspec/S1066
const nodes_1 = require("../utils/nodes");
const locations_1 = require("../utils/locations");
const docs_url_1 = require("../utils/docs-url");
const rule = {
meta: {
type: "suggestion",
type: 'suggestion',
docs: {
description: 'Collapsible "if" statements should be merged',
category: 'Best Practices',
recommended: 'error',
url: docs_url_1.default(__filename),
},
schema: [
{
// internal parameter
enum: ["sonar-runtime"],
enum: ['sonar-runtime'],
},

@@ -33,0 +40,0 @@ ],

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,9 +21,16 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-3981
// https://sonarsource.github.io/rspec/#/rspec/S3981
const parser_services_1 = require("../utils/parser-services");
const CollectionLike = ["Array", "Map", "Set", "WeakMap", "WeakSet"];
const CollectionSizeLike = ["length", "size"];
const docs_url_1 = require("../utils/docs-url");
const CollectionLike = ['Array', 'Map', 'Set', 'WeakMap', 'WeakSet'];
const CollectionSizeLike = ['length', 'size'];
const rule = {
meta: {
type: "problem",
type: 'problem',
docs: {
description: 'Collection sizes and array length comparisons should make sense',
category: 'Possible Errors',
recommended: 'error',
url: docs_url_1.default(__filename),
},
},

@@ -36,10 +43,10 @@ create(context) {

const expr = node;
if (["<", ">="].includes(expr.operator)) {
if (['<', '>='].includes(expr.operator)) {
const lhs = expr.left;
const rhs = expr.right;
if (isZeroLiteral(rhs) && lhs.type === "MemberExpression") {
if (isZeroLiteral(rhs) && lhs.type === 'MemberExpression') {
const { object, property } = lhs;
if (property.type === "Identifier" &&
if (property.type === 'Identifier' &&
CollectionSizeLike.includes(property.name) &&
(!isTypeCheckerAvailable || isCollection(object, services))) {
(!isTypeCheckerAvailable || (services && isCollection(object, services)))) {
context.report({

@@ -59,3 +66,3 @@ message: `Fix this expression; ${property.name} of "${context

function isZeroLiteral(node) {
return node.type === "Literal" && node.value === 0;
return node.type === 'Literal' && node.value === 0;
}

@@ -62,0 +69,0 @@ function isCollection(node, services) {

@@ -1,3 +0,4 @@

import { Rule } from "eslint";
declare const rule: Rule.RuleModule;
import { Rule } from '../utils/types';
declare type Options = [number];
declare const rule: Rule.RuleModule<string, Options>;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,4 +21,4 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-1192
const nodes_1 = require("../utils/nodes");
// https://sonarsource.github.io/rspec/#/rspec/S1192
const docs_url_1 = require("../utils/docs-url");
// Number of times a literal must be duplicated to trigger an issue

@@ -28,8 +28,19 @@ const DEFAULT_THRESHOLD = 3;

const NO_SEPARATOR_REGEXP = /^\w*$/;
const EXCLUDED_CONTEXTS = ["ImportDeclaration", "JSXAttribute", "ExportAllDeclaration", "ExportNamedDeclaration"];
const MESSAGE = "Define a constant instead of duplicating this literal {{times}} times.";
const EXCLUDED_CONTEXTS = [
'ImportDeclaration',
'JSXAttribute',
'ExportAllDeclaration',
'ExportNamedDeclaration',
];
const MESSAGE = 'Define a constant instead of duplicating this literal {{times}} times.';
const rule = {
meta: {
type: "suggestion",
schema: [{ type: "integer", minimum: 2 }],
type: 'suggestion',
docs: {
description: 'String literals should not be duplicated',
category: 'Best Practices',
recommended: 'error',
url: docs_url_1.default(__filename),
},
schema: [{ type: 'integer', minimum: 2 }],
},

@@ -42,5 +53,6 @@ create(context) {

const literal = node;
const parent = nodes_1.getParent(context);
if (typeof literal.value === "string" &&
(parent && !["ExpressionStatement", "TSLiteralType"].includes(parent.type))) {
const { parent } = literal;
if (typeof literal.value === 'string' &&
parent &&
!['ExpressionStatement', 'TSLiteralType'].includes(parent.type)) {
const stringContent = literal.value.trim();

@@ -56,3 +68,3 @@ if (!isExcludedByUsageContext(context, literal) &&

},
"Program:exit"() {
'Program:exit'() {
literalsByValue.forEach(literals => {

@@ -72,13 +84,15 @@ if (literals.length >= threshold) {

function isExcludedByUsageContext(context, literal) {
const parent = nodes_1.getParent(context);
const parent = literal.parent;
const parentType = parent.type;
return (EXCLUDED_CONTEXTS.includes(parentType) || isRequireContext(parent, context) || isObjectPropertyKey(parent, literal));
return (EXCLUDED_CONTEXTS.includes(parentType) ||
isRequireContext(parent, context) ||
isObjectPropertyKey(parent, literal));
}
function isRequireContext(parent, context) {
return parent.type === "CallExpression" && context.getSourceCode().getText(parent.callee) === "require";
return (parent.type === 'CallExpression' && context.getSourceCode().getText(parent.callee) === 'require');
}
function isObjectPropertyKey(parent, literal) {
return parent.type === "Property" && parent.key === literal;
return parent.type === 'Property' && parent.key === literal;
}
module.exports = rule;
//# sourceMappingURL=no-duplicate-string.js.map

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,3 +21,3 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-1871
// https://sonarsource.github.io/rspec/#/rspec/S1871
const nodes_1 = require("../utils/nodes");

@@ -27,10 +27,17 @@ const equivalence_1 = require("../utils/equivalence");

const locations_1 = require("../utils/locations");
const docs_url_1 = require("../utils/docs-url");
const MESSAGE = "This {{type}}'s code block is the same as the block for the {{type}} on line {{line}}.";
const rule = {
meta: {
type: "problem",
type: 'problem',
docs: {
description: 'Two branches in a conditional structure should not have exactly the same implementation',
category: 'Possible Errors',
recommended: 'error',
url: docs_url_1.default(__filename),
},
schema: [
{
// internal parameter
enum: ["sonar-runtime"],
enum: ['sonar-runtime'],
},

@@ -49,4 +56,3 @@ ],

function visitIfStatement(ifStmt) {
const parent = nodes_1.getParent(context);
if (nodes_1.isIfStatement(parent)) {
if (nodes_1.isIfStatement(ifStmt.parent)) {
return;

@@ -56,3 +62,3 @@ }

if (allEquivalentWithoutDefault(branches, endsWithElse)) {
branches.slice(1).forEach((branch, i) => reportIssue(branch, branches[i], "branch"));
branches.slice(1).forEach((branch, i) => reportIssue(branch, branches[i], 'branch'));
return;

@@ -76,3 +82,5 @@ }

if (allEquivalentWithoutDefault(casesWithoutBreak, endsWithDefault)) {
nonEmptyCases.slice(1).forEach((caseStmt, i) => reportIssue(caseStmt, nonEmptyCases[i], "case"));
nonEmptyCases
.slice(1)
.forEach((caseStmt, i) => reportIssue(caseStmt, nonEmptyCases[i], 'case'));
return;

@@ -86,3 +94,3 @@ }

if (equivalence_1.areEquivalent(firstClauseWithoutBreak, secondClauseWithoutBreak, context.getSourceCode())) {
reportIssue(cases[i], cases[j], "case");
reportIssue(cases[i], cases[j], 'case');
break;

@@ -99,4 +107,4 @@ }

...context.getSourceCode().getTokens(nodes[nodes.length - 1]),
].filter(token => token.value !== "{" && token.value !== "}");
return tokens.length > 0 && tokens[tokens.length - 1].loc.end.line > tokens[0].loc.start.line;
].filter(token => token.value !== '{' && token.value !== '}');
return (tokens.length > 0 && tokens[tokens.length - 1].loc.end.line > tokens[0].loc.start.line);
}

@@ -108,3 +116,3 @@ return false;

if (equivalent && b.loc) {
reportIssue(a, b, "branch");
reportIssue(a, b, 'branch');
}

@@ -125,9 +133,9 @@ return equivalent;

branches.length > 1 &&
branches.slice(1).every((branch, index) => equivalence_1.areEquivalent(branch, branches[index], context.getSourceCode())));
branches
.slice(1)
.every((branch, index) => equivalence_1.areEquivalent(branch, branches[index], context.getSourceCode())));
}
function reportIssue(node, equivalentNode, type) {
const equivalentNodeLoc = equivalentNode.loc;
locations_1.report(context, { message: MESSAGE, data: { type, line: String(equivalentNode.loc.start.line) }, node }, [
locations_1.issueLocation(equivalentNodeLoc, equivalentNodeLoc, "Original"),
]);
locations_1.report(context, { message: MESSAGE, data: { type, line: String(equivalentNode.loc.start.line) }, node }, [locations_1.issueLocation(equivalentNodeLoc, equivalentNodeLoc, 'Original')]);
}

@@ -134,0 +142,0 @@ },

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,14 +21,21 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-4143
// https://sonarsource.github.io/rspec/#/rspec/S4143
const equivalence_1 = require("../utils/equivalence");
const nodes_1 = require("../utils/nodes");
const locations_1 = require("../utils/locations");
const docs_url_1 = require("../utils/docs-url");
const message = (index, line) => `Verify this is the index that was intended; "${index}" was already set on line ${line}.`;
const rule = {
meta: {
type: "problem",
type: 'problem',
docs: {
description: 'Collection elements should not be replaced unconditionally',
category: 'Possible Errors',
recommended: 'error',
url: docs_url_1.default(__filename),
},
schema: [
{
// internal parameter
enum: ["sonar-runtime"],
enum: ['sonar-runtime'],
},

@@ -58,3 +65,4 @@ ],

if (keyWriteUsage) {
if (collection && !equivalence_1.areEquivalent(keyWriteUsage.collectionNode, collection, context.getSourceCode())) {
if (collection &&
!equivalence_1.areEquivalent(keyWriteUsage.collectionNode, collection, context.getSourceCode())) {
usedKeys.clear();

@@ -65,3 +73,5 @@ }

const sameKeyWriteUsageLoc = sameKeyWriteUsage.node.loc;
const secondaryLocations = [locations_1.issueLocation(sameKeyWriteUsageLoc, sameKeyWriteUsageLoc, "Original value")];
const secondaryLocations = [
locations_1.issueLocation(sameKeyWriteUsageLoc, sameKeyWriteUsageLoc, 'Original value'),
];
locations_1.report(context, {

@@ -106,4 +116,4 @@ node: keyWriteUsage.node,

const methodName = propertyAccess.property.name;
const addMethod = methodName === "add" && node.arguments.length === 1;
const setMethod = methodName === "set" && node.arguments.length === 2;
const addMethod = methodName === 'add' && node.arguments.length === 1;
const setMethod = methodName === 'set' && node.arguments.length === 2;
if (addMethod || setMethod) {

@@ -126,3 +136,3 @@ const key = extractIndex(node.arguments[0]);

const { value } = node;
return typeof value === "number" || typeof value === "string" ? String(value) : undefined;
return typeof value === 'number' || typeof value === 'string' ? String(value) : undefined;
}

@@ -158,5 +168,5 @@ else if (nodes_1.isIdentifier(node)) {

function isSimpleAssignment(node) {
return nodes_1.isAssignmentExpression(node) && node.operator === "=";
return nodes_1.isAssignmentExpression(node) && node.operator === '=';
}
module.exports = rule;
//# sourceMappingURL=no-element-overwrite.js.map

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,12 +21,19 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-930
// https://sonarsource.github.io/rspec/#/rspec/S930
const nodes_1 = require("../utils/nodes");
const locations_1 = require("../utils/locations");
const docs_url_1 = require("../utils/docs-url");
const rule = {
meta: {
type: "problem",
type: 'problem',
docs: {
description: 'Function calls should not pass extra arguments',
category: 'Possible Errors',
recommended: 'error',
url: docs_url_1.default(__filename),
},
schema: [
{
// internal parameter
enum: ["sonar-runtime"],
enum: ['sonar-runtime'],
},

@@ -44,9 +51,11 @@ ],

if (nodes_1.isIdentifier(callExpr.callee)) {
const reference = context.getScope().references.find(ref => ref.identifier === callExpr.callee);
const reference = context
.getScope()
.references.find(ref => ref.identifier === callExpr.callee);
const definition = reference && getSingleDefinition(reference);
if (definition) {
if (definition.type === "FunctionName") {
if (definition.type === 'FunctionName') {
checkFunction(callExpr, definition.node);
}
else if (definition.type === "Variable") {
else if (definition.type === 'Variable') {
const { init } = definition.node;

@@ -59,3 +68,4 @@ if (init && (nodes_1.isFunctionExpression(init) || nodes_1.isArrowFunctionExpression(init))) {

}
else if (nodes_1.isArrowFunctionExpression(callExpr.callee) || nodes_1.isFunctionExpression(callExpr.callee)) {
else if (nodes_1.isArrowFunctionExpression(callExpr.callee) ||
nodes_1.isFunctionExpression(callExpr.callee)) {
// IIFE

@@ -65,3 +75,3 @@ checkFunction(callExpr, callExpr.callee);

},
":function"(node) {
':function'(node) {
const fn = node;

@@ -72,9 +82,9 @@ if (nodes_1.isBlockStatement(fn.body) && fn.body.body.length === 0 && fn.params.length === 0) {

},
"FunctionDeclaration > BlockStatement Identifier"(node) {
'FunctionDeclaration > BlockStatement Identifier'(node) {
checkArguments(node);
},
"FunctionExpression > BlockStatement Identifier"(node) {
'FunctionExpression > BlockStatement Identifier'(node) {
checkArguments(node);
},
"Program:exit"() {
'Program:exit'() {
callExpressionsToCheck.forEach(({ callExpr, functionNode }) => {

@@ -97,3 +107,3 @@ if (!usingArguments.has(functionNode) && !emptyFunctions.has(functionNode)) {

function checkArguments(identifier) {
if (identifier.name === "arguments") {
if (identifier.name === 'arguments') {
const reference = context.getScope().references.find(ref => ref.identifier === identifier);

@@ -112,3 +122,3 @@ const definition = reference && getSingleDefinition(reference);

function checkFunction(callExpr, functionNode) {
const hasRest = functionNode.params.some(param => param.type === "RestElement");
const hasRest = functionNode.params.some(param => param.type === 'RestElement');
if (!hasRest && callExpr.arguments.length > functionNode.params.length) {

@@ -136,6 +146,6 @@ callExpressionsToCheck.push({ callExpr, functionNode });

message,
node: callExpr,
}, getSecondaryLocations(functionNode));
node: callExpr.callee,
}, getSecondaryLocations(callExpr, functionNode));
}
function getSecondaryLocations(functionNode) {
function getSecondaryLocations(callExpr, functionNode) {
const paramLength = functionNode.params.length;

@@ -146,7 +156,3 @@ const secondaryLocations = [];

const endLoc = functionNode.params[paramLength - 1].loc;
// defensive check as `loc` property may be undefined according to
// its type declaration
if (startLoc && endLoc) {
secondaryLocations.push(locations_1.issueLocation(startLoc, endLoc, "Formal parameters"));
}
secondaryLocations.push(locations_1.issueLocation(startLoc, endLoc, 'Formal parameters'));
}

@@ -157,5 +163,11 @@ else {

if (fnToken) {
secondaryLocations.push(locations_1.issueLocation(fnToken, fnToken, "Formal parameters"));
secondaryLocations.push(locations_1.issueLocation(fnToken, fnToken, 'Formal parameters'));
}
}
// find actual extra arguments to highlight
callExpr.arguments.forEach((argument, index) => {
if (index >= paramLength) {
secondaryLocations.push(locations_1.toSecondaryLocation(argument, 'Extra argument'));
}
});
return secondaryLocations;

@@ -162,0 +174,0 @@ }

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,13 +21,20 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-1862
// https://sonarsource.github.io/rspec/#/rspec/S1862
const nodes_1 = require("../utils/nodes");
const equivalence_1 = require("../utils/equivalence");
const locations_1 = require("../utils/locations");
const docs_url_1 = require("../utils/docs-url");
const rule = {
meta: {
type: "problem",
type: 'problem',
docs: {
description: 'Related "if/else if" statements should not have the same condition',
category: 'Possible Errors',
recommended: 'error',
url: docs_url_1.default(__filename),
},
schema: [
{
// internal parameter
enum: ["sonar-runtime"],
enum: ['sonar-runtime'],
},

@@ -50,3 +57,3 @@ ],

node: statement.test,
}, [locations_1.issueLocation(condition.loc, condition.loc, "Original")]);
}, [locations_1.issueLocation(condition.loc, condition.loc, 'Original')]);
}

@@ -53,0 +60,0 @@ }

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,9 +21,21 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-1764
// https://sonarsource.github.io/rspec/#/rspec/S1764
const nodes_1 = require("../utils/nodes");
const equivalence_1 = require("../utils/equivalence");
const locations_1 = require("../utils/locations");
const EQUALITY_OPERATOR_TOKEN_KINDS = new Set(["==", "===", "!=", "!=="]);
const docs_url_1 = require("../utils/docs-url");
const EQUALITY_OPERATOR_TOKEN_KINDS = new Set(['==', '===', '!=', '!==']);
// consider only binary expressions with these operators
const RELEVANT_OPERATOR_TOKEN_KINDS = new Set(["&&", "||", "/", "-", "<<", ">>", "<", "<=", ">", ">="]);
const RELEVANT_OPERATOR_TOKEN_KINDS = new Set([
'&&',
'||',
'/',
'-',
'<<',
'>>',
'<',
'<=',
'>',
'>=',
]);
const message = (operator) => `Correct one of the identical sub-expressions on both sides of operator "${operator}"`;

@@ -38,11 +50,17 @@ function hasRelevantOperator(node) {

function isOneOntoOneShifting(node) {
return node.operator === "<<" && nodes_1.isLiteral(node.left) && node.left.value === 1;
return node.operator === '<<' && nodes_1.isLiteral(node.left) && node.left.value === 1;
}
const rule = {
meta: {
type: "problem",
type: 'problem',
docs: {
description: 'Identical expressions should not be used on both sides of a binary operator',
category: 'Possible Errors',
recommended: 'error',
url: docs_url_1.default(__filename),
},
schema: [
{
// internal parameter
enum: ["sonar-runtime"],
enum: ['sonar-runtime'],
},

@@ -75,3 +93,3 @@ ],

function isSonarRuntime() {
return context.options[context.options.length - 1] === "sonar-runtime";
return context.options[context.options.length - 1] === 'sonar-runtime';
}

@@ -78,0 +96,0 @@ },

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,13 +21,19 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-4144
// https://sonarsource.github.io/rspec/#/rspec/S4144
const equivalence_1 = require("../utils/equivalence");
const locations_1 = require("../utils/locations");
const nodes_1 = require("../utils/nodes");
const docs_url_1 = require("../utils/docs-url");
const message = (line) => `Update this function so that its implementation is not identical to the one on line ${line}.`;
const rule = {
meta: {
type: "problem",
type: 'problem',
docs: {
description: 'Functions should not have identical implementations',
category: 'Possible Errors',
recommended: 'error',
url: docs_url_1.default(__filename),
},
schema: [
{
enum: ["sonar-runtime"],
enum: ['sonar-runtime'],
},

@@ -48,3 +54,3 @@ ],

},
"Program:exit"() {
'Program:exit'() {
processFunctions();

@@ -55,9 +61,6 @@ },

if (isBigEnough(node.body)) {
functions.push({ function: node, parent: nodes_1.getParent(context) });
functions.push({ function: node, parent: node.parent });
}
}
function processFunctions() {
if (functions.length < 2) {
return;
}
for (let i = 1; i < functions.length; i++) {

@@ -72,3 +75,3 @@ const duplicatingFunction = functions[i].function;

const secondaryLocations = [
locations_1.issueLocation(originalFunctionLoc, originalFunctionLoc, "Original implementation"),
locations_1.issueLocation(originalFunctionLoc, originalFunctionLoc, 'Original implementation'),
];

@@ -86,6 +89,6 @@ locations_1.report(context, {

const tokens = context.getSourceCode().getTokens(node);
if (tokens.length > 0 && tokens[0].value === "{") {
if (tokens.length > 0 && tokens[0].value === '{') {
tokens.shift();
}
if (tokens.length > 0 && tokens[tokens.length - 1].value === "}") {
if (tokens.length > 0 && tokens[tokens.length - 1].value === '}') {
tokens.pop();

@@ -92,0 +95,0 @@ }

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,26 +21,35 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-1940
// https://sonarsource.github.io/rspec/#/rspec/S1940
const nodes_1 = require("../utils/nodes");
const MESSAGE = "Use the opposite operator ({{invertedOperator}}) instead.";
const docs_url_1 = require("../utils/docs-url");
const MESSAGE = 'Use the opposite operator ({{invertedOperator}}) instead.';
const invertedOperators = {
"==": "!=",
"!=": "==",
"===": "!==",
"!==": "===",
">": "<=",
"<": ">=",
">=": "<",
"<=": ">",
'==': '!=',
'!=': '==',
'===': '!==',
'!==': '===',
'>': '<=',
'<': '>=',
'>=': '<',
'<=': '>',
};
const rule = {
meta: {
fixable: "code",
type: "suggestion",
type: 'suggestion',
docs: {
description: 'Boolean checks should not be inverted',
category: 'Best Practices',
recommended: 'error',
url: docs_url_1.default(__filename),
},
fixable: 'code',
},
create(context) {
return { UnaryExpression: (node) => visitUnaryExpression(node, context) };
return {
UnaryExpression: (node) => visitUnaryExpression(node, context),
};
},
};
function visitUnaryExpression(unaryExpression, context) {
if (unaryExpression.operator === "!" && nodes_1.isBinaryExpression(unaryExpression.argument)) {
if (unaryExpression.operator === '!' && nodes_1.isBinaryExpression(unaryExpression.argument)) {
const condition = unaryExpression.argument;

@@ -47,0 +56,0 @@ const invertedOperator = invertedOperators[condition.operator];

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,7 +21,14 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-1751
// https://sonarsource.github.io/rspec/#/rspec/S1751
const nodes_1 = require("../utils/nodes");
const docs_url_1 = require("../utils/docs-url");
const rule = {
meta: {
type: "problem",
type: 'problem',
docs: {
description: 'Loops with at most one iteration should be refactored',
category: 'Possible Errors',
recommended: 'error',
url: docs_url_1.default(__filename),
},
},

@@ -49,9 +56,7 @@ create(context) {

},
"WhileStatement > *"() {
const parent = nodes_1.getParent(context);
visitLoopChild(parent);
'WhileStatement > *'(node) {
visitLoopChild(node.parent);
},
"ForStatement > *"() {
const parent = nodes_1.getParent(context);
visitLoopChild(parent);
'ForStatement > *'(node) {
visitLoopChild(node.parent);
},

@@ -70,7 +75,7 @@ onCodePathSegmentLoop(_, toSegment, node) {

},
"Program:exit"() {
'Program:exit'() {
loops.forEach(loop => {
if (!loopingNodes.has(loop)) {
context.report({
message: "Refactor this loop to do more than one iteration.",
message: 'Refactor this loop to do more than one iteration.',
loc: context.getSourceCode().getFirstToken(loop).loc,

@@ -77,0 +82,0 @@ });

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,8 +21,15 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-1125
// https://sonarsource.github.io/rspec/#/rspec/S1125
const nodes_1 = require("../utils/nodes");
const MESSAGE = "Remove the unnecessary boolean literal.";
const docs_url_1 = require("../utils/docs-url");
const MESSAGE = 'Remove the unnecessary boolean literal.';
const rule = {
meta: {
type: "suggestion",
type: 'suggestion',
docs: {
description: 'Boolean literals should not be redundant',
category: 'Best Practices',
recommended: 'error',
url: docs_url_1.default(__filename),
},
},

@@ -33,3 +40,3 @@ create(context) {

const expression = node;
if (expression.operator === "==" || expression.operator === "!=") {
if (expression.operator === '==' || expression.operator === '!=') {
checkBooleanLiteral(expression.left);

@@ -42,8 +49,8 @@ checkBooleanLiteral(expression.right);

checkBooleanLiteral(expression.left);
if (expression.operator === "&&") {
if (expression.operator === '&&') {
checkBooleanLiteral(expression.right);
}
// ignore `x || true` and `x || false` expressions outside of conditional expressions and `if` statements
const parent = nodes_1.getParent(context);
if (expression.operator === "||" &&
const { parent } = node;
if (expression.operator === '||' &&
((nodes_1.isConditionalExpression(parent) && parent.test === expression) || nodes_1.isIfStatement(parent))) {

@@ -55,3 +62,3 @@ checkBooleanLiteral(expression.right);

const unaryExpression = node;
if (unaryExpression.operator === "!") {
if (unaryExpression.operator === '!') {
checkBooleanLiteral(unaryExpression.argument);

@@ -58,0 +65,0 @@ }

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,15 +21,21 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-3626
const nodes_1 = require("../utils/nodes");
const message = "Remove this redundant jump.";
const loops = "WhileStatement, ForStatement, DoWhileStatement, ForInStatement, ForOfStatement";
// https://sonarsource.github.io/rspec/#/rspec/S3626
const docs_url_1 = require("../utils/docs-url");
const message = 'Remove this redundant jump.';
const loops = 'WhileStatement, ForStatement, DoWhileStatement, ForInStatement, ForOfStatement';
const rule = {
meta: {
type: "suggestion",
type: 'suggestion',
docs: {
description: 'Jump statements should not be redundant',
category: 'Best Practices',
recommended: 'error',
url: docs_url_1.default(__filename),
},
},
create(context) {
function reportIfLastStatement(node) {
const withArgument = node.type === "ContinueStatement" ? !!node.label : !!node.argument;
const withArgument = node.type === 'ContinueStatement' ? !!node.label : !!node.argument;
if (!withArgument) {
const block = nodes_1.getParent(context);
const block = node.parent;
if (block.body[block.body.length - 1] === node && block.body.length > 1) {

@@ -58,6 +64,6 @@ context.report({

},
":function > BlockStatement > ReturnStatement": (node) => {
':function > BlockStatement > ReturnStatement': (node) => {
reportIfLastStatement(node);
},
":function > BlockStatement > IfStatement > BlockStatement > ReturnStatement": (node) => {
':function > BlockStatement > IfStatement > BlockStatement > ReturnStatement': (node) => {
reportIfLastStatementInsideIf(node);

@@ -64,0 +70,0 @@ },

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,11 +21,18 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-3972
// https://sonarsource.github.io/rspec/#/rspec/S3972
const locations_1 = require("../utils/locations");
const docs_url_1 = require("../utils/docs-url");
const rule = {
meta: {
type: "problem",
type: 'problem',
docs: {
description: 'Conditionals should start on new lines',
category: 'Possible Errors',
recommended: 'error',
url: docs_url_1.default(__filename),
},
schema: [
{
// internal parameter
enum: ["sonar-runtime"],
enum: ['sonar-runtime'],
},

@@ -66,3 +73,5 @@ ],

const previousStatement = statements[currentIndex - 1];
if (statement.type === "IfStatement" && !!previousStatement && previousStatement.type === "IfStatement") {
if (statement.type === 'IfStatement' &&
!!previousStatement &&
previousStatement.type === 'IfStatement') {
return [{ first: previousStatement, following: statement }, ...siblingsArray];

@@ -69,0 +78,0 @@ }

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,7 +21,14 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-1301
// https://sonarsource.github.io/rspec/#/rspec/S1301
const docs_url_1 = require("../utils/docs-url");
const MESSAGE = '"switch" statements should have at least 3 "case" clauses';
const rule = {
meta: {
type: "suggestion",
type: 'suggestion',
docs: {
description: '"switch" statements should have at least 3 "case" clauses',
category: 'Best Practices',
recommended: 'error',
url: docs_url_1.default(__filename),
},
},

@@ -28,0 +35,0 @@ create(context) {

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,12 +21,19 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-4030
// https://sonarsource.github.io/rspec/#/rspec/S4030
const collections_1 = require("../utils/collections");
const docs_url_1 = require("../utils/docs-url");
const message = "Either use this collection's contents or remove the collection.";
const rule = {
meta: {
type: "problem",
type: 'problem',
docs: {
description: 'Collection and array contents should be used',
category: 'Possible Errors',
recommended: 'error',
url: docs_url_1.default(__filename),
},
},
create(context) {
return {
"Program:exit": () => {
'Program:exit': () => {
const unusedArrays = [];

@@ -45,3 +52,3 @@ collectUnusedCollections(context.getScope(), unusedArrays);

function collectUnusedCollections(scope, unusedArray) {
if (scope.type !== "global") {
if (scope.type !== 'global') {
scope.variables.filter(isUnusedCollection).forEach(v => {

@@ -55,3 +62,11 @@ unusedArray.push(v);

}
function isExported(variable) {
var _a, _b;
const definition = variable.defs[0];
return definition && ((_b = (_a = definition.node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.type.startsWith('Export'));
}
function isUnusedCollection(variable) {
if (isExported(variable)) {
return false;
}
if (variable.references.length <= 1) {

@@ -79,10 +94,10 @@ return false;

function isReferenceAssigningCollection(ref) {
const declOrExprStmt = findFirstMatchingAncestor(ref.identifier, n => n.type === "VariableDeclarator" || n.type === "ExpressionStatement");
const declOrExprStmt = findFirstMatchingAncestor(ref.identifier, n => n.type === 'VariableDeclarator' || n.type === 'ExpressionStatement');
if (declOrExprStmt) {
if (declOrExprStmt.type === "VariableDeclarator" && declOrExprStmt.init) {
if (declOrExprStmt.type === 'VariableDeclarator' && declOrExprStmt.init) {
return isCollectionType(declOrExprStmt.init);
}
if (declOrExprStmt.type === "ExpressionStatement") {
if (declOrExprStmt.type === 'ExpressionStatement') {
const { expression } = declOrExprStmt;
return (expression.type === "AssignmentExpression" &&
return (expression.type === 'AssignmentExpression' &&
isReferenceTo(ref, expression.left) &&

@@ -95,6 +110,6 @@ isCollectionType(expression.right));

function isCollectionType(node) {
if (node && node.type === "ArrayExpression") {
if (node && node.type === 'ArrayExpression') {
return true;
}
else if (node && (node.type === "CallExpression" || node.type === "NewExpression")) {
else if (node && (node.type === 'CallExpression' || node.type === 'NewExpression')) {
return isIdentifier(node.callee, ...collections_1.collectionConstructor);

@@ -105,3 +120,3 @@ }

function isRead(ref) {
const expressionStatement = findFirstMatchingAncestor(ref.identifier, n => n.type === "ExpressionStatement");
const expressionStatement = findFirstMatchingAncestor(ref.identifier, n => n.type === 'ExpressionStatement');
if (expressionStatement) {

@@ -118,3 +133,3 @@ return !(isElementWrite(expressionStatement, ref) || isWritingMethodCall(expressionStatement, ref));

function isWritingMethodCall(statement, ref) {
if (statement.expression.type === "CallExpression") {
if (statement.expression.type === 'CallExpression') {
const { callee } = statement.expression;

@@ -129,3 +144,3 @@ if (isMemberExpression(callee)) {

function isMemberExpression(node) {
return node.type === "MemberExpression";
return node.type === 'MemberExpression';
}

@@ -140,3 +155,3 @@ /**

function isElementWrite(statement, ref) {
if (statement.expression.type === "AssignmentExpression") {
if (statement.expression.type === 'AssignmentExpression') {
const assignmentExpression = statement.expression;

@@ -149,9 +164,10 @@ const lhs = assignmentExpression.left;

function isMemberExpressionReference(lhs, ref) {
return (lhs.type === "MemberExpression" && (isReferenceTo(ref, lhs.object) || isMemberExpressionReference(lhs.object, ref)));
return (lhs.type === 'MemberExpression' &&
(isReferenceTo(ref, lhs.object) || isMemberExpressionReference(lhs.object, ref)));
}
function isIdentifier(node, ...values) {
return node.type === "Identifier" && values.some(value => value === node.name);
return node.type === 'Identifier' && values.some(value => value === node.name);
}
function isReferenceTo(ref, node) {
return node.type === "Identifier" && node === ref.identifier;
return node.type === 'Identifier' && node === ref.identifier;
}

@@ -158,0 +174,0 @@ function findFirstMatchingAncestor(node, predicate) {

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,28 +21,35 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-3699
// https://sonarsource.github.io/rspec/#/rspec/S3699
const nodes_1 = require("../utils/nodes");
function isReturnValueUsed(callExpr, context) {
const parent = nodes_1.getParent(context);
const docs_url_1 = require("../utils/docs-url");
function isReturnValueUsed(callExpr) {
const { parent } = callExpr;
if (!parent) {
return false;
}
if (parent.type === "LogicalExpression") {
if (parent.type === 'LogicalExpression') {
return parent.left === callExpr;
}
if (parent.type === "SequenceExpression") {
if (parent.type === 'SequenceExpression') {
return parent.expressions[parent.expressions.length - 1] === callExpr;
}
if (parent.type === "ConditionalExpression") {
if (parent.type === 'ConditionalExpression') {
return parent.test === callExpr;
}
return (parent.type !== "ExpressionStatement" &&
parent.type !== "ArrowFunctionExpression" &&
parent.type !== "UnaryExpression" &&
parent.type !== "AwaitExpression" &&
parent.type !== "ReturnStatement" &&
parent.type !== "ThrowStatement");
return (parent.type !== 'ExpressionStatement' &&
parent.type !== 'ArrowFunctionExpression' &&
parent.type !== 'UnaryExpression' &&
parent.type !== 'AwaitExpression' &&
parent.type !== 'ReturnStatement' &&
parent.type !== 'ThrowStatement');
}
const rule = {
meta: {
type: "problem",
type: 'problem',
docs: {
description: "The output of functions that don't return anything should not be used",
category: 'Possible Errors',
recommended: 'error',
url: docs_url_1.default(__filename),
},
},

@@ -55,3 +62,3 @@ create(context) {

const callExpr = node;
if (!isReturnValueUsed(callExpr, context)) {
if (!isReturnValueUsed(callExpr)) {
return;

@@ -65,6 +72,6 @@ }

const definition = variable.defs[0];
if (definition.type === "FunctionName") {
if (definition.type === 'FunctionName') {
callExpressionsToCheck.set(reference.identifier, definition.node);
}
else if (definition.type === "Variable") {
else if (definition.type === 'Variable') {
const { init } = definition.node;

@@ -82,5 +89,5 @@ if (init && (nodes_1.isFunctionExpression(init) || nodes_1.isArrowFunctionExpression(init))) {

const ancestors = [...context.getAncestors()].reverse();
const functionNode = ancestors.find(node => node.type === "FunctionExpression" ||
node.type === "FunctionDeclaration" ||
node.type === "ArrowFunctionExpression");
const functionNode = ancestors.find(node => node.type === 'FunctionExpression' ||
node.type === 'FunctionDeclaration' ||
node.type === 'ArrowFunctionExpression');
functionsWithReturnValue.add(functionNode);

@@ -95,9 +102,11 @@ }

},
":function"(node) {
':function'(node) {
const func = node;
if (func.async || func.generator || (nodes_1.isBlockStatement(func.body) && func.body.body.length === 0)) {
if (func.async ||
func.generator ||
(nodes_1.isBlockStatement(func.body) && func.body.body.length === 0)) {
functionsWithReturnValue.add(func);
}
},
"Program:exit"() {
'Program:exit'() {
callExpressionsToCheck.forEach((functionDeclaration, callee) => {

@@ -104,0 +113,0 @@ if (!functionsWithReturnValue.has(functionDeclaration)) {

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,12 +21,21 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-1940
// https://sonarsource.github.io/rspec/#/rspec/S1940
const nodes_1 = require("../utils/nodes");
const equivalence_1 = require("../utils/equivalence");
const MESSAGE = "Add logic to this catch clause or eliminate it and rethrow the exception automatically.";
const docs_url_1 = require("../utils/docs-url");
const MESSAGE = 'Add logic to this catch clause or eliminate it and rethrow the exception automatically.';
const rule = {
meta: {
type: "suggestion",
type: 'suggestion',
docs: {
description: '"catch" clauses should do more than rethrow',
category: 'Best Practices',
recommended: 'error',
url: docs_url_1.default(__filename),
},
},
create(context) {
return { CatchClause: (node) => visitCatchClause(node, context) };
return {
CatchClause: (node) => visitCatchClause(node, context),
};
},

@@ -47,5 +56,8 @@ };

function onlyRethrows(statement, catchParam, sourceCode) {
return nodes_1.isThrowStatement(statement) && equivalence_1.areEquivalent(catchParam, statement.argument, sourceCode);
return (nodes_1.isThrowStatement(statement) &&
catchParam !== null &&
statement.argument !== null &&
equivalence_1.areEquivalent(catchParam, statement.argument, sourceCode));
}
module.exports = rule;
//# sourceMappingURL=no-useless-catch.js.map

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,8 +21,15 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-1488
// https://sonarsource.github.io/rspec/#/rspec/S1488
const nodes_1 = require("../utils/nodes");
const docs_url_1 = require("../utils/docs-url");
const rule = {
meta: {
type: "suggestion",
fixable: "code",
type: 'suggestion',
docs: {
description: 'Local variables should not be declared and then immediately returned or thrown',
category: 'Best Practices',
recommended: 'error',
url: docs_url_1.default(__filename),
},
fixable: 'code',
},

@@ -46,4 +53,6 @@ create(context) {

const sameVariable = getVariables(context).find(variable => {
return (variable.references.find(ref => ref.identifier === returnedIdentifier) !== undefined &&
variable.references.find(ref => ref.identifier === declaredIdentifier.id) !== undefined);
return (variable.references.find(ref => ref.identifier === returnedIdentifier) !==
undefined &&
variable.references.find(ref => ref.identifier === declaredIdentifier.id) !==
undefined);
});

@@ -55,3 +64,3 @@ // there must be only one "read" - in `return` or `throw`

node: declaredIdentifier.init,
fix: fixer => fix(fixer, last, lastButOne, declaredIdentifier.init),
fix: fixer => fix(fixer, last, lastButOne, declaredIdentifier.init, returnedIdentifier),
});

@@ -62,21 +71,19 @@ }

}
function fix(fixer, last, lastButOne, expression) {
const throwOrReturnKeyword = context.getSourceCode().getFirstToken(last);
if (lastButOne.range && last.range && throwOrReturnKeyword) {
const expressionText = context.getSourceCode().getText(expression);
const fixedRangeStart = lastButOne.range[0];
const fixedRangeEnd = last.range[1];
const semicolonToken = context.getSourceCode().getLastToken(last);
const semicolon = semicolonToken && semicolonToken.value === ";" ? ";" : "";
return [
fixer.removeRange([fixedRangeStart, fixedRangeEnd]),
fixer.insertTextAfterRange([1, fixedRangeStart], `${throwOrReturnKeyword.value} ${expressionText}${semicolon}`),
];
}
else {
return null;
}
// eslint-disable-next-line max-params
function fix(fixer, last, lastButOne, expressionToReturn, returnedExpression) {
const expressionText = context.getSourceCode().getText(expressionToReturn);
const rangeToRemoveStart = lastButOne.range[0];
const commentsBetweenStatements = context.getSourceCode().getCommentsAfter(lastButOne);
const rangeToRemoveEnd = commentsBetweenStatements.length > 0
? commentsBetweenStatements[0].range[0]
: last.range[0];
return [
fixer.removeRange([rangeToRemoveStart, rangeToRemoveEnd]),
fixer.replaceText(returnedExpression, expressionText),
];
}
function getOnlyReturnedVariable(node) {
return (nodes_1.isReturnStatement(node) || nodes_1.isThrowStatement(node)) && node.argument && nodes_1.isIdentifier(node.argument)
return (nodes_1.isReturnStatement(node) || nodes_1.isThrowStatement(node)) &&
node.argument &&
nodes_1.isIdentifier(node.argument)
? node.argument

@@ -95,3 +102,3 @@ : undefined;

function formatMessage(node, variable) {
const action = nodes_1.isReturnStatement(node) ? "return" : "throw";
const action = nodes_1.isReturnStatement(node) ? 'return' : 'throw';
return `Immediately ${action} this expression instead of assigning it to the temporary variable "${variable}".`;

@@ -98,0 +105,0 @@ }

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,9 +21,16 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-2428
// https://sonarsource.github.io/rspec/#/rspec/S2428
const nodes_1 = require("../utils/nodes");
const equivalence_1 = require("../utils/equivalence");
const MESSAGE = "Declare one or more properties of this object inside of the object literal syntax instead of using separate statements.";
const docs_url_1 = require("../utils/docs-url");
const MESSAGE = 'Declare one or more properties of this object inside of the object literal syntax instead of using separate statements.';
const rule = {
meta: {
type: "suggestion",
type: 'suggestion',
docs: {
description: 'Object literal syntax should be used',
category: 'Best Practices',
recommended: 'error',
url: docs_url_1.default(__filename),
},
},

@@ -30,0 +37,0 @@ create(context) {

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 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 GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* 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 GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// https://jira.sonarsource.com/browse/RSPEC-1126
const nodes_1 = require("../utils/nodes");
const docs_url_1 = require("../utils/docs-url");
const rule = {
meta: {
type: "suggestion",
type: 'suggestion',
docs: {
description: 'Return of boolean expressions should not be wrapped into an "if-then-else" statement',
category: 'Best Practices',
recommended: 'error',
url: docs_url_1.default(__filename),
},
},

@@ -33,3 +20,3 @@ create(context) {

// ignore `else if`
!nodes_1.isIfStatement(nodes_1.getParent(context)) &&
!nodes_1.isIfStatement(ifStmt.parent) &&
// `ifStmt.alternate` can be `null`, replace it with `undefined` in this case

@@ -39,3 +26,3 @@ returnsBoolean(ifStmt.alternate || undefined) &&

context.report({
message: "Replace this if-then-else statement by a single return statement.",
message: 'Replace this if-then-else statement by a single return statement.',
node: ifStmt,

@@ -51,3 +38,5 @@ });

function isBlockReturningBooleanLiteral(statement) {
return (nodes_1.isBlockStatement(statement) && statement.body.length === 1 && isSimpleReturnBooleanLiteral(statement.body[0]));
return (nodes_1.isBlockStatement(statement) &&
statement.body.length === 1 &&
isSimpleReturnBooleanLiteral(statement.body[0]));
}

@@ -54,0 +43,0 @@ function isSimpleReturnBooleanLiteral(statement) {

@@ -1,3 +0,3 @@

import { Rule } from "eslint";
import { Rule } from '../utils/types';
declare const rule: Rule.RuleModule;
export = rule;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -21,7 +21,14 @@ *

*/
// https://jira.sonarsource.com/browse/RSPEC-1264
// https://sonarsource.github.io/rspec/#/rspec/S1264
const docs_url_1 = require("../utils/docs-url");
const rule = {
meta: {
fixable: "code",
type: "suggestion",
type: 'suggestion',
docs: {
description: 'A "while" loop should be used instead of a "for" loop',
category: 'Best Practices',
recommended: 'error',
url: docs_url_1.default(__filename),
},
fixable: 'code',
},

@@ -33,3 +40,3 @@ create(context) {

const forKeyword = context.getSourceCode().getFirstToken(node);
if (!forLoop.init && !forLoop.update && forKeyword) {
if (!forLoop.init && !forLoop.update && forLoop.test && forKeyword) {
context.report({

@@ -36,0 +43,0 @@ message: `Replace this "for" loop with a "while" loop.`,

@@ -6,3 +6,3 @@ "use strict";

* eslint-plugin-sonarjs
* Copyright (C) 2018 SonarSource SA
* Copyright (C) 2018-2021 SonarSource SA
* mailto:info AT sonarsource DOT com

@@ -24,20 +24,20 @@ *

*/
exports.collectionConstructor = ["Array", "Map", "Set", "WeakSet", "WeakMap"];
exports.collectionConstructor = ['Array', 'Map', 'Set', 'WeakSet', 'WeakMap'];
exports.writingMethods = [
// array methods
"copyWithin",
"fill",
"pop",
"push",
"reverse",
"set",
"shift",
"sort",
"splice",
"unshift",
'copyWithin',
'fill',
'pop',
'push',
'reverse',
'set',
'shift',
'sort',
'splice',
'unshift',
// map, set methods
"add",
"clear",
"delete",
'add',
'clear',
'delete',
];
//# sourceMappingURL=collections.js.map

@@ -1,13 +0,13 @@

import * as estree from "estree";
import { TSESTree } from '@typescript-eslint/experimental-utils';
/** Returns a list of statements corresponding to a `if - else if - else` chain */
export declare function collectIfBranches(node: estree.IfStatement): {
branches: estree.Statement[];
export declare function collectIfBranches(node: TSESTree.IfStatement): {
branches: TSESTree.Statement[];
endsWithElse: boolean;
};
/** Returns a list of `switch` clauses (both `case` and `default`) */
export declare function collectSwitchBranches(node: estree.SwitchStatement): {
branches: estree.Statement[][];
export declare function collectSwitchBranches(node: TSESTree.SwitchStatement): {
branches: TSESTree.Statement[][];
endsWithDefault: boolean;
};
/** Excludes the break statement from the list */
export declare function takeWithoutBreak(nodes: estree.Statement[]): estree.Statement[];
export declare function takeWithoutBreak(nodes: TSESTree.Statement[]): TSESTree.Statement[];

@@ -43,5 +43,7 @@ "use strict";

function takeWithoutBreak(nodes) {
return nodes.length > 0 && nodes[nodes.length - 1].type === "BreakStatement" ? nodes.slice(0, -1) : nodes;
return nodes.length > 0 && nodes[nodes.length - 1].type === 'BreakStatement'
? nodes.slice(0, -1)
: nodes;
}
exports.takeWithoutBreak = takeWithoutBreak;
//# sourceMappingURL=conditions.js.map

@@ -1,3 +0,2 @@

import { Node } from "estree";
import { SourceCode } from "eslint";
import { TSESTree, TSESLint } from '@typescript-eslint/experimental-utils';
/**

@@ -8,2 +7,2 @@ * Equivalence is implemented by comparing node types and their tokens.

*/
export declare function areEquivalent(first: Node | Node[], second: Node | Node[], sourceCode: SourceCode): boolean;
export declare function areEquivalent(first: TSESTree.Node | TSESTree.Node[], second: TSESTree.Node | TSESTree.Node[], sourceCode: TSESLint.SourceCode): boolean;

@@ -15,3 +15,4 @@ "use strict";

else if (!Array.isArray(first) && !Array.isArray(second)) {
return first.type === second.type && compareTokens(sourceCode.getTokens(first), sourceCode.getTokens(second));
return (first.type === second.type &&
compareTokens(sourceCode.getTokens(first), sourceCode.getTokens(second)));
}

@@ -18,0 +19,0 @@ return false;

@@ -1,3 +0,3 @@

import { Rule, AST } from "eslint";
import * as estree from "estree";
import { TSESTree, TSESLint } from '@typescript-eslint/experimental-utils';
import { Rule } from './types';
export interface IssueLocation {

@@ -21,6 +21,3 @@ column: number;

*/
export declare function getMainFunctionTokenLocation(fn: estree.Function, parent: estree.Node | undefined, context: Rule.RuleContext): estree.SourceLocation;
export declare type ReportDescriptor = Rule.ReportDescriptor & {
message: string;
};
export declare function getMainFunctionTokenLocation(fn: TSESTree.FunctionLike, parent: TSESTree.Node | undefined, context: Rule.RuleContext): TSESTree.SourceLocation;
/**

@@ -31,9 +28,10 @@ * Wrapper for `context.report`, supporting secondary locations and cost.

*/
export declare function report(context: Rule.RuleContext, reportDescriptor: ReportDescriptor, secondaryLocations?: IssueLocation[], cost?: number): void;
export declare function report(context: Rule.RuleContext, reportDescriptor: Rule.ReportDescriptor, secondaryLocations?: IssueLocation[], cost?: number): void;
/**
* Converts `SourceLocation` range into `IssueLocation`
*/
export declare function issueLocation(startLoc: estree.SourceLocation, endLoc?: estree.SourceLocation, message?: string): IssueLocation;
export declare function toEncodedMessage(message: string, secondaryLocationsHolder: Array<AST.Token | estree.Node>, secondaryMessages?: string[], cost?: number): string;
export declare function getFirstTokenAfter(node: estree.Node, context: Rule.RuleContext): AST.Token | null;
export declare function getFirstToken(node: estree.Node, context: Rule.RuleContext): AST.Token;
export declare function issueLocation(startLoc: TSESTree.SourceLocation, endLoc?: TSESTree.SourceLocation, message?: string): IssueLocation;
export declare function toEncodedMessage(message: string, secondaryLocationsHolder: Array<TSESLint.AST.Token | TSESTree.Node>, secondaryMessages?: string[], cost?: number): string;
export declare function toSecondaryLocation(locationHolder: TSESLint.AST.Token | TSESTree.Node, message?: string): IssueLocation;
export declare function getFirstTokenAfter(node: TSESTree.Node, context: Rule.RuleContext): TSESLint.AST.Token | null;
export declare function getFirstToken(node: TSESTree.Node, context: Rule.RuleContext): TSESLint.AST.Token;
"use strict";
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018-2021 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 GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* 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 GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getFirstToken = exports.getFirstTokenAfter = exports.toEncodedMessage = exports.issueLocation = exports.report = exports.getMainFunctionTokenLocation = void 0;
exports.getFirstToken = exports.getFirstTokenAfter = exports.toSecondaryLocation = exports.toEncodedMessage = exports.issueLocation = exports.report = exports.getMainFunctionTokenLocation = void 0;
/**

@@ -12,4 +31,4 @@ * Returns a location of the "main" function token:

let location;
if (fn.type === "FunctionDeclaration") {
// `fn.id` can be null when it is `export default function` (despite of the @types/estree definition)
if (fn.type === 'FunctionDeclaration') {
// `fn.id` can be null when it is `export default function` (despite of the @types/TSESTree definition)
if (fn.id) {

@@ -19,16 +38,16 @@ location = fn.id.loc;

else {
const token = getTokenByValue(fn, "function", context);
const token = getTokenByValue(fn, 'function', context);
location = token && token.loc;
}
}
else if (fn.type === "FunctionExpression") {
if (parent && (parent.type === "MethodDefinition" || parent.type === "Property")) {
else if (fn.type === 'FunctionExpression') {
if (parent && (parent.type === 'MethodDefinition' || parent.type === 'Property')) {
location = parent.key.loc;
}
else {
const token = getTokenByValue(fn, "function", context);
const token = getTokenByValue(fn, 'function', context);
location = token && token.loc;
}
}
else if (fn.type === "ArrowFunctionExpression") {
else if (fn.type === 'ArrowFunctionExpression') {
const token = context

@@ -38,3 +57,3 @@ .getSourceCode()

.reverse()
.find(token => token.value === "=>");
.find(token => token.value === '=>');
location = token && token.loc;

@@ -52,4 +71,4 @@ }

const { message } = reportDescriptor;
if (context.options[context.options.length - 1] === "sonar-runtime") {
const encodedMessage = { secondaryLocations, message, cost };
if (context.options[context.options.length - 1] === 'sonar-runtime') {
const encodedMessage = { secondaryLocations, message: message, cost };
reportDescriptor.message = JSON.stringify(encodedMessage);

@@ -63,3 +82,3 @@ }

*/
function issueLocation(startLoc, endLoc = startLoc, message = "") {
function issueLocation(startLoc, endLoc = startLoc, message = '') {
return {

@@ -93,2 +112,3 @@ line: startLoc.start.line,

}
exports.toSecondaryLocation = toSecondaryLocation;
function getTokenByValue(node, value, context) {

@@ -95,0 +115,0 @@ return context

@@ -1,24 +0,22 @@

import { Rule } from "eslint";
import * as estree from "estree";
export declare function getParent(context: Rule.RuleContext): estree.Identifier | estree.SimpleLiteral | estree.RegExpLiteral | estree.Program | estree.FunctionDeclaration | estree.FunctionExpression | estree.ArrowFunctionExpression | estree.SwitchCase | estree.CatchClause | estree.VariableDeclarator | estree.ExpressionStatement | estree.BlockStatement | estree.EmptyStatement | estree.DebuggerStatement | estree.WithStatement | estree.ReturnStatement | estree.LabeledStatement | estree.BreakStatement | estree.ContinueStatement | estree.IfStatement | estree.SwitchStatement | estree.ThrowStatement | estree.TryStatement | estree.WhileStatement | estree.DoWhileStatement | estree.ForStatement | estree.ForInStatement | estree.ForOfStatement | estree.VariableDeclaration | estree.ClassDeclaration | estree.ThisExpression | estree.ArrayExpression | estree.ObjectExpression | estree.YieldExpression | estree.UnaryExpression | estree.UpdateExpression | estree.BinaryExpression | estree.AssignmentExpression | estree.LogicalExpression | estree.MemberExpression | estree.ConditionalExpression | estree.SimpleCallExpression | estree.NewExpression | estree.SequenceExpression | estree.TemplateLiteral | estree.TaggedTemplateExpression | estree.ClassExpression | estree.MetaProperty | estree.AwaitExpression | estree.ImportExpression | estree.ChainExpression | estree.Property | estree.Super | estree.TemplateElement | estree.SpreadElement | estree.ObjectPattern | estree.ArrayPattern | estree.RestElement | estree.AssignmentPattern | estree.ClassBody | estree.MethodDefinition | estree.ImportDeclaration | estree.ExportNamedDeclaration | estree.ExportDefaultDeclaration | estree.ExportAllDeclaration | estree.ImportSpecifier | estree.ImportDefaultSpecifier | estree.ImportNamespaceSpecifier | estree.ExportSpecifier | undefined;
export declare function isArrowFunctionExpression(node: estree.Node | undefined): node is estree.ArrowFunctionExpression;
export declare function isAssignmentExpression(node: estree.Node | undefined): node is estree.AssignmentExpression;
export declare function isBinaryExpression(node: estree.Node | undefined): node is estree.BinaryExpression;
export declare function isBlockStatement(node: estree.Node | undefined): node is estree.BlockStatement;
export declare function isBooleanLiteral(node: estree.Node | undefined): node is estree.Literal;
export declare function isCallExpression(node: estree.Node | undefined): node is estree.CallExpression;
export declare function isConditionalExpression(node: estree.Node | undefined): node is estree.ConditionalExpression;
export declare function isContinueStatement(node: estree.Node | undefined): node is estree.ContinueStatement;
export declare function isExpressionStatement(node: estree.Node | undefined): node is estree.ExpressionStatement;
export declare function isFunctionDeclaration(node: estree.Node | undefined): node is estree.FunctionDeclaration;
export declare function isFunctionExpression(node: estree.Node | undefined): node is estree.FunctionExpression;
export declare function isIdentifier(node: estree.Node | undefined): node is estree.Identifier;
export declare function isIfStatement(node: estree.Node | undefined): node is estree.IfStatement;
export declare function isLiteral(node: estree.Node | undefined): node is estree.Literal;
export declare function isLogicalExpression(node: estree.Node | undefined): node is estree.LogicalExpression;
export declare function isMemberExpression(node: estree.Node | undefined): node is estree.MemberExpression;
export declare function isModuleDeclaration(node: estree.Node | undefined): node is estree.ModuleDeclaration;
export declare function isObjectExpression(node: estree.Node | undefined): node is estree.ObjectExpression;
export declare function isReturnStatement(node: estree.Node | undefined): node is estree.ReturnStatement;
export declare function isThrowStatement(node: estree.Node | undefined): node is estree.ThrowStatement;
export declare function isVariableDeclaration(node: estree.Node | undefined): node is estree.VariableDeclaration;
import { TSESTree } from '@typescript-eslint/experimental-utils';
export declare function isArrowFunctionExpression(node: TSESTree.Node | undefined): node is TSESTree.ArrowFunctionExpression;
export declare function isAssignmentExpression(node: TSESTree.Node | undefined): node is TSESTree.AssignmentExpression;
export declare function isBinaryExpression(node: TSESTree.Node | undefined): node is TSESTree.BinaryExpression;
export declare function isBlockStatement(node: TSESTree.Node | undefined): node is TSESTree.BlockStatement;
export declare function isBooleanLiteral(node: TSESTree.Node | undefined): node is TSESTree.Literal;
export declare function isCallExpression(node: TSESTree.Node | undefined): node is TSESTree.CallExpression;
export declare function isConditionalExpression(node: TSESTree.Node | undefined): node is TSESTree.ConditionalExpression;
export declare function isContinueStatement(node: TSESTree.Node | undefined): node is TSESTree.ContinueStatement;
export declare function isExpressionStatement(node: TSESTree.Node | undefined): node is TSESTree.ExpressionStatement;
export declare function isFunctionDeclaration(node: TSESTree.Node | undefined): node is TSESTree.FunctionDeclaration;
export declare function isFunctionExpression(node: TSESTree.Node | undefined): node is TSESTree.FunctionExpression;
export declare function isIdentifier(node: TSESTree.Node | undefined): node is TSESTree.Identifier;
export declare function isIfStatement(node: TSESTree.Node | undefined): node is TSESTree.IfStatement;
export declare function isLiteral(node: TSESTree.Node | undefined): node is TSESTree.Literal;
export declare function isLogicalExpression(node: TSESTree.Node | undefined): node is TSESTree.LogicalExpression;
export declare function isMemberExpression(node: TSESTree.Node | undefined): node is TSESTree.MemberExpression;
export declare function isModuleDeclaration(node: TSESTree.Node | undefined): node is TSESTree.ExportAllDeclaration | TSESTree.ExportDefaultDeclaration | TSESTree.ExportNamedDeclaration | TSESTree.ImportDeclaration;
export declare function isObjectExpression(node: TSESTree.Node | undefined): node is TSESTree.ObjectExpression;
export declare function isReturnStatement(node: TSESTree.Node | undefined): node is TSESTree.ReturnStatement;
export declare function isThrowStatement(node: TSESTree.Node | undefined): node is TSESTree.ThrowStatement;
export declare function isVariableDeclaration(node: TSESTree.Node | undefined): node is TSESTree.VariableDeclaration;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isVariableDeclaration = exports.isThrowStatement = exports.isReturnStatement = exports.isObjectExpression = exports.isModuleDeclaration = exports.isMemberExpression = exports.isLogicalExpression = exports.isLiteral = exports.isIfStatement = exports.isIdentifier = exports.isFunctionExpression = exports.isFunctionDeclaration = exports.isExpressionStatement = exports.isContinueStatement = exports.isConditionalExpression = exports.isCallExpression = exports.isBooleanLiteral = exports.isBlockStatement = exports.isBinaryExpression = exports.isAssignmentExpression = exports.isArrowFunctionExpression = exports.getParent = void 0;
exports.isVariableDeclaration = exports.isThrowStatement = exports.isReturnStatement = exports.isObjectExpression = exports.isModuleDeclaration = exports.isMemberExpression = exports.isLogicalExpression = exports.isLiteral = exports.isIfStatement = exports.isIdentifier = exports.isFunctionExpression = exports.isFunctionDeclaration = exports.isExpressionStatement = exports.isContinueStatement = exports.isConditionalExpression = exports.isCallExpression = exports.isBooleanLiteral = exports.isBlockStatement = exports.isBinaryExpression = exports.isAssignmentExpression = exports.isArrowFunctionExpression = void 0;
/*
* eslint-plugin-sonarjs
* Copyright (C) 2018-2021 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 GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* 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 GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
const MODULE_DECLARATION_NODES = [
"ImportDeclaration",
"ExportNamedDeclaration",
"ExportDefaultDeclaration",
"ExportAllDeclaration",
experimental_utils_1.AST_NODE_TYPES.ImportDeclaration,
experimental_utils_1.AST_NODE_TYPES.ExportNamedDeclaration,
experimental_utils_1.AST_NODE_TYPES.ExportDefaultDeclaration,
experimental_utils_1.AST_NODE_TYPES.ExportAllDeclaration,
];
function getParent(context) {
const ancestors = context.getAncestors();
return ancestors.length > 0 ? ancestors[ancestors.length - 1] : undefined;
}
exports.getParent = getParent;
function isArrowFunctionExpression(node) {
return node !== undefined && node.type === "ArrowFunctionExpression";
return node !== undefined && node.type === 'ArrowFunctionExpression';
}
exports.isArrowFunctionExpression = isArrowFunctionExpression;
function isAssignmentExpression(node) {
return node !== undefined && node.type === "AssignmentExpression";
return node !== undefined && node.type === 'AssignmentExpression';
}
exports.isAssignmentExpression = isAssignmentExpression;
function isBinaryExpression(node) {
return node !== undefined && node.type === "BinaryExpression";
return node !== undefined && node.type === 'BinaryExpression';
}
exports.isBinaryExpression = isBinaryExpression;
function isBlockStatement(node) {
return node !== undefined && node.type === "BlockStatement";
return node !== undefined && node.type === 'BlockStatement';
}
exports.isBlockStatement = isBlockStatement;
function isBooleanLiteral(node) {
return isLiteral(node) && typeof node.value === "boolean";
return isLiteral(node) && typeof node.value === 'boolean';
}
exports.isBooleanLiteral = isBooleanLiteral;
function isCallExpression(node) {
return node !== undefined && node.type === "CallExpression";
return node !== undefined && node.type === 'CallExpression';
}
exports.isCallExpression = isCallExpression;
function isConditionalExpression(node) {
return node !== undefined && node.type === "ConditionalExpression";
return node !== undefined && node.type === 'ConditionalExpression';
}
exports.isConditionalExpression = isConditionalExpression;
function isContinueStatement(node) {
return node !== undefined && node.type === "ContinueStatement";
return node !== undefined && node.type === 'ContinueStatement';
}
exports.isContinueStatement = isContinueStatement;
function isExpressionStatement(node) {
return node !== undefined && node.type === "ExpressionStatement";
return node !== undefined && node.type === 'ExpressionStatement';
}
exports.isExpressionStatement = isExpressionStatement;
function isFunctionDeclaration(node) {
return node !== undefined && node.type === "FunctionDeclaration";
return node !== undefined && node.type === 'FunctionDeclaration';
}
exports.isFunctionDeclaration = isFunctionDeclaration;
function isFunctionExpression(node) {
return node !== undefined && node.type === "FunctionExpression";
return node !== undefined && node.type === 'FunctionExpression';
}
exports.isFunctionExpression = isFunctionExpression;
function isIdentifier(node) {
return node !== undefined && node.type === "Identifier";
return node !== undefined && node.type === 'Identifier';
}
exports.isIdentifier = isIdentifier;
function isIfStatement(node) {
return node !== undefined && node.type === "IfStatement";
return node !== undefined && node.type === 'IfStatement';
}
exports.isIfStatement = isIfStatement;
function isLiteral(node) {
return node !== undefined && node.type === "Literal";
return node !== undefined && node.type === 'Literal';
}
exports.isLiteral = isLiteral;
function isLogicalExpression(node) {
return node !== undefined && node.type === "LogicalExpression";
return node !== undefined && node.type === 'LogicalExpression';
}
exports.isLogicalExpression = isLogicalExpression;
function isMemberExpression(node) {
return node !== undefined && node.type === "MemberExpression";
return node !== undefined && node.type === 'MemberExpression';
}

@@ -84,17 +99,17 @@ exports.isMemberExpression = isMemberExpression;

function isObjectExpression(node) {
return node !== undefined && node.type === "ObjectExpression";
return node !== undefined && node.type === 'ObjectExpression';
}
exports.isObjectExpression = isObjectExpression;
function isReturnStatement(node) {
return node !== undefined && node.type === "ReturnStatement";
return node !== undefined && node.type === 'ReturnStatement';
}
exports.isReturnStatement = isReturnStatement;
function isThrowStatement(node) {
return node !== undefined && node.type === "ThrowStatement";
return node !== undefined && node.type === 'ThrowStatement';
}
exports.isThrowStatement = isThrowStatement;
function isVariableDeclaration(node) {
return node !== undefined && node.type === "VariableDeclaration";
return node !== undefined && node.type === 'VariableDeclaration';
}
exports.isVariableDeclaration = isVariableDeclaration;
//# sourceMappingURL=nodes.js.map

@@ -1,5 +0,5 @@

import { ParserServices } from "@typescript-eslint/parser";
import { ParserServices } from '@typescript-eslint/experimental-utils';
export declare type RequiredParserServices = {
[k in keyof ParserServices]: Exclude<ParserServices[k], undefined>;
};
export declare function isRequiredParserServices(services: ParserServices): services is RequiredParserServices;
export declare function isRequiredParserServices(services: ParserServices | undefined): services is RequiredParserServices;
{
"name": "eslint-plugin-sonarjs",
"version": "0.8.0-125",
"version": "0.9.0",
"description": "SonarJS rules for ESLint",

@@ -22,9 +22,11 @@ "main": "lib/index.js",

"scripts": {
"build": "rimraf lib && tsc -d -p tsconfig-src.json",
"build": "rimraf lib && npm run check-format && tsc -d -p tsconfig-src.json",
"test": "jest",
"ruling": "ts-node ruling/index.ts",
"ruling": "ts-node --files ruling/index.ts",
"typecheck": "tsc -p tsconfig.json",
"lint": "eslint --ext js,ts src tests ruling/index.ts",
"precommit": "lint-staged && yarn typecheck",
"prepack": "yarn build"
"precommit": "lint-staged && npm run typecheck",
"prepack": "npm run build",
"format": "prettier --write \"{src,tests}/**/*.ts\"",
"check-format": "prettier --list-different \"{src,tests}/**/*.ts\""
},

@@ -35,4 +37,2 @@ "peerDependencies": {

"devDependencies": {
"@types/eslint": "7.2.6",
"@types/estree": "0.0.46",
"@types/jest": "26.0.20",

@@ -42,4 +42,4 @@ "@types/lodash": "4.14.106",

"@types/node": "14.14.25",
"@typescript-eslint/experimental-utils": "4.15.0",
"@typescript-eslint/parser": "4.15.0",
"@typescript-eslint/experimental-utils": "4.28.0",
"@typescript-eslint/parser": "4.28.0",
"babel-eslint": "8.2.2",

@@ -56,11 +56,14 @@ "eslint": "7.19.0",

"minimist": "1.2.3",
"prettier": "1.11.1",
"prettier": "2.3.0",
"rimraf": "2.6.2",
"ts-jest": "26.5.1",
"ts-node": "9.1.1",
"typescript": "4.1.4"
"typescript": "4.3.4"
},
"prettier": {
"printWidth": 120,
"trailingComma": "all"
"printWidth": 100,
"trailingComma": "all",
"singleQuote": true,
"arrowParens": "avoid",
"endOfLine": "lf"
},

@@ -67,0 +70,0 @@ "jest": {

@@ -11,9 +11,13 @@ # eslint-plugin-sonarjs [![npm version](https://badge.fury.io/js/eslint-plugin-sonarjs.svg)](https://badge.fury.io/js/eslint-plugin-sonarjs) [![Build Status](https://api.cirrus-ci.com/github/SonarSource/eslint-plugin-sonarjs.svg?branch=master)](https://cirrus-ci.com/github/SonarSource/eslint-plugin-sonarjs) [![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=eslint-plugin-sonarjs&metric=alert_status)](https://sonarcloud.io/dashboard?id=eslint-plugin-sonarjs) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=eslint-plugin-sonarjs&metric=coverage)](https://sonarcloud.io/dashboard?id=eslint-plugin-sonarjs)

* Generators should "yield" something ([`generator-without-yield`])
* All branches in a conditional structure should not have exactly the same implementation ([`no-all-duplicated-branches`])
* Collection elements should not be replaced unconditionally ([`no-element-overwrite`])
* Empty collections should not be accessed or iterated ([`no-empty-collection`])
* Function calls should not pass extra arguments ([`no-extra-arguments`])
* Related "if/else if" statements should not have the same condition ([`no-identical-conditions`])
* Identical expressions should not be used on both sides of a binary operator ([`no-identical-expressions`])
* Return values from functions without side effects should not be ignored ([`no-ignored-return`])
* Loops with at most one iteration should be refactored ([`no-one-iteration-loop`])
* The output of functions that don't return anything should not be used ([`no-use-of-empty-return-value`])
* Non-existent operators '=+', '=-' and '=!' should not be used ([`non-existent-operator`])

@@ -25,2 +29,3 @@ ### Code Smell Detection :pig:

* Cognitive Complexity of functions should not be too high ([`cognitive-complexity`])
* "if ... else if" constructs should end with "else" clauses ([`elseif-without-else`]) (*disabled*)
* "switch" statements should not have too many "case" clauses ([`max-switch-cases`])

@@ -31,4 +36,7 @@ * Collapsible "if" statements should be merged ([`no-collapsible-if`])

* Two branches in a conditional structure should not have exactly the same implementation ([`no-duplicated-branches`])
* Boolean expressions should not be gratuitous ([`no-gratuitous-expressions`])
* Functions should not have identical implementations ([`no-identical-functions`])
* Boolean checks should not be inverted ([`no-inverted-boolean-check`]) (:wrench: *fixable*)
* "switch" statements should not be nested ([`no-nested-switch`])
* Template literals should not be nested ([`no-nested-template-literals`])
* Boolean literals should not be redundant ([`no-redundant-boolean`])

@@ -46,2 +54,4 @@ * Jump statements should not be redundant ([`no-redundant-jump`])

[`cognitive-complexity`]: ./docs/rules/cognitive-complexity.md
[`elseif-without-else`]: ./docs/rules/elseif-without-else.md
[`generator-without-yield`]: ./docs/rules/generator-without-yield.md
[`max-switch-cases`]: ./docs/rules/max-switch-cases.md

@@ -54,7 +64,12 @@ [`no-all-duplicated-branches`]: ./docs/rules/no-all-duplicated-branches.md

[`no-element-overwrite`]: ./docs/rules/no-element-overwrite.md
[`no-empty-collection`]: ./docs/rules/no-empty-collection.md
[`no-extra-arguments`]: ./docs/rules/no-extra-arguments.md
[`no-gratuitous-expressions`]: ./docs/rules/no-gratuitous-expressions.md
[`no-identical-conditions`]: ./docs/rules/no-identical-conditions.md
[`no-identical-expressions`]: ./docs/rules/no-identical-expressions.md
[`no-identical-functions`]: ./docs/rules/no-identical-functions.md
[`no-ignored-return`]: ./docs/rules/no-ignored-return.md
[`no-inverted-boolean-check`]: ./docs/rules/no-inverted-boolean-check.md
[`no-nested-switch`]: ./docs/rules/no-nested-switch.md
[`no-nested-template-literals`]: ./docs/rules/no-nested-template-literals.md
[`no-one-iteration-loop`]: ./docs/rules/no-one-iteration-loop.md

@@ -68,2 +83,3 @@ [`no-redundant-boolean`]: ./docs/rules/no-redundant-boolean.md

[`no-useless-catch`]: ./docs/rules/no-useless-catch.md
[`non-existent-operator`]: ./docs/rules/non-existent-operator.md
[`prefer-immediate-return`]: ./docs/rules/prefer-immediate-return.md

@@ -116,4 +132,7 @@ [`prefer-object-literal`]: ./docs/rules/prefer-object-literal.md

## Available Configurations
This plugin provides only `recommended` configuration. Almost all rules are activated in this profile with a few exceptions (check `disabled` tag in the rules list). `recommended` configuration activates rules with `error` severity.
## Contributing
You want to participate in the development of the project? Have a look at our [contributing](./docs/CONTRIBUTING.md) guide!

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc