@abaplint/core
Version:
abaplint - Core API
137 lines (135 loc) • 6.47 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Abapdoc = exports.AbapdocConf = void 0;
const _abap_rule_1 = require("./_abap_rule");
const _basic_rule_config_1 = require("./_basic_rule_config");
const issue_1 = require("../issue");
const visibility_1 = require("../abap/4_file_information/visibility");
const _irule_1 = require("./_irule");
class AbapdocConf extends _basic_rule_config_1.BasicRuleConfig {
constructor() {
super(...arguments);
/** Check local classes and interfaces for abapdoc. */
this.checkLocal = false;
this.classDefinition = false;
this.interfaceDefinition = false;
/** Ignores classes flagged as FOR TESTING */
this.ignoreTestClasses = true;
}
}
exports.AbapdocConf = AbapdocConf;
class Abapdoc extends _abap_rule_1.ABAPRule {
constructor() {
super(...arguments);
this.conf = new AbapdocConf();
}
getMetadata() {
return {
key: "abapdoc",
title: "Check abapdoc",
shortDescription: `Various checks regarding abapdoc.`,
extendedInformation: `Base rule checks for existence of abapdoc for public class methods and all interface methods.
Plus class and interface definitions.
https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#abap-doc-only-for-public-apis`,
tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Styleguide],
};
}
getConfig() {
return this.conf;
}
setConfig(conf) {
this.conf = conf;
}
runParsed(file) {
var _a, _b;
const issues = [];
const rows = file.getRawRows();
const regexEmptyTags = '^\\"! .*<[^/>]*><\\/';
const regexEmptyAbapdoc = '^\\"!.+$';
const regexEmptyParameterName = '^\\"! @parameter .+\\|';
let methods = [];
for (const classDef of file.getInfo().listClassDefinitions()) {
if (this.conf.checkLocal === false && classDef.isLocal === true) {
continue;
}
if (this.conf.ignoreTestClasses === true && classDef.isForTesting === true) {
continue;
}
methods = methods.concat(classDef.methods.filter(m => m.visibility === visibility_1.Visibility.Public));
if (this.conf.classDefinition === true) {
const previousRow = classDef.identifier.getStart().getRow() - 2;
if (((_a = rows[previousRow]) === null || _a === void 0 ? void 0 : _a.trim().substring(0, 2)) !== "\"!") {
const message = "Missing ABAP Doc for class " + classDef.identifier.getToken().getStr();
const issue = issue_1.Issue.atIdentifier(classDef.identifier, message, this.getMetadata().key, this.conf.severity);
issues.push(issue);
}
}
}
for (const interfaceDef of file.getInfo().listInterfaceDefinitions()) {
if (this.conf.checkLocal === false && interfaceDef.isLocal === true) {
continue;
}
methods = methods.concat(interfaceDef.methods);
if (this.conf.interfaceDefinition === true) {
const previousRow = interfaceDef.identifier.getStart().getRow() - 2;
if (((_b = rows[previousRow]) === null || _b === void 0 ? void 0 : _b.trim().substring(0, 2)) !== "\"!") {
const message = "Missing ABAP Doc for interface " + interfaceDef.identifier.getToken().getStr();
const issue = issue_1.Issue.atIdentifier(interfaceDef.identifier, message, this.getMetadata().key, this.conf.severity);
issues.push(issue);
}
}
}
for (const method of methods) {
if (method.isRedefinition === true) {
continue;
}
const previousRowsTexts = this.getAbapdoc(rows, method.identifier.getStart());
if (previousRowsTexts === undefined) {
continue;
}
for (const rowText of previousRowsTexts) {
if (rowText.trim().match(regexEmptyTags) !== null) {
const message = "Empty tag(s) in ABAP Doc for method " + method.identifier.getToken().getStr() + " (" + rowText + ")";
const issue = issue_1.Issue.atIdentifier(method.identifier, message, this.getMetadata().key, this.conf.severity);
issues.push(issue);
}
if (rowText.trim().match(regexEmptyAbapdoc) === null && previousRowsTexts.indexOf(rowText) === previousRowsTexts.length - 1) {
const message = "Missing ABAP Doc for method " + method.identifier.getToken().getStr() + " (" + rowText + ")";
const issue = issue_1.Issue.atIdentifier(method.identifier, message, this.getMetadata().key, this.conf.severity);
issues.push(issue);
}
if (rowText.trim().match(regexEmptyParameterName) !== null) {
const message = "Missing ABAP Doc parameter name for method " + method.identifier.getToken().getStr() + " (" + rowText + ")";
const issue = issue_1.Issue.atIdentifier(method.identifier, message, this.getMetadata().key, this.conf.severity);
issues.push(issue);
}
}
}
return issues;
}
getAbapdoc(rows, pos) {
let previousRow = pos.getRow() - 2;
let rowText = rows[previousRow].trim().toUpperCase();
const text = [];
if (rowText === "METHODS" || rowText === "CLASS-METHODS") {
previousRow--;
rowText = rows[previousRow].trim().toUpperCase();
}
text.push(rowText);
//we need to push the first row despite if it is actually an abapdoc or not
//if the first row above a method is abapdoc then try to get the rest of the abapdoc block above
if (rowText.trim().substring(0, 2) === "\"!") {
while (previousRow >= 0) {
previousRow--;
rowText = rows[previousRow].trim().toUpperCase();
if (rowText.trim().substring(0, 2) !== "\"!") {
break;
}
text.push(rowText);
}
}
return text;
}
}
exports.Abapdoc = Abapdoc;
//# sourceMappingURL=abapdoc.js.map