All files / src/objects _abstract_object.ts

95.86% Statements 139/145
92.1% Branches 35/38
100% Functions 15/15
95.86% Lines 139/145

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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 1451x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 8537x 8537x 8537x 8537x 8537x 1x 1x 334x 334x 1x 1x 297x 297x 1x 1x 49167x 49167x 1x 1x 10078x 10078x 10078x 1x 1x 8535x 8535x 8535x 8535x 297x 1x 1x 1x 297x 8534x 8534x 8534x 1x 1x 29901x 29901x 1x 1x 215x 222x 210x 210x 222x 5x 5x 1x 1x 45x 45x 45x 45x 45x 45x 45x     1x 1x 17525x 17525x 1x 1x 106x 106x 106x     106x 106x 1x 1x 7616x 7616x 7616x 7616x 7865x 1079x 1079x 7865x 6537x 7616x 6563x 3x 3x 6563x 6534x 6534x 1x 1x 3683x 3683x 655x 655x 3028x 3028x 1x 1x 523x 523x 530x 522x 522x 522x 530x 1x 1x 1x 1x 3433x 3433x 2927x 2927x 506x 506x 3433x     3433x 1x 1x
import {IFile} from "../files/_ifile";
import {IAllowedNaming, IObject, IParseResult} from "./_iobject";
import {XMLParser} from "fast-xml-parser";
import {Issue} from "../issue";
import {Version} from "../version";
import {Identifier} from "../abap/4_file_information/_identifier";
import {Identifier as IdentifierToken} from "../abap/1_lexer/tokens/identifier";
import {Position} from "../position";
import {IRegistry} from "../_iregistry";
 
export abstract class AbstractObject implements IObject {
  protected old: readonly Issue[];
  protected dirty: boolean;
  private files: IFile[];
  private readonly name: string;
 
  public abstract getType(): string;
  public abstract getAllowedNaming(): IAllowedNaming;
  public abstract getDescription(): string | undefined;
 
  public constructor(name: string) {
    this.name = name;
    this.files = [];
    this.old = [];
    this.dirty = false;
  }
 
  public getParsingIssues() {
    return this.old;
  }
 
  public parse(_version?: Version, _globalMacros?: readonly string[], _reg?: IRegistry): IParseResult {
    return {updated: false, runtime: 0};
  }
 
  public getName(): string {
    return this.name;
  }
 
  public setDirty(): void {
    this.old = [];
    this.dirty = true;
  }
 
  public addFile(file: IFile) {
    this.setDirty();
 
    // update if it already exists
    for (let i = 0; i < this.files.length; i++) {
      if (this.files[i].getFilename() === file.getFilename()) {
        this.files[i] = file;
        return;
      }
    }
 
    this.files.push(file);
  }
 
  public getFiles(): readonly IFile[] {
    return this.files;
  }
 
  public containsFile(filename: string): boolean {
    for (const f of this.files) {
      if (f.getFilename() === filename) {
        return true;
      }
    }
    return false;
  }
 
  public removeFile(file: IFile): void {
    this.setDirty();
    for (let i = 0; i < this.files.length; i++) {
      if (this.files[i].getFilename() === file.getFilename()) {
        this.files.splice(i, 1);
        return;
      }
    }
    throw new Error("removeFile: file not found");
  }
 
  public isDirty() {
    return this.dirty;
  }
 
  public getIdentifier(): Identifier | undefined {
    // this method can be redefined in each object type to give a better result
    const file = this.getXMLFile();
    if (file === undefined) {
      return undefined;
    }
    return new Identifier(new IdentifierToken(new Position(1, 1), this.getName()), file.getFilename());
  }
 
  public getXMLFile() {
// todo, https://github.com/abaplint/abaplint/issues/673 uris
    const expected1 = this.getName().toLowerCase().replace(/\//g, "#") + "." + this.getType().toLowerCase() + ".xml";
    const expected2 = this.getName().toLowerCase().replace(/\//g, "%23") + "." + this.getType().toLowerCase() + ".xml";
    for (const file of this.getFiles()) {
      if (file.getFilename().endsWith(expected1) || file.getFilename().endsWith(expected2)) {
        return file;
      }
    }
    // uri fallback, assume there is only one xml file
    for (const file of this.getFiles()) {
      if (file.getFilename().endsWith(".xml")) {
        return file;
      }
    }
    return undefined;
  }
 
  public getXML(): string | undefined {
    const file = this.getXMLFile();
    if (file) {
      return file.getRaw();
    }
    return undefined;
  }
 
  public updateFile(file: IFile) {
    this.setDirty();
    for (let i = 0; i < this.files.length; i++) {
      if (this.files[i].getFilename() === file.getFilename()) {
        this.files[i] = file;
        return;
      }
    }
    throw new Error("updateFile: file not found");
  }
 
  protected parseRaw2(): any | undefined {
    const xml = this.getXML();
    if (xml === undefined) {
      return undefined;
    }
    try {
      return new XMLParser({parseTagValue: false, ignoreAttributes: true, trimValues: false}).parse(xml);
    } catch {
      return undefined;
    }
  }
 
}