All files / src ddic_references.ts

97.95% Statements 96/98
93.93% Branches 31/33
100% Functions 7/7
97.95% Lines 96/98

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 981x 1x 1x 6996x 6996x 6996x 6996x 6996x 563x 563x 103x 103x 563x 6996x 6996x 514x     514x 514x 514x 514x 514x 321x 321x 514x 321x 321x 514x 514x 514x 514x 406x 283x 283x 406x 336x 336x 406x 406x 514x 6996x 6996x 2940x 2940x 120x 58x 58x 58x 58x 58x 120x 2940x 2940x 2940x 2940x 2940x 81x 81x 2940x 6996x 6996x 103x 103x 6996x 6996x 2942x 2942x 2942x 2942x 2942x 82x 2942x 2860x 2860x 2942x 6996x 6996x 123x 123x 123x 123x 123x 123x 123x 89x 89x 141x 115x 115x 141x 89x 89x 123x 123x 123x 6996x 6996x
import {IObject} from "./objects/_iobject";
import {IDDICReferences, IObjectAndToken} from "./_iddic_references";
 
export class DDICReferences implements IDDICReferences {
  private readonly nameTypeIndex: { [name: string]: { [type: string]: IObjectAndToken[] } } = {};
  private readonly filenameIndex: { [filename: string]: { [line: number]: IObjectAndToken[] } } = {};
 
  public setUsing(obj: IObject, using: IObjectAndToken[]): void {
    this.clear(obj);
    for (const u of using) {
      this.addUsing(obj, u);
    }
  }
 
  public addUsing(obj: IObject, using: IObjectAndToken | undefined) {
    if (using === undefined) {
      return;
    }
 
    // add to name and type index
    const newName = obj.getName().toUpperCase();
    const newType = obj.getType();
    if (this.nameTypeIndex[newName] === undefined) {
      this.nameTypeIndex[newName] = {};
    }
    if (this.nameTypeIndex[newName][newType] === undefined) {
      this.nameTypeIndex[newName][newType] = [];
    }
    this.nameTypeIndex[newName][newType].push(using);
 
    // add to filename index
    if (using.filename && using.token) {
      if (this.filenameIndex[using.filename] === undefined) {
        this.filenameIndex[using.filename] = {};
      }
      if (this.filenameIndex[using.filename][using.token.getRow()] === undefined) {
        this.filenameIndex[using.filename][using.token.getRow()] = [];
      }
      this.filenameIndex[using.filename][using.token.getRow()].push(using);
    }
  }
 
  public clear(obj: IObject) {
    // remove from filenameIndex first
    for (const u of this.listUsing(obj)) {
      if (u.filename && u.token) {
        const found = this.filenameIndex[u.filename]?.[u.token.getRow()];
        if (found) {
          found.pop(); // TODODOD, this assumes there is max one reference on each line
        }
      }
    }
 
    // remove from name + type index
    const name = obj.getName().toUpperCase();
    const type = obj.getType();
    if (this.nameTypeIndex[name]?.[type]) {
      this.nameTypeIndex[name][type] = [];
    }
  }
 
  public listByFilename(filename: string, line: number): IObjectAndToken[] {
    return this.filenameIndex[filename]?.[line] || [];
  }
 
  public listUsing(obj: IObject): readonly IObjectAndToken[] {
    const newName = obj.getName().toUpperCase();
    const newType = obj.getType();
 
    const found = this.nameTypeIndex[newName]?.[newType];
    if (found !== undefined) {
      return found;
    } else {
      return [];
    }
  }
 
  public listWhereUsed(obj: IObject) {
    // todo, add reverse index, this is slow
 
    const ret = [];
    const searchName = obj.getName().toUpperCase();
    const searchType = obj.getType();
 
    for (const name in this.nameTypeIndex) {
      for (const type in this.nameTypeIndex[name]) {
        for (const f of this.nameTypeIndex[name][type]) {
          if (f.object && f.object.getType() === searchType && f.object.getName() === searchName) {
            ret.push({type, name, token: f.token, filename: f.filename});
          }
        }
      }
    }
 
    return ret;
  }
 
}