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 7436x 7436x 7436x 7436x 7436x 232x 232x 74x 74x 232x 7436x 7436x 526x     526x 526x 526x 526x 526x 355x 355x 526x 355x 355x 526x 526x 526x 526x 447x 313x 313x 447x 377x 377x 447x 447x 526x 7436x 7436x 2711x 2711x 86x 58x 58x 58x 58x 58x 86x 2711x 2711x 2711x 2711x 2711x 50x 50x 2711x 7436x 7436x 111x 111x 7436x 7436x 2713x 2713x 2713x 2713x 2713x 51x 2713x 2662x 2662x 2713x 7436x 7436x 123x 123x 123x 123x 123x 123x 123x 89x 89x 141x 115x 115x 141x 89x 89x 123x 123x 123x 7436x 7436x
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;
  }
 
}