@abaplint/core
Version:
abaplint - Core API
107 lines (106 loc) • 4.13 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.UseLineExists = exports.UseLineExistsConf = void 0;
const issue_1 = require("../issue");
const Statements = require("../abap/2_statements/statements");
const Expressions = require("../abap/2_statements/expressions");
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 _statement_1 = require("../abap/2_statements/statements/_statement");
class UseLineExistsConf extends _basic_rule_config_1.BasicRuleConfig {
}
exports.UseLineExistsConf = UseLineExistsConf;
class UseLineExists extends _abap_rule_1.ABAPRule {
constructor() {
super(...arguments);
this.conf = new UseLineExistsConf();
}
getMetadata() {
return {
key: "use_line_exists",
title: "Use line_exists",
shortDescription: `Use line_exists, from 740sp02 and up`,
extendedInformation: `
https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-line_exists-to-read-table-or-loop-at
Not reported if the READ TABLE statement contains BINARY SEARCH.`,
tags: [_irule_1.RuleTag.Upport, _irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
badExample: `READ TABLE my_table TRANSPORTING NO FIELDS WITH KEY key = 'A'.
IF sy-subrc = 0.
ENDIF.`,
goodExample: `IF line_exists( my_table[ key = 'A' ] ).
ENDIF.`,
};
}
getConfig() {
return this.conf;
}
setConfig(conf) {
this.conf = conf;
}
runParsed(file, obj) {
const issues = [];
if (obj.getType() === "INTF") {
return [];
}
const vers = this.reg.getConfig().getVersion();
if (vers === version_1.Version.OpenABAP) {
return [];
}
else if (vers < version_1.Version.v740sp02 && vers !== version_1.Version.Cloud) {
return [];
}
const statements = file.getStatements();
for (let i = 0; i < statements.length; i++) {
const statement = statements[i];
if (!(statement.get() instanceof Statements.ReadTable)) {
continue;
}
const concat = statement.concatTokens().toUpperCase();
if (concat.includes(" TRANSPORTING NO FIELDS") === true
&& concat.includes(" BINARY SEARCH") === false
&& this.checksSubrc(i, statements) === true
&& this.usesTabix(i, statements) === false) {
issues.push(issue_1.Issue.atStatement(file, statement, "Use line_exists", this.getMetadata().key, this.conf.severity));
}
}
return issues;
}
///////////////////////
checksSubrc(index, statements) {
for (let i = index + 1; i < statements.length; i++) {
const statement = statements[i];
if (statement.get() instanceof _statement_1.Comment) {
continue;
}
for (const c of statement.findAllExpressions(Expressions.Cond)) {
for (const s of c.findAllExpressions(Expressions.Source)) {
if (s.concatTokens().toUpperCase() === "SY-SUBRC") {
return true;
}
}
}
return false;
}
return false;
}
// this is a heuristic, data flow analysis is required to get the correct result
usesTabix(index, statements) {
for (let i = index + 1; i < index + 5; i++) {
const statement = statements[i];
if (statement === undefined) {
break;
}
else if (statement.get() instanceof _statement_1.Comment) {
continue;
}
else if (statement.concatTokens().toUpperCase().includes(" SY-TABIX")) {
return true;
}
}
return false;
}
}
exports.UseLineExists = UseLineExists;
//# sourceMappingURL=use_line_exists.js.map