@abaplint/core
Version:
abaplint - Core API
121 lines (119 loc) • 6.63 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.UseBoolExpression = exports.UseBoolExpressionConf = void 0;
const issue_1 = require("../issue");
const Statements = require("../abap/2_statements/statements");
const Expressions = require("../abap/2_statements/expressions");
const Structures = require("../abap/3_structures/structures");
const _abap_rule_1 = require("./_abap_rule");
const _basic_rule_config_1 = require("./_basic_rule_config");
const version_1 = require("../version");
const _irule_1 = require("./_irule");
const edit_helper_1 = require("../edit_helper");
// note this rule assumes abap_true and abap_false is used for boolean variables
// some other rule will in the future find assignments to abap_bool that are not abap_true/abap_false/abap_undefined
class UseBoolExpressionConf extends _basic_rule_config_1.BasicRuleConfig {
}
exports.UseBoolExpressionConf = UseBoolExpressionConf;
class UseBoolExpression extends _abap_rule_1.ABAPRule {
constructor() {
super(...arguments);
this.conf = new UseBoolExpressionConf();
}
getMetadata() {
return {
key: "use_bool_expression",
title: "Use boolean expression",
shortDescription: `Use boolean expression, xsdbool from 740sp08 and up, boolc from 702 and up`,
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#use-xsdbool-to-set-boolean-variables`,
tags: [_irule_1.RuleTag.Upport, _irule_1.RuleTag.Styleguide, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.SingleFile],
badExample: `IF line IS INITIAL.
has_entries = abap_false.
ELSE.
has_entries = abap_true.
ENDIF.
DATA(fsdf) = COND #( WHEN foo <> bar THEN abap_true ELSE abap_false ).`,
goodExample: `DATA(has_entries) = xsdbool( line IS NOT INITIAL ).
DATA(fsdf) = xsdbool( foo <> bar ).`,
};
}
getConfig() {
return this.conf;
}
setConfig(conf) {
this.conf = conf;
}
runParsed(file) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
const issues = [];
const stru = file.getStructure();
const version = this.reg.getConfig().getVersion();
if (stru === undefined || (version < version_1.Version.v702 && version !== version_1.Version.Cloud)) {
return [];
}
for (const i of stru.findAllStructures(Structures.If)) {
if (i.findDirectStructure(Structures.ElseIf) !== undefined) {
continue;
}
const bodyNodes = (_a = i.findDirectStructure(Structures.Body)) === null || _a === void 0 ? void 0 : _a.findAllStatementNodes();
if (bodyNodes === undefined || bodyNodes.length !== 1) {
continue;
}
const bodyStatement = bodyNodes[0];
if (!(bodyStatement.get() instanceof Statements.Move)) {
continue;
}
const elseNodes = (_c = (_b = i.findDirectStructure(Structures.Else)) === null || _b === void 0 ? void 0 : _b.findDirectStructure(Structures.Body)) === null || _c === void 0 ? void 0 : _c.findAllStatementNodes();
if (elseNodes === undefined || elseNodes.length !== 1) {
continue;
}
const elseStatement = elseNodes[0];
if (!(elseStatement.get() instanceof Statements.Move)) {
continue;
}
let bodyTarget = (_d = bodyStatement.findFirstExpression(Expressions.Target)) === null || _d === void 0 ? void 0 : _d.concatTokens();
if (bodyTarget === null || bodyTarget === void 0 ? void 0 : bodyTarget.startsWith("DATA(")) {
bodyTarget = bodyTarget.substr(5, bodyTarget.length - 6);
}
const elseTarget = (_e = elseStatement.findFirstExpression(Expressions.Target)) === null || _e === void 0 ? void 0 : _e.concatTokens();
if (bodyTarget === undefined
|| elseTarget === undefined
|| bodyTarget.toUpperCase() !== elseTarget.toUpperCase()) {
continue;
}
const bodySource = (_f = bodyStatement.findFirstExpression(Expressions.Source)) === null || _f === void 0 ? void 0 : _f.concatTokens().toUpperCase();
const elseSource = (_g = elseStatement.findFirstExpression(Expressions.Source)) === null || _g === void 0 ? void 0 : _g.concatTokens().toUpperCase();
if ((bodySource === "ABAP_TRUE" && elseSource === "ABAP_FALSE")
|| (bodySource === "ABAP_FALSE" && elseSource === "ABAP_TRUE")) {
const func = (this.reg.getConfig().getVersion() >= version_1.Version.v740sp08
|| this.reg.getConfig().getVersion() === version_1.Version.Cloud) ? "xsdbool" : "boolc";
const negate = bodySource === "ABAP_FALSE";
const message = `Use ${func} instead of IF` + (negate ? ", negate expression" : "");
const start = i.getFirstToken().getStart();
const end = i.getLastToken().getEnd();
const statement = bodyTarget + " = " + func + "( " +
(negate ? "NOT ( " : "") +
((_j = (_h = i.findFirstStatement(Statements.If)) === null || _h === void 0 ? void 0 : _h.findFirstExpression(Expressions.Cond)) === null || _j === void 0 ? void 0 : _j.concatTokens()) +
(negate ? " )" : "") +
" ).";
const fix = edit_helper_1.EditHelper.replaceRange(file, start, end, statement);
issues.push(issue_1.Issue.atRange(file, start, end, message, this.getMetadata().key, this.conf.severity, fix));
}
}
if (version >= version_1.Version.v740sp08 || version === version_1.Version.Cloud) {
for (const b of stru.findAllExpressions(Expressions.CondBody)) {
const concat = b.concatTokens().toUpperCase();
if (concat.endsWith(" THEN ABAP_TRUE ELSE ABAP_FALSE")
|| concat.endsWith(" THEN ABAP_TRUE")
|| concat.endsWith(" THEN ABAP_FALSE ELSE ABAP_TRUE")) {
const message = "Use xsdbool";
// eslint-disable-next-line max-len
issues.push(issue_1.Issue.atRange(file, b.getFirstToken().getStart(), b.getLastToken().getEnd(), message, this.getMetadata().key, this.conf.severity));
}
}
}
return issues;
}
}
exports.UseBoolExpression = UseBoolExpression;
//# sourceMappingURL=use_bool_expression.js.map