All files / src/rules check_ddic.ts

100% Statements 81/81
95.83% Branches 23/24
100% Functions 7/7
100% Lines 81/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 1x 1x 1x 1x 11109x 11109x 11109x 11109x 11109x 43762x 43762x 43762x 43762x 43762x 43762x 43762x 43762x 11109x 11109x 252x 252x 252x 11109x 11109x 10583x 10583x 11109x 11109x 244x 244x 11109x 11109x 335x 335x 335x 335x 335x 335x 335x 335x 335x 70x 335x 265x 265x 70x 70x 70x 11109x 11109x 152x 152x 152x 14x 14x 14x 152x 25x 25x 76x 76x 138x 6x 6x 152x 152x 152x 152x 11109x 11109x
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.AuthorizationCheckField
        || obj instanceof Objects.LockObject
        || obj instanceof Objects.MaintenanceAndTransportObject
        || 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;
  }
 
}