All files / src/objects view.ts

81.55% Statements 84/103
68.18% Branches 15/22
83.33% Functions 5/6
81.55% Lines 84/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 103 1041x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 9x 9x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 1x 1x 3x 2x 2x 3x     3x 3x 3x 3x 3x 8x       8x 8x     8x 8x     8x               8x 8x 8x 8x 3x 3x 3x 1x 1x 2x 2x 2x 1x 1x       1x 1x 1x 1x 2x 2x 2x 2x 1x 1x 1x 2x 2x 4x 4x 4x 4x 4x 4x 1x 1x 1x  
import * as Types from "../abap/types/basic";
import {AbstractObject} from "./_abstract_object";
import {xmlToArray} from "../xml_utils";
import {IRegistry} from "../_iregistry";
import {DDIC} from "../ddic";
import {TypedIdentifier} from "../abap/types/_typed_identifier";
import {AbstractType} from "../abap/types/basic/_abstract_type";
import {IObject} from "./_iobject";
 
export class View extends AbstractObject {
  private parsedData: {
    fields: {
      VIEWFIELD: string,
      TABNAME: string,
      FIELDNAME: string}[]} | undefined;
 
  public getType(): string {
    return "VIEW";
  }
 
  public getAllowedNaming() {
    return {
      maxLength: 30,
      allowNamespace: true,
    };
  }
 
  public setDirty(): void {
    this.parsedData = undefined;
    super.setDirty();
  }
 
  public parseType(reg: IRegistry): AbstractType {
    if (this.parsedData === undefined) {
      this.parseXML();
    }
    if (this.parsedData === undefined) {
      return new Types.UnknownType("View, parser error", this.getName());
    }
 
    const components: Types.IStructureComponent[] = [];
    const references: IObject[] = [];
    const ddic = new DDIC(reg);
    for (const field of this.parsedData.fields) {
      if (field.VIEWFIELD === "*") {
        // ignore, this is a special case of old style .INCLUDE
        continue;
      }
      const lookup = ddic.lookupTableOrView(field.TABNAME);
      if (lookup.object) {
        references.push(lookup.object);
      }
      let found = lookup.type;
      if (found instanceof TypedIdentifier) {
        found = found.getType();
      }
      if (found instanceof Types.StructureType) {
        const s = found.getComponentByName(field.FIELDNAME);
        if (s === undefined) {
          found = new Types.UnknownType(field.FIELDNAME + " not found in " + field.TABNAME + ", VIEW parse type");
        } else {
          found = s;
        }
      }
      components.push({
        name: field.VIEWFIELD,
        type: found});
    }
 
    reg.getDDICReferences().setUsing(this, references);
    if (components.length === 0) {
      return new Types.UnknownType("View " + this.getName() + " does not contain any components");
    }
 
    return new Types.StructureType(components, this.getName());
  }
 
  public getDescription(): string | undefined {
    // todo
    return undefined;
  }
 
///////////////
 
  private parseXML() {
    this.parsedData = {fields: []};
 
    const parsed = super.parseRaw2();
    if (parsed === undefined || parsed.abapGit === undefined) {
      return;
    }
 
    const fields = parsed.abapGit["asx:abap"]["asx:values"]?.DD27P_TABLE;
    for (const field of xmlToArray(fields?.DD27P)) {
      this.parsedData.fields.push({
        VIEWFIELD: field.VIEWFIELD,
        TABNAME: field.TABNAME,
        FIELDNAME: field.FIELDNAME,
      });
    }
  }
 
}