All files / src/rules check_ddic.ts

100% Statements 78/78
95.23% Branches 20/21
100% Functions 7/7
100% Lines 78/78

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 781x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 9365x 9365x 9365x 9365x 9365x 27924x 27924x 27924x 27924x 27924x 27924x 27924x 27924x 9365x 9365x 221x 221x 221x 9365x 9365x 8898x 8898x 9365x 9365x 216x 216x 9365x 9365x 280x 280x 280x 280x 280x 280x 52x 280x 228x 228x 52x 52x 52x 9365x 9365x 90x 90x 90x 2x 2x 2x 90x 17x 17x 35x 35x 88x 3x 3x 90x 90x 90x 90x 9365x 9365x
import {IRule, RuleTag} from "./_irule";
import {Issue} from "../issue";
import * as Objects from "../objects";
import {IObject} from "../objects/_iobject";
import {IRegistry} from "../_iregistry";
import {BasicRuleConfig} from "./_basic_rule_config";
import {Position} from "../position";
import {AbstractType} from "../abap/types/basic/_abstract_type";
import {UnknownType, StructureType, TableType} from "../abap/types/basic";
import {TypedIdentifier} from "../abap/types/_typed_identifier";
 
export class CheckDDICConf extends BasicRuleConfig {
// todo, add option to not allow any void types?
}
 
export class CheckDDIC implements IRule {
  private reg: IRegistry;
  private conf = new CheckDDICConf();
 
  public getMetadata() {
    return {
      key: "check_ddic",
      title: "Check DDIC",
      // eslint-disable-next-line max-len
      shortDescription: `Checks the types of DDIC objects can be resolved, the namespace of the development/errors can be configured in "errorNamespace" `,
      tags: [RuleTag.Syntax],
    };
  }
 
  public initialize(reg: IRegistry) {
    this.reg = reg;
    return this;
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: CheckDDICConf) {
    this.conf = conf;
  }
 
  public run(obj: IObject): Issue[] {
    let found: AbstractType | undefined = undefined;
    if (obj instanceof Objects.DataElement
        || obj instanceof Objects.Domain
        || obj instanceof Objects.Table
        || obj instanceof Objects.View
        || obj instanceof Objects.TableType) {
      found = obj.parseType(this.reg);
    } else {
      return [];
    }
 
    return this.check(found, obj);
  }
 
  private check(found: AbstractType | undefined, obj: IObject): Issue[] {
    const ret: Issue[] = [];
 
    if (found instanceof UnknownType) {
      const position = new Position(1, 1);
      const message = "Unknown/un-resolveable type in " + obj.getName() + ": " + found.getError();
      ret.push(Issue.atPosition(obj.getFiles()[0], position, message, this.getMetadata().key, this.conf.severity));
    } else if (found instanceof StructureType) {
// assumption: no circular types
      for (const c of found.getComponents()) {
        ret.push(...this.check(c.type instanceof TypedIdentifier ? c.type.getType() : c.type, obj));
      }
    } else if (found instanceof TableType) {
      ret.push(...this.check(found.getRowType(), obj));
    }
// todo, reference types?
 
    return ret;
  }
 
}