@abaplint/core
Version:
abaplint - Core API
130 lines (125 loc) • 4.69 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.IfInIf = exports.IfInIfConf = void 0;
const issue_1 = require("../issue");
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");
const edit_helper_1 = require("../edit_helper");
class IfInIfConf extends _basic_rule_config_1.BasicRuleConfig {
}
exports.IfInIfConf = IfInIfConf;
class IfInIf extends _abap_rule_1.ABAPRule {
constructor() {
super(...arguments);
this.conf = new IfInIfConf();
}
getMetadata() {
return {
key: "if_in_if",
title: "IF in IF",
shortDescription: `Detects nested ifs which can be refactored.`,
extendedInformation: `
Directly nested IFs without ELSE can be refactored to a single condition using AND.
ELSE condtions with directly nested IF refactored to ELSEIF, quickfixes are suggested for this case.
https://docs.abapopenchecks.org/checks/01/
https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#keep-the-nesting-depth-low`,
badExample: `IF condition1.
IF condition2.
...
ENDIF.
ENDIF.
IF condition1.
...
ELSE.
IF condition2.
...
ENDIF.
ENDIF.`,
goodExample: `IF ( condition1 ) AND ( condition2 ).
...
ENDIF.
IF condition1.
...
ELSEIF condition2.
...
ENDIF.
CASE variable.
WHEN value1.
...
WHEN value2.
IF condition2.
...
ENDIF.
ENDCASE.`,
tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Quickfix],
};
}
getConfig() {
return this.conf;
}
setConfig(conf) {
this.conf = conf;
}
runParsed(file, obj) {
var _a, _b;
const issues = [];
if (obj.getType() === "INTF") {
return [];
}
const stru = file.getStructure();
if (stru === undefined) {
return [];
}
let fixed = false;
let possible = stru.findAllStructures(Structures.If);
possible = possible.concat(stru.findAllStructures(Structures.Else));
for (const i of possible) {
if (i.findDirectStructures(Structures.ElseIf).length > 0
|| i.findDirectStructures(Structures.Else).length > 0) {
continue;
}
const blist = i.findDirectStructures(Structures.Body);
if (blist.length === 0) {
continue;
}
const nlist = blist[0].findDirectStructures(Structures.Normal);
if (nlist.length !== 1) {
continue;
}
const niflist = nlist[0].findDirectStructures(Structures.If);
if (niflist.length !== 1) {
continue;
}
const nestedIf = niflist[0];
if (i.get() instanceof Structures.If
&& (nestedIf.findDirectStructures(Structures.ElseIf).length > 0
|| nestedIf.findDirectStructures(Structures.Else).length > 0)) {
continue;
}
let message = "IF in IF. Use IF cond1 AND cond2 instead";
let fix = undefined;
if (i.get() instanceof Structures.Else) {
message = "Change ELSE part to ELSEIF";
const els = i.findFirstStatement(Statements.Else);
const iff = (_a = i.findFirstStructure(Structures.If)) === null || _a === void 0 ? void 0 : _a.findDirectStatement(Statements.If);
const endif = (_b = i.findFirstStructure(Structures.If)) === null || _b === void 0 ? void 0 : _b.findDirectStatement(Statements.EndIf);
if (fixed === false && iff && els && endif) {
const fix1 = edit_helper_1.EditHelper.deleteRange(file, els.getLastToken().getStart(), iff === null || iff === void 0 ? void 0 : iff.getFirstToken().getStart());
const fix2 = edit_helper_1.EditHelper.deleteStatement(file, endif);
fix = edit_helper_1.EditHelper.merge(fix1, fix2);
// max one fix per file at a time
fixed = true;
}
}
const token = i.getFirstToken();
const issue = issue_1.Issue.atToken(file, token, message, this.getMetadata().key, this.conf.severity, fix);
issues.push(issue);
}
return issues;
}
}
exports.IfInIf = IfInIf;
//# sourceMappingURL=if_in_if.js.map