@abaplint/core
Version:
abaplint - Core API
143 lines (142 loc) • 5.55 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChangeIfToCase = exports.ChangeIfToCaseConf = void 0;
const issue_1 = require("../issue");
const Expressions = require("../abap/2_statements/expressions");
const Statements = require("../abap/2_statements/statements");
const Structures = require("../abap/3_structures/structures");
const _abap_rule_1 = require("./_abap_rule");
const _basic_rule_config_1 = require("./_basic_rule_config");
const _irule_1 = require("./_irule");
class ChangeIfToCaseConf extends _basic_rule_config_1.BasicRuleConfig {
constructor() {
super(...arguments);
/** skip specific names, case insensitive regular expression
* @uniqueItems true
*/
this.skipNames = [];
}
}
exports.ChangeIfToCaseConf = ChangeIfToCaseConf;
class ChangeIfToCase extends _abap_rule_1.ABAPRule {
constructor() {
super(...arguments);
this.conf = new ChangeIfToCaseConf();
}
getMetadata() {
return {
key: "change_if_to_case",
title: "Change IF to CASE",
shortDescription: `Finds IF constructs that can be changed to CASE`,
// eslint-disable-next-line max-len
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-case-to-else-if-for-multiple-alternative-conditions
If the first comparison is a boolean compare, no issue is reported.`,
tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Styleguide],
badExample: `IF l_fcat-fieldname EQ 'FOO'.
ELSEIF l_fcat-fieldname = 'BAR'
OR l_fcat-fieldname = 'MOO'.
ENDIF.`,
goodExample: `CASE l_fcat-fieldname.
WHEN 'FOO'.
WHEN 'BAR' OR 'MOO'.
ENDCASE.`,
};
}
getConfig() {
return this.conf;
}
setConfig(conf) {
this.conf = conf;
}
runParsed(file) {
var _a;
const issues = [];
const stru = file.getStructure();
if (stru === undefined) {
return issues;
}
for (const i of stru.findAllStructuresRecursive(Structures.If)) {
const conds = [];
const ifStatement = i.findDirectStatement(Statements.If);
if (ifStatement === undefined) {
continue;
}
if (ifStatement.concatTokens().match(/ (abap_true|abap_false)\s*\./i)) {
continue;
}
conds.push(ifStatement === null || ifStatement === void 0 ? void 0 : ifStatement.findDirectExpression(Expressions.Cond));
for (const ei of i.findDirectStructures(Structures.ElseIf)) {
conds.push((_a = ei.findDirectStatement(Statements.ElseIf)) === null || _a === void 0 ? void 0 : _a.findDirectExpression(Expressions.Cond));
}
if (conds.length === 1) {
continue;
}
const issue = this.analyze(conds);
if (issue === true) {
const message = "Change IF to CASE";
issues.push(issue_1.Issue.atStatement(file, ifStatement, message, this.getMetadata().key, this.getConfig().severity));
}
}
return issues;
}
analyze(conds) {
var _a, _b, _c, _d, _e;
const tuples = [];
for (const c of conds) {
if (c === undefined) {
continue;
}
if (c.findFirstExpression(Expressions.CondSub)) {
return false;
}
else if (c.findDirectTokenByText("AND") || c.findDirectTokenByText("EQUIV")) {
return false;
}
for (const compare of c.findAllExpressions(Expressions.Compare)) {
const op = (_a = compare.findDirectExpression(Expressions.CompareOperator)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase();
if (compare.getChildren().length !== 3) {
return false;
}
else if (op !== "=" && op !== "EQ") {
return false;
}
const left = (_c = (_b = compare.getChildren()[0]) === null || _b === void 0 ? void 0 : _b.concatTokens()) === null || _c === void 0 ? void 0 : _c.toUpperCase();
const right = (_e = (_d = compare.getChildren()[2]) === null || _d === void 0 ? void 0 : _d.concatTokens()) === null || _e === void 0 ? void 0 : _e.toUpperCase();
tuples.push({ left, right });
}
}
if (tuples.length === 1) {
return false;
}
let chain = "";
if (tuples[0].left === tuples[1].left) {
chain = tuples[0].left;
}
else if (tuples[0].left === tuples[1].right) {
chain = tuples[0].left;
}
else if (tuples[0].right === tuples[1].right) {
chain = tuples[0].right;
}
else if (tuples[0].right === tuples[1].left) {
chain = tuples[0].right;
}
else {
return false;
}
for (const skip of this.getConfig().skipNames || []) {
const reg = new RegExp(skip, "i");
if (chain.match(reg)) {
return false;
}
}
for (const t of tuples) {
if (t.left !== chain && t.right !== chain) {
return false;
}
}
return true;
}
}
exports.ChangeIfToCase = ChangeIfToCase;
//# sourceMappingURL=change_if_to_case.js.map