All files / src ddic_references.ts

97.93% Statements 95/97
93.93% Branches 31/33
100% Functions 7/7
97.93% Lines 95/97

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 971x 1x 1x 6238x 6238x 6238x 6238x 6238x 378x 378x 74x 74x 378x 6238x 6238x 371x     371x 371x 371x 371x 371x 220x 220x 371x 220x 220x 371x 371x 371x 371x 292x 191x 191x 292x 228x 228x 292x 292x 371x 6238x 6238x 2103x 2103x 98x 56x 56x 56x 56x 56x 98x 2103x 2103x 2103x 2103x 59x 59x 2103x 6238x 6238x 72x 72x 6238x 6238x 2105x 2105x 2105x 2105x 2105x 60x 2105x 2045x 2045x 2105x 6238x 6238x 98x 98x 98x 98x 98x 98x 98x 75x 75x 119x 95x 95x 119x 75x 75x 98x 98x 98x 6238x 6238x
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
        }
      }
    }
 
    const newName = obj.getName().toUpperCase();
    const newType = obj.getType();
    if (this.nameTypeIndex[newName]?.[newType]) {
      this.nameTypeIndex[newName][newType] = [];
    }
  }
 
  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;
  }
 
}