UNPKG

@abaplint/core

Version:
222 lines (218 loc) • 10.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CheckSubrc = exports.CheckSubrcConf = void 0; const Statements = require("../abap/2_statements/statements"); const Expressions = require("../abap/2_statements/expressions"); const issue_1 = require("../issue"); const _basic_rule_config_1 = require("./_basic_rule_config"); const _abap_rule_1 = require("./_abap_rule"); const _irule_1 = require("./_irule"); const _statement_1 = require("../abap/2_statements/statements/_statement"); const edit_helper_1 = require("../edit_helper"); class CheckSubrcConf extends _basic_rule_config_1.BasicRuleConfig { constructor() { super(...arguments); this.openDataset = true; this.authorityCheck = true; this.selectSingle = true; this.selectTable = true; this.updateDatabase = true; this.insertDatabase = true; this.modifyDatabase = true; this.readTable = true; this.assign = true; this.find = true; } } exports.CheckSubrcConf = CheckSubrcConf; class CheckSubrc extends _abap_rule_1.ABAPRule { constructor() { super(...arguments); this.conf = new CheckSubrcConf(); } getMetadata() { return { key: "check_subrc", title: "Check sy-subrc", shortDescription: `Check sy-subrc`, extendedInformation: `Pseudo comment "#EC CI_SUBRC can be added to suppress findings If sy-dbcnt is checked after database statements, it is considered okay. "SELECT SINGLE @abap_true FROM " is considered as an existence check, also "SELECT COUNT( * )" is considered okay If IS ASSIGNED is checked after assigning, it is considered okay. FIND statement with MATCH COUNT is considered okay if subrc is not checked`, tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Quickfix], pseudoComment: "EC CI_SUBRC", pragma: "##SUBRC_OK", }; } getConfig() { return this.conf; } setConfig(conf) { this.conf = conf; } buildFix(file, statement) { return { description: "Add ##SUBRC_OK", edit: edit_helper_1.EditHelper.insertAt(file, statement.getLastToken().getStart(), " ##SUBRC_OK"), }; } runParsed(file) { const issues = []; const statements = file.getStatements(); const message = "Check sy-subrc"; const config = this.getConfig(); for (let i = 0; i < statements.length; i++) { const statement = statements[i]; // todo: CALL FUNCTION if (statement.getPragmas().some(t => t.getStr() === this.getMetadata().pragma)) { continue; } if (config.openDataset === true && statement.get() instanceof Statements.OpenDataset && this.isChecked(i, statements) === false) { // it doesnt make sense to ignore the subrc for open dataset, so no quick fix issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity)); } else if (config.authorityCheck === true && statement.get() instanceof Statements.AuthorityCheck && this.isChecked(i, statements) === false) { // it doesnt make sense to ignore the subrc for authority checks, so no quick fix issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity)); } else if (config.selectSingle === true && statement.get() instanceof Statements.Select && statement.concatTokens().toUpperCase().startsWith("SELECT SINGLE ") && this.isChecked(i, statements) === false && this.checksDbcnt(i, statements) === false) { const concat = statement.concatTokens().toUpperCase(); if (concat.startsWith("SELECT SINGLE @ABAP_TRUE FROM ")) { continue; } const fix = this.buildFix(file, statement); issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix])); } else if (config.selectTable === true && statement.get() instanceof Statements.Select && statement.concatTokens().toUpperCase().startsWith("SELECT SINGLE ") === false && statement.concatTokens().toUpperCase().startsWith("SELECT COUNT( * ) ") === false && statement.concatTokens().toUpperCase().startsWith("SELECT COUNT(*) ") === false && this.isChecked(i, statements) === false && this.checksDbcnt(i, statements) === false) { const fix = this.buildFix(file, statement); issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix])); } else if (config.updateDatabase === true && statement.get() instanceof Statements.UpdateDatabase && this.isChecked(i, statements) === false && this.checksDbcnt(i, statements) === false) { const fix = this.buildFix(file, statement); issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix])); } else if (config.insertDatabase === true && statement.get() instanceof Statements.InsertDatabase && this.isChecked(i, statements) === false && this.checksDbcnt(i, statements) === false) { const fix = this.buildFix(file, statement); issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix])); } else if (config.modifyDatabase === true && statement.get() instanceof Statements.ModifyDatabase && this.isChecked(i, statements) === false && this.checksDbcnt(i, statements) === false) { const fix = this.buildFix(file, statement); issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix])); } else if (config.readTable === true && statement.get() instanceof Statements.ReadTable && this.isChecked(i, statements) === false) { const fix = this.buildFix(file, statement); issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix])); } else if (config.assign === true && statement.get() instanceof Statements.Assign && this.isSimpleAssign(statement) === false && this.isChecked(i, statements) === false) { const fix = this.buildFix(file, statement); issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix])); } else if (config.find === true && statement.get() instanceof Statements.Find && this.isExemptedFind(statement) === false && this.isChecked(i, statements) === false) { const fix = this.buildFix(file, statement); issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix])); } } return issues; } //////////////// isSimpleAssign(statement) { if (statement.getChildren().length === 5) { const source = statement.findDirectExpression(Expressions.AssignSource); if ((source === null || source === void 0 ? void 0 : source.getChildren().length) === 1 && source.findDirectExpression(Expressions.Source) !== undefined) { return true; } } return false; } isExemptedFind(s) { // see https://github.com/abaplint/abaplint/issues/2130 return s.concatTokens().toUpperCase().includes(" MATCH COUNT ") === true; } checksDbcnt(index, statements) { for (let i = index + 1; i < statements.length; i++) { const statement = statements[i]; const concat = statement.concatTokens().toUpperCase(); if (statement.get() instanceof _statement_1.Comment) { continue; } else if (statement.get() instanceof Statements.EndIf || statement.get() instanceof Statements.EndTestSeam) { continue; } else { return concat.includes("SY-DBCNT"); } } return false; } isChecked(index, statements) { var _a, _b; let assigned = undefined; let assignedn = undefined; if (statements[index].get() instanceof Statements.Assign || statements[index].get() instanceof Statements.ReadTable) { const fs = (_b = (_a = statements[index].findFirstExpression(Expressions.FSTarget)) === null || _a === void 0 ? void 0 : _a.findFirstExpression(Expressions.FieldSymbol)) === null || _b === void 0 ? void 0 : _b.getFirstToken().getStr(); assigned = (fs === null || fs === void 0 ? void 0 : fs.toUpperCase()) + " IS ASSIGNED"; assignedn = (fs === null || fs === void 0 ? void 0 : fs.toUpperCase()) + " IS NOT ASSIGNED"; } for (let i = index + 1; i < statements.length; i++) { const statement = statements[i]; const concat = statement.concatTokens().toUpperCase(); if (statement.get() instanceof _statement_1.Comment) { if (concat.includes("" + this.getMetadata().pseudoComment)) { return true; } } else if (statement.get() instanceof Statements.EndIf || statement.get() instanceof Statements.EndTestSeam) { continue; } else { if (assigned && concat.includes(assigned)) { return true; } if (assignedn && concat.includes(assignedn)) { return true; } return concat.includes(" SY-SUBRC") || concat.includes("CL_ABAP_UNIT_ASSERT=>ASSERT_SUBRC"); } } return false; } } exports.CheckSubrc = CheckSubrc; //# sourceMappingURL=check_subrc.js.map