All files / src/rules global_class.ts

93.2% Statements 96/103
94.28% Branches 33/35
100% Functions 5/5
93.2% Lines 96/103

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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 1031x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 11598x 11598x 11598x 11598x 34642x 34642x 34642x 34642x 34642x 34642x 34642x 34642x 34642x 34642x 34642x 34642x 34642x 34642x 34642x 34642x 34642x 34642x 11598x 11598x 11055x 11055x 11598x 11598x 252x 252x 11598x 11598x 279x 279x 279x 135x 2x 2x 2x 135x 135x 2x 2x 2x 135x 135x       135x 135x 51x 2x 2x 2x 51x         51x 135x 279x 279x 133x 133x 133x 2x 2x 2x 133x 279x 279x 60x 60x 60x 1x 1x 1x 60x 279x 279x 60x 2x 2x 2x 60x 279x 279x 279x 11598x
import {Issue} from "../issue";
import {ABAPRule} from "./_abap_rule";
import {IObject} from "../objects/_iobject";
import * as Objects from "../objects";
import {BasicRuleConfig} from "./_basic_rule_config";
import {IRuleMetadata, RuleTag} from "./_irule";
import {ABAPFile} from "../abap/abap_file";
import {ClassCategory} from "../objects";
 
export class GlobalClassConf extends BasicRuleConfig {
}
 
export class GlobalClass extends ABAPRule {
  private conf = new GlobalClassConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "global_class",
      title: "Global class checks",
      shortDescription: `Checks related to global classes`,
      extendedInformation: `* global classes must be in own files
 
* file names must match class name
 
* file names must match interface name
 
* global classes must be global definitions
 
* global interfaces must be global definitions
 
* global FOR TESTING, must have CATEGORY = 05 in the XML`,
      tags: [RuleTag.Syntax],
    };
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: GlobalClassConf) {
    this.conf = conf;
  }
 
  public runParsed(file: ABAPFile, obj: IObject) {
    const output: Issue[] = [];
 
    for (const definition of file.getInfo().listClassDefinitions()) {
      if (definition.isLocal && obj instanceof Objects.Class && file.getFilename().match(/\.clas\.abap$/)) {
        const issue = Issue.atIdentifier(definition.identifier, "Global classes must be global", this.getMetadata().key, this.conf.severity);
        output.push(issue);
      }
 
      if (definition.isGlobal && obj instanceof Objects.Class && definition.name.toUpperCase() !== obj.getName().toUpperCase()) {
        const issue = Issue.atIdentifier(definition.identifier, "Class definition name must match filename", this.getMetadata().key, this.conf.severity);
        output.push(issue);
      }
 
      if (definition.isGlobal && !(obj instanceof Objects.Class)) {
        const issue = Issue.atIdentifier(definition.identifier, "Class must be local", this.getMetadata().key, this.conf.severity);
        output.push(issue);
      }
 
      if (definition.isGlobal && obj instanceof Objects.Class) {
        if (definition.isForTesting === true && obj instanceof Objects.Class && obj.getCategory() !== ClassCategory.Test) {
          const message = "Class is marked as FOR TESTING, but CATEGORY is not 05 in the XML";
          const issue = Issue.atIdentifier(definition.identifier, message, this.getMetadata().key, this.conf.severity);
          output.push(issue);
        } else if (definition.isForTesting === false && obj instanceof Objects.Class && obj.getCategory() === ClassCategory.Test) {
          const message = "Class has CATEGORY 05 in the XML, but is not marked as FOR TESTING";
          const issue = Issue.atIdentifier(definition.identifier, message, this.getMetadata().key, this.conf.severity);
          output.push(issue);
        }
      }
    }
 
    for (const impl of file.getInfo().listClassImplementations()) {
      if (file.getFilename().match(/\.clas\.abap$/)
          && obj instanceof Objects.Class
          && impl.identifier.getName().toUpperCase() !== obj.getName().toUpperCase()) {
        const issue = Issue.atIdentifier(impl.identifier, "Class implementation name must match filename", this.getMetadata().key, this.conf.severity);
        output.push(issue);
      }
    }
 
    for (const impl of file.getInfo().listInterfaceDefinitions()) {
      if (file.getFilename().match(/\.intf\.abap$/)
          && obj instanceof Objects.Interface
          && impl.identifier.getName().toUpperCase() !== obj.getName().toUpperCase()) {
        const issue = Issue.atIdentifier(impl.identifier, "Interface implementation name must match filename", this.getMetadata().key, this.conf.severity);
        output.push(issue);
      }
    }
 
    for (const intf of file.getInfo().listInterfaceDefinitions()) {
      if (intf.isLocal && obj instanceof Objects.Interface && file.getFilename().match(/\.intf\.abap$/)) {
        const issue = Issue.atIdentifier(intf.identifier, "Global interface must be global", this.getMetadata().key, this.conf.severity);
        output.push(issue);
      }
    }
 
    return output;
  }
}