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 10064x 10064x 10064x 10064x 10064x 10064x 10064x 10064x 10064x 10064x 77x 60x 77x 13x 13x 64x 64x 10064x 10064x 6x 6x 6x 6x 6x     10064x 10064x 43x 37x 37x 43x 43x 10064x 10064x 276x 276x 10x 10x 276x 276x 10064x 10064x 10x 10x 10x 10x 4x 4x 4x 4x 10x 10x 10064x 10064x 10463x 10463x 10463x 10064x 10064x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x     1x     10064x 10064x
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;
  }
 
}