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 8981x 8981x 8981x 8981x 8981x 8981x 8981x 8981x 8981x 8981x 61x 53x 61x 5x 5x 56x 56x 8981x 8981x 2x 2x 2x 2x 2x     8981x 8981x 39x 35x 35x 39x 39x 8981x 8981x 260x 260x 6x 6x 260x 260x 8981x 8981x 6x 6x 6x 6x 4x 4x 4x 4x 6x 6x 8981x 8981x 9385x 9385x 9385x 8981x 8981x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x     1x     8981x 8981x
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;
  }
 
}