All files / src macro_references.ts

92.77% Statements 77/83
75% Branches 18/24
100% Functions 8/8
92.77% Lines 77/83

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 831x 1x 1x 1x 13306x 13306x 13306x 13306x 13306x 13306x 13306x 13306x 13306x 13306x 117x 93x 117x 20x 20x 97x 97x 13306x 13306x 6x 6x 6x 6x 6x     13306x 13306x 76x 70x 70x 76x 76x 13306x 13306x 302x 302x 15x 15x 302x 302x 13306x 13306x 15x 15x 15x 15x 9x 9x 9x 9x 15x 15x 13306x 13306x 14164x 14164x 14164x 13306x 13306x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x     1x     13306x 13306x
import {IFilenameAndToken, IMacroReferences} from "./_imacro_references";
import {AbstractToken} from "./abap/1_lexer/tokens/abstract_token";
import {Position} from "./position";
 
export class MacroReferences implements IMacroReferences {
  private readonly definitions: {[filename: string]: {
    token: AbstractToken,
    start: Position,
    end: Position,
  }[]} = {};
 
  private readonly references: {[filename: string]: IFilenameAndToken[]} = {};
 
  public addDefinition(ref: IFilenameAndToken, start: Position, end: Position): void {
    if (this.definitions[ref.filename] === undefined) {
      this.definitions[ref.filename] = [];
    } else if (this.definitions[ref.filename].find((d) => d.token.getStart().equals(ref.token.getStart()))) {
      return;
    }
    this.definitions[ref.filename].push({token: ref.token, start, end});
  }
 
  public getDefinitionRange(filename: string, token: AbstractToken): {start: Position, end: Position} | undefined {
    for (const d of this.definitions[filename] || []) {
      if (d.token.getStart().equals(token.getStart())) {
        return {start: d.start, end: d.end};
      }
    }
    return undefined;
  }
 
  public addReference(ref: IFilenameAndToken): void {
    if (this.references[ref.filename] === undefined) {
      this.references[ref.filename] = [];
    }
    this.references[ref.filename].push(ref);
  }
 
  public listDefinitionsByFile(filename: string): AbstractToken[] {
    const ret: AbstractToken[] = [];
    for (const d of this.definitions[filename] || []) {
      ret.push(d.token);
    }
    return ret;
  }
 
  public listUsagesbyMacro(filename: string, token: AbstractToken): IFilenameAndToken[] {
    const ret: IFilenameAndToken[] = [];
    const tokenStr = token.getStr().toUpperCase();
 
    for (const ref of this.references[filename] || []) {
      if (ref.token.getStr().toUpperCase() === tokenStr) {
        ret.push(ref);
      }
    }
    return ret;
  }
 
  public clear(filename: string): void {
    delete this.definitions[filename];
    delete this.references[filename];
  }
 
  public findDefinitionByUsage(filename: string, token: AbstractToken): {filename: string, token: AbstractToken} | undefined {
    const tokenStr = token.getStr().toUpperCase();
 
    for (const ref of this.references[filename] || []) {
      if (ref.token.getStart().equals(token.getStart())) {
        for (const d of this.definitions[ref.filename] || []) {
          if (d.token.getStr().toUpperCase() === tokenStr) {
            return {
              filename: ref.filename,
              token: d.token,
            };
          }
        }

      }
    }
    return undefined;
  }
 
}