@abaplint/core
Version:
abaplint - Core API
115 lines • 6.07 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConstantClasses = exports.ConstantClassesConf = void 0;
const issue_1 = require("../issue");
const _basic_rule_config_1 = require("./_basic_rule_config");
const _irule_1 = require("./_irule");
const Objects = require("../objects");
const visibility_1 = require("../abap/4_file_information/visibility");
/** Checks that constants classes are in sync with domain fixed values */
class ConstantClassesConf extends _basic_rule_config_1.BasicRuleConfig {
constructor() {
super(...arguments);
/** Specify a list of domain-class pairs which will be validated */
this.mapping = [];
}
}
exports.ConstantClassesConf = ConstantClassesConf;
class ConstantClasses {
constructor() {
this.conf = new ConstantClassesConf();
}
getMetadata() {
return {
key: "constant_classes",
title: "Validate constant classes",
shortDescription: `Checks that a class contains exactly the constants corresponding to a domain's fixed values.`,
extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-enumeration-classes-to-constants-interfaces`,
tags: [_irule_1.RuleTag.Styleguide],
};
}
initialize(reg) {
this.reg = reg;
return this;
}
getConfig() {
return this.conf;
}
setConfig(conf) {
this.conf = conf;
}
run(obj) {
if (this.conf
&& this.conf.mapping
&& obj instanceof Objects.Domain) {
const configEntry = this.conf.mapping.find(x => x.domain.toUpperCase() === obj.getName().toUpperCase());
if (!configEntry) {
return [];
}
const classWithConstants = this.reg.getObject("CLAS", configEntry === null || configEntry === void 0 ? void 0 : configEntry.class.toUpperCase());
if (!classWithConstants) {
return [issue_1.Issue.atIdentifier(obj.getIdentifier(), `Constant class pattern implementation ${configEntry.class} missing for domain ${configEntry.domain}`, this.getMetadata().key, this.conf.severity)];
// quickfix will implement the whole class
}
const classContents = classWithConstants.getMainABAPFile();
if (classContents === undefined) {
return [];
}
const def = classWithConstants.getClassDefinition();
if (!def) {
// this issue is checked by rule implement_methods.
// we will not issue errors that all constants are missing until there is a class implementation
return [];
}
const domainValueInfo = obj.getFixedValues();
const domainValues = domainValueInfo.map(x => x.low);
const issues = [];
if (obj.getFixedValues().length === 0) {
// possibly this is not even a domain with fixed values
issues.push(issue_1.Issue.atStatement(classContents, classContents.getStatements()[0], `Domain ${configEntry.domain} does not contain any fixed values. Either add some values or disable this check`, this.getMetadata().key, this.conf.severity));
}
// later we will raise an issue if we did not find it
let domainNameConstantFound = false;
for (const constant of def.constants) {
if (configEntry.constantForDomainName
&& constant.name === configEntry.constantForDomainName) {
// we require the constant value to be uppercase just in case
// in the config it does not matter
if (constant.value !== configEntry.domain.toLocaleUpperCase()) {
issues.push(this.issueAtConstant(constant, `Constant value ${constant.value} must match domain name ${configEntry.domain} `));
}
domainNameConstantFound = true;
continue;
}
if (configEntry.useExactType && constant.typeName.toLowerCase() !== configEntry.domain.toLowerCase()) {
issues.push(this.issueAtConstant(constant, `Use exact type ${configEntry.domain} instead of ${constant.typeName}`));
// quickfix will change the type
}
if (constant.visibility !== visibility_1.Visibility.Public) {
issues.push(this.issueAtConstant(constant, `Constant ${constant.name} should be public`));
// quickfix will move constant
}
if (!domainValues.includes(constant.value)) {
issues.push(this.issueAtConstant(constant, `Extra constant ${constant.name} found which is not present in domain ${configEntry.domain}`));
// quickfix will remove constant
}
}
for (const d of domainValueInfo) {
if (!def.constants.find(c => c.value === d.low)) {
issues.push(issue_1.Issue.atStatement(classContents, classContents.getStatements()[0], `Missing constant for ${d.low} (domain ${configEntry.domain})`, this.getMetadata().key, this.conf.severity));
// quickfix will add constant
}
}
if (configEntry.constantForDomainName && !domainNameConstantFound) {
issues.push(issue_1.Issue.atStatement(classContents, classContents.getStatements()[0], `Missing constant ${configEntry.constantForDomainName} for name of domain ${configEntry.domain}`, this.getMetadata().key, this.conf.severity));
}
return issues;
}
return [];
}
issueAtConstant(constant, message) {
return issue_1.Issue.atIdentifier(constant.identifier, message, this.getMetadata().key, this.conf.severity);
}
}
exports.ConstantClasses = ConstantClasses;
//# sourceMappingURL=constant_classes.js.map