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 9904x 9904x 9904x 9904x 9904x 288x 288x 75x 75x 288x 9904x 9904x 656x     656x 656x 656x 656x 656x 440x 440x 656x 440x 440x 656x 656x 656x 656x 576x 397x 397x 576x 500x 500x 576x 576x 656x 9904x 9904x 3269x 3269x 88x 62x 62x 62x 62x 62x 88x 3269x 3269x 3269x 3269x 3269x 49x 49x 3269x 9904x 9904x 127x 127x 9904x 9904x 3273x 3273x 3273x 3273x 3273x 52x 3273x 3221x 3221x 3273x 9904x 9904x 134x 134x 134x 134x 134x 134x 134x 100x 100x 152x 126x 126x 152x 100x 100x 134x 134x 134x 9904x 9904x
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;
  }
 
}