@abaplint/core
Version:
abaplint - Core API
221 lines • 10.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XMLConsistency = exports.XMLConsistencyConf = void 0;
const issue_1 = require("../issue");
const _irule_1 = require("./_irule");
const Objects = require("../objects");
const _abap_object_1 = require("../objects/_abap_object");
const _basic_rule_config_1 = require("./_basic_rule_config");
const fast_xml_parser_1 = require("fast-xml-parser");
const severity_1 = require("../severity");
class XMLConsistencyConf extends _basic_rule_config_1.BasicRuleConfig {
constructor() {
super(...arguments);
/** Problem severity for text and translation length checks */
this.textAndTranslationLengthSeverity = severity_1.Severity.Error;
}
}
exports.XMLConsistencyConf = XMLConsistencyConf;
class XMLConsistency {
constructor() {
this.conf = new XMLConsistencyConf();
}
getMetadata() {
return {
key: "xml_consistency",
title: "XML consistency",
shortDescription: `Checks the consistency of main XML files`,
extendedInformation: `Checks:
* XML is well-formed and parseable
* Naming for CLAS and INTF objects
* Texts and translations do not exceed maximum allowed length.`,
tags: [_irule_1.RuleTag.Naming, _irule_1.RuleTag.Syntax],
};
}
getConfig() {
return this.conf;
}
setConfig(conf) {
this.conf = conf;
}
initialize(_reg) {
return this;
}
run(obj) {
const issues = [];
const file = obj.getXMLFile();
if (file === undefined) {
return issues;
}
const xml = obj.getXML();
if (xml) {
const res = fast_xml_parser_1.XMLValidator.validate(xml);
if (res !== true) {
issues.push(issue_1.Issue.atRow(file, 1, "XML parser error: " + res.err.msg, this.getMetadata().key, this.conf.severity));
}
}
// todo, have some XML validation in each object?
if (obj instanceof Objects.Class) {
issues.push(...this.runClass(obj, file));
}
else if (obj instanceof Objects.Interface) {
issues.push(...this.runInterface(obj, file));
}
else if (obj instanceof Objects.DataElement) {
issues.push(...this.runDataElement(obj, file));
}
else if (obj instanceof Objects.Domain) {
issues.push(...this.runDomain(obj, file));
}
else if (obj instanceof Objects.Transaction) {
issues.push(...this.runTransaction(obj, file));
}
else if (obj instanceof Objects.MessageClass) {
issues.push(...this.runMessageClass(obj, file));
}
if (obj instanceof _abap_object_1.ABAPObject) {
issues.push(...this.runTextPool(obj, file));
}
return issues;
}
runClass(obj, file) {
var _a;
const issues = [];
const name = obj.getNameFromXML();
if (name === undefined) {
issues.push(issue_1.Issue.atRow(file, 1, "Name undefined in XML", this.getMetadata().key, this.conf.severity));
}
else if (obj.getDescription() && obj.getDescription().length > 60) {
issues.push(issue_1.Issue.atRow(file, 1, "Description too long", this.getMetadata().key, this.conf.severity));
}
else if (name !== obj.getName().toUpperCase()) {
issues.push(issue_1.Issue.atRow(file, 1, "Name in XML does not match object", this.getMetadata().key, this.conf.severity));
}
else if (((_a = obj.getMainABAPFile()) === null || _a === void 0 ? void 0 : _a.getStructure()) !== undefined && obj.getClassDefinition() === undefined) {
issues.push(issue_1.Issue.atRow(file, 1, "Class matching XML name not found in ABAP file", this.getMetadata().key, this.conf.severity));
}
return issues;
}
runTextPool(obj, file) {
const issues = [];
const push = (issue) => { if (issue) {
issues.push(issue);
} };
for (const [key, el] of Object.entries(obj.getTextElements())) {
push(this.checkTextLength(file, `ENTRY[${key}]`, el.entry, el.maxLength));
}
for (const translation of obj.getTextElementsTranslations()) {
for (const [key, el] of Object.entries(translation.textElements)) {
push(this.checkTextLength(file, `ENTRY[${key}]`, el.entry, el.maxLength, translation.language));
}
}
return issues;
}
runInterface(obj, file) {
var _a;
const issues = [];
const name = obj.getNameFromXML();
if (name === undefined) {
issues.push(issue_1.Issue.atRow(file, 1, "Name undefined in XML", this.getMetadata().key, this.conf.severity));
}
else if (obj.getDescription() && obj.getDescription().length > 60) {
issues.push(issue_1.Issue.atRow(file, 1, "Description too long", this.getMetadata().key, this.conf.severity));
}
else if (name !== obj.getName().toUpperCase()) {
issues.push(issue_1.Issue.atRow(file, 1, "Name in XML does not match object", this.getMetadata().key, this.conf.severity));
}
else if (obj.getDefinition() !== undefined && ((_a = obj.getDefinition()) === null || _a === void 0 ? void 0 : _a.getName().toUpperCase()) !== name.toUpperCase()) {
issues.push(issue_1.Issue.atRow(file, 1, "Interface matching XML name not found in ABAP file", this.getMetadata().key, this.conf.severity));
}
return issues;
}
checkTextLength(file, fieldName, text, maxLength, lang) {
if (text === undefined || maxLength === undefined) {
return undefined;
}
const max = typeof maxLength === "number" ? maxLength : parseInt(maxLength, 10);
if (text.length > max) {
const prefix = lang ? `[${lang}] ` : "";
return issue_1.Issue.atRow(file, 1, `${prefix}${fieldName} "${text}" exceeds maximum length of ${max} characters (actual: ${text.length})`, this.getMetadata().key, this.conf.textAndTranslationLengthSeverity);
}
return undefined;
}
runDataElement(obj, file) {
var _a;
const issues = [];
const texts = obj.getTexts();
const maxLengths = obj.getTextMaxLengths();
for (const issue of [
this.checkTextLength(file, "DDTEXT", obj.getDescription(), 60),
this.checkTextLength(file, "SCRTEXT_S", texts === null || texts === void 0 ? void 0 : texts.short, maxLengths === null || maxLengths === void 0 ? void 0 : maxLengths.short),
this.checkTextLength(file, "SCRTEXT_M", texts === null || texts === void 0 ? void 0 : texts.medium, maxLengths === null || maxLengths === void 0 ? void 0 : maxLengths.medium),
this.checkTextLength(file, "SCRTEXT_L", texts === null || texts === void 0 ? void 0 : texts.long, maxLengths === null || maxLengths === void 0 ? void 0 : maxLengths.long),
this.checkTextLength(file, "REPTEXT", texts === null || texts === void 0 ? void 0 : texts.heading, maxLengths === null || maxLengths === void 0 ? void 0 : maxLengths.heading),
]) {
if (issue) {
issues.push(issue);
}
}
for (const translation of (_a = obj.getTextsTranslations()) !== null && _a !== void 0 ? _a : []) {
const lang = translation.language;
for (const issue of [
this.checkTextLength(file, "DDTEXT", translation.description, 60, lang),
this.checkTextLength(file, "SCRTEXT_S", translation.short, maxLengths === null || maxLengths === void 0 ? void 0 : maxLengths.short, lang),
this.checkTextLength(file, "SCRTEXT_M", translation.medium, maxLengths === null || maxLengths === void 0 ? void 0 : maxLengths.medium, lang),
this.checkTextLength(file, "SCRTEXT_L", translation.long, maxLengths === null || maxLengths === void 0 ? void 0 : maxLengths.long, lang),
this.checkTextLength(file, "REPTEXT", translation.heading, maxLengths === null || maxLengths === void 0 ? void 0 : maxLengths.heading, lang),
]) {
if (issue) {
issues.push(issue);
}
}
}
return issues;
}
runDomain(obj, file) {
var _a, _b;
const maxTextLength = 60;
const issues = [];
const push = (issue) => { if (issue) {
issues.push(issue);
} };
push(this.checkTextLength(file, "DDTEXT", obj.getDescription(), maxTextLength));
for (const fixedValue of (_a = obj.getFixedValues()) !== null && _a !== void 0 ? _a : []) {
push(this.checkTextLength(file, "DDTEXT", fixedValue.description, maxTextLength, fixedValue.language));
}
for (const translationFixedValue of (_b = obj.getFixedValuesTranslations()) !== null && _b !== void 0 ? _b : []) {
push(this.checkTextLength(file, "DDTEXT", translationFixedValue.description, maxTextLength, translationFixedValue.language));
}
return issues;
}
runTransaction(obj, file) {
var _a;
const maxTextLength = 36;
const issues = [];
const push = (issue) => { if (issue) {
issues.push(issue);
} };
push(this.checkTextLength(file, "TTEXT", obj.getDescription(), maxTextLength));
for (const translation of (_a = obj.getTextsTranslations()) !== null && _a !== void 0 ? _a : []) {
push(this.checkTextLength(file, "TTEXT", translation.description, maxTextLength, translation.language));
}
return issues;
}
runMessageClass(obj, file) {
var _a;
const maxTextLength = 73;
const issues = [];
const push = (issue) => { if (issue) {
issues.push(issue);
} };
for (const msg of obj.getMessages()) {
push(this.checkTextLength(file, `TEXT[${msg.getNumber()}]`, msg.getMessage(), maxTextLength));
}
for (const translation of (_a = obj.getTextsTranslations()) !== null && _a !== void 0 ? _a : []) {
push(this.checkTextLength(file, `TEXT[${translation.number}]`, translation.text, maxTextLength, translation.language));
}
return issues;
}
}
exports.XMLConsistency = XMLConsistency;
//# sourceMappingURL=xml_consistency.js.map