UNPKG

eslint-plugin-sonarjs

Version:
90 lines (89 loc) 3.71 kB
"use strict"; /* * 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/S135/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"); exports.rule = { meta: (0, index_js_1.generateMeta)(meta_js_1.meta, undefined, true), create(context) { let jumpTargets = []; function enterScope() { jumpTargets.push(new JumpTarget()); } function leaveScope() { jumpTargets.pop(); } function increateNumberOfJumpsInScopes(jump, label) { for (const jumpTarget of [...jumpTargets].reverse()) { jumpTarget.jumps.push(jump); if (label === jumpTarget.label) { break; } } } function leaveScopeAndCheckNumberOfJumps(node) { const jumps = jumpTargets.pop()?.jumps; if (jumps && jumps.length > 1) { const sourceCode = context.sourceCode; const firstToken = sourceCode.getFirstToken(node); (0, index_js_1.report)(context, { loc: firstToken.loc, message: 'Reduce the total number of "break" and "continue" statements in this loop to use one at most.', }, jumps.map(jmp => (0, index_js_1.toSecondaryLocation)(jmp, jmp.type === 'BreakStatement' ? '"break" statement.' : '"continue" statement.'))); } } return { Program: () => { jumpTargets = []; }, BreakStatement: (node) => { const breakStatement = node; increateNumberOfJumpsInScopes(breakStatement, breakStatement.label?.name); }, ContinueStatement: (node) => { const continueStatement = node; increateNumberOfJumpsInScopes(continueStatement, continueStatement.label?.name); }, SwitchStatement: enterScope, 'SwitchStatement:exit': leaveScope, ForStatement: enterScope, 'ForStatement:exit': leaveScopeAndCheckNumberOfJumps, ForInStatement: enterScope, 'ForInStatement:exit': leaveScopeAndCheckNumberOfJumps, ForOfStatement: enterScope, 'ForOfStatement:exit': leaveScopeAndCheckNumberOfJumps, WhileStatement: enterScope, 'WhileStatement:exit': leaveScopeAndCheckNumberOfJumps, DoWhileStatement: enterScope, 'DoWhileStatement:exit': leaveScopeAndCheckNumberOfJumps, LabeledStatement: (node) => { const labeledStatement = node; jumpTargets.push(new JumpTarget(labeledStatement.label.name)); }, 'LabeledStatement:exit': leaveScope, }; }, }; class JumpTarget { constructor(label) { this.jumps = []; this.label = label; } }