All files / src/rules xml_consistency.ts

95.06% Statements 77/81
77.77% Branches 21/27
100% Functions 6/6
95.06% Lines 77/81

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 811x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 11517x 11517x 11517x 11517x 11517x 23370x 23370x 23370x 23370x 23370x 23370x 23370x 11517x 11517x 11006x 11006x 11517x 11517x 235x 235x 11517x 11517x 246x 246x 11517x 11517x 316x 316x 316x 316x 230x 230x 86x 86x 86x 86x 86x 9x 9x 86x 86x 86x 316x 10x 10x   10x 1x 10x 1x 9x 1x 1x 316x 5x 5x   5x   5x   5x 1x 1x 5x 86x 86x 86x 11517x 11517x
import {Issue} from "../issue";
import {IRule, IRuleMetadata, RuleTag} from "./_irule";
import {IObject} from "../objects/_iobject";
import * as Objects from "../objects";
import {IRegistry} from "../_iregistry";
import {BasicRuleConfig} from "./_basic_rule_config";
import {XMLValidator} from "fast-xml-parser";
 
export class XMLConsistencyConf extends BasicRuleConfig {
}
 
export class XMLConsistency implements IRule {
 
  private conf = new XMLConsistencyConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "xml_consistency",
      title: "XML consistency",
      shortDescription: `Checks the consistency of main XML files, eg. naming for CLAS and INTF objects`,
      tags: [RuleTag.Naming, RuleTag.Syntax],
    };
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: XMLConsistencyConf) {
    this.conf = conf;
  }
 
  public initialize(_reg: IRegistry) {
    return this;
  }
 
  public run(obj: IObject): Issue[] {
    const issues: Issue[] = [];
 
    const file = obj.getXMLFile();
    if (file === undefined) {
      return issues;
    }
 
    const xml = obj.getXML();
    if (xml) {
      const res = XMLValidator.validate(xml);
      if (res !== true) {
        issues.push(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) {
      const name = obj.getNameFromXML();
      if (name === undefined) {
        issues.push(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.atRow(file, 1, "Description too long", this.getMetadata().key, this.conf.severity));
      } else if (name !== obj.getName().toUpperCase()) {
        issues.push(Issue.atRow(file, 1, "Name in XML does not match object", this.getMetadata().key, this.conf.severity));
      } else if (obj.getMainABAPFile()?.getStructure() !== undefined && obj.getClassDefinition() === undefined) {
        issues.push(Issue.atRow(file, 1, "Class matching XML name not found in ABAP file", this.getMetadata().key, this.conf.severity));
      }
    } else if (obj instanceof Objects.Interface) {
      const name = obj.getNameFromXML();
      if (name === undefined) {
        issues.push(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.atRow(file, 1, "Description too long", this.getMetadata().key, this.conf.severity));
      } else if (name !== obj.getName().toUpperCase()) {
        issues.push(Issue.atRow(file, 1, "Name in XML does not match object", this.getMetadata().key, this.conf.severity));
      } else if (obj.getDefinition() !== undefined && obj.getDefinition()?.getName().toUpperCase() !== name.toUpperCase()) {
        issues.push(Issue.atRow(file, 1, "Interface matching XML name not found in ABAP file", this.getMetadata().key, this.conf.severity));
      }
    }
 
    return issues;
  }
 
}