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 7475x 7475x 7475x 7475x 7475x 232x 232x 74x 74x 232x 7475x 7475x 528x     528x 528x 528x 528x 528x 356x 356x 528x 356x 356x 528x 528x 528x 528x 449x 314x 314x 449x 379x 379x 449x 449x 528x 7475x 7475x 2729x 2729x 86x 58x 58x 58x 58x 58x 86x 2729x 2729x 2729x 2729x 2729x 50x 50x 2729x 7475x 7475x 111x 111x 7475x 7475x 2731x 2731x 2731x 2731x 2731x 51x 2731x 2680x 2680x 2731x 7475x 7475x 123x 123x 123x 123x 123x 123x 123x 89x 89x 141x 115x 115x 141x 89x 89x 123x 123x 123x 7475x 7475x
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;
  }
 
}