@abaplint/core
Version:
abaplint - Core API
160 lines (159 loc) • 6.88 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EmptyStructure = exports.EmptyStructureConf = void 0;
const issue_1 = require("../issue");
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 _statement_1 = require("../abap/2_statements/statements/_statement");
class EmptyStructureConf extends _basic_rule_config_1.BasicRuleConfig {
constructor() {
super(...arguments);
/** Checks for empty LOOP blocks */
this.loop = true;
/** Allow empty LOOP if subrc is checked after the loop */
this.loopAllowIfSubrc = true;
/** Checks for empty IF blocks */
this.if = true;
/** Checks for empty WHILE blocks */
this.while = true;
/** Checks for empty CASE blocks */
this.case = true;
/** Checks for empty SELECT blockss */
this.select = true;
/** Checks for empty DO blocks */
this.do = true;
/** Checks for empty AT blocks */
this.at = true;
/** Checks for empty TRY blocks */
this.try = true;
/** Checks for empty WHEN blocks */
this.when = true;
// todo, other category containing ELSE
}
}
exports.EmptyStructureConf = EmptyStructureConf;
class EmptyStructure extends _abap_rule_1.ABAPRule {
constructor() {
super(...arguments);
this.conf = new EmptyStructureConf();
}
getMetadata() {
return {
key: "empty_structure",
title: "Find empty blocks",
shortDescription: `Checks that the code does not contain empty blocks.`,
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#no-empty-if-branches`,
tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
badExample: `IF foo = bar.
ENDIF.
DO 2 TIMES.
ENDDO.`,
goodExample: `LOOP AT itab WHERE qty = 0 OR date > sy-datum.
ENDLOOP.
result = xsdbool( sy-subrc = 0 ).`,
};
}
getDescription(name) {
return "Empty block, add code: " + name;
}
getConfig() {
return this.conf;
}
setConfig(conf) {
this.conf = conf;
}
runParsed(file) {
const issues = [];
const stru = file.getStructure();
if (stru === undefined) {
return [];
}
const statements = file.getStatements();
for (const statement of statements) {
if (statement.get() instanceof _statement_1.Unknown) {
return []; // contains parser errors
}
}
const candidates = [];
if (this.getConfig().while === true) {
candidates.push(...stru.findAllStructuresRecursive(Structures.While));
}
if (this.getConfig().case === true) {
candidates.push(...stru.findAllStructuresRecursive(Structures.Case));
}
if (this.getConfig().select === true) {
candidates.push(...stru.findAllStructuresRecursive(Structures.Select));
}
if (this.getConfig().do === true) {
candidates.push(...stru.findAllStructuresRecursive(Structures.Do));
}
if (this.getConfig().at === true) {
candidates.push(...stru.findAllStructuresRecursive(Structures.At));
candidates.push(...stru.findAllStructuresRecursive(Structures.AtFirst));
candidates.push(...stru.findAllStructuresRecursive(Structures.AtLast));
}
for (const l of candidates) {
if (l.getChildren().length === 2) {
const token = l.getFirstToken();
const issue = issue_1.Issue.atToken(file, token, this.getDescription(l.get().constructor.name), this.getMetadata().key, this.conf.severity);
issues.push(issue);
}
}
if (this.getConfig().try === true) {
const tries = stru.findAllStructuresRecursive(Structures.Try);
for (const t of tries) {
const normal = t.findDirectStructure(Structures.Body);
if (normal === undefined) {
const token = t.getFirstToken();
const issue = issue_1.Issue.atToken(file, token, this.getDescription(t.get().constructor.name), this.getMetadata().key, this.conf.severity);
issues.push(issue);
}
}
}
if (this.getConfig().loop === true) {
const loops = stru.findAllStructuresRecursive(Structures.Loop);
for (const loop of loops) {
if (loop.getChildren().length === 2) {
const endloopStatement = loop.getLastChild();
const endloopIndex = statements.findIndex((s) => s === endloopStatement);
const afterEndloop = statements[endloopIndex + 1];
if (afterEndloop !== undefined && afterEndloop.concatTokens().toUpperCase().includes("SY-SUBRC")) {
continue;
}
const token = loop.getFirstToken();
const issue = issue_1.Issue.atToken(file, token, this.getDescription(loop.get().constructor.name), this.getMetadata().key, this.conf.severity);
issues.push(issue);
}
}
}
if (this.getConfig().if === true) {
const tries = stru.findAllStructuresRecursive(Structures.If)
.concat(stru.findAllStructuresRecursive(Structures.Else))
.concat(stru.findAllStructuresRecursive(Structures.ElseIf));
for (const t of tries) {
const normal = t.findDirectStructure(Structures.Body);
if (normal === undefined) {
const token = t.getFirstToken();
const issue = issue_1.Issue.atToken(file, token, this.getDescription(t.get().constructor.name), this.getMetadata().key, this.conf.severity);
issues.push(issue);
}
}
}
if (this.getConfig().when === true) {
const tries = stru.findAllStructuresRecursive(Structures.When);
for (const t of tries) {
if (t.getChildren().length === 1) {
const token = t.getFirstToken();
const message = this.getDescription(t.get().constructor.name);
const issue = issue_1.Issue.atToken(file, token, message, this.getMetadata().key, this.conf.severity);
issues.push(issue);
}
}
}
return issues;
}
}
exports.EmptyStructure = EmptyStructure;
//# sourceMappingURL=empty_structure.js.map