All files / src/lsp dump_scope.ts

89.62% Statements 95/106
81.25% Branches 13/16
100% Functions 4/4
89.62% Lines 95/106

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 98 99 100 101 102 103 104 105 1061x 1x 1x 1x 1x 1x 4x 4x 4x 4x 1x 1x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 11x 13x 2x 2x 13x 13x 13x 13x 4x 4x 13x 9x 9x 13x 13x 13x 9x 9x 13x 13x 13x 1x 1x 9x 9x 9x 9x 9x 9x 9x     9x 9x               9x 9x 9x 8x 9x 1x 1x 9x 9x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 9x 9x 9x 9x 9x 9x     9x 9x 9x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x
import {ScopeType} from "../abap/5_syntax/_scope_type";
import {ISpaghettiScope, ISpaghettiScopeNode} from "../abap/5_syntax/_spaghetti_scope";
 
export class DumpScope {
 
  public static dump(spaghetti: ISpaghettiScope): string {
    let ret = "<hr>Spaghetti Scope:<br><br>\n";
    ret = ret + this.traverseSpaghetti(spaghetti.getTop(), 0);
    return ret;
  }
 
  private static traverseSpaghetti(node: ISpaghettiScopeNode, indent: number): string {
    const identifier = node.getIdentifier();
    const coverage = node.calcCoverage();
 
    const sident = "&nbsp".repeat(indent * 2);
 
    let ret: string = sident + "<u>" + identifier.stype + ", <tt>" + identifier.sname + "</tt>";
 
    ret += ", (" + coverage.start.getRow() + ", " + coverage.start.getCol() + ")";
    if (coverage.end.getRow() === Number.MAX_SAFE_INTEGER
        && coverage.end.getCol() === Number.MAX_SAFE_INTEGER) {
      ret += ", (max, max)";
    } else {
      ret += ", (" + coverage.end.getRow() + ", " + coverage.end.getCol() + ")";
    }
 
    ret += "</u><br>";
 
    if (node.getIdentifier().stype === ScopeType.BuiltIn) {
      ret += sident + node.getData().types.length + " type definitions<br>";
      ret += sident + node.getData().vars.length + " data definitions<br>";
    } else {
      ret = ret + this.dumpNode(node, indent);
    }
    ret = ret + "<br>";
 
    for (const c of node.getChildren()) {
      ret = ret + this.traverseSpaghetti(c, indent + 1);
    }
 
    return ret;
  }
 
  private static dumpNode(node: ISpaghettiScopeNode, indent: number): string {
    let ret = "";
    const sident = "&nbsp;".repeat(indent * 2);
 
    const types = node.getData().types;
    if (Object.keys(types).length === 0) {
      ret = ret + sident + "0 type definitions<br>";
    } else {
      ret = ret + sident + "Types:<br>";
    }
 
    for (const name in types) {
      const identifier = types[name];
      ret = ret + sident + "<tt>" + this.escape(name) + "</tt>";
      const pos = identifier.getStart();
      ret = ret + "(" + pos.getRow().toString() + ", " + pos.getCol().toString() + ") ";
      ret = ret + identifier.getType().toText(0);
      ret = ret + "<br>";
    }
 
    const vars = node.getData().vars;
    if (Object.keys(vars).length === 0) {
      ret = ret + sident + "0 data definitions<br>";
    } else {
      ret = ret + sident + "Data:<br>";
    }
 
    for (const name in vars) {
      const identifier = vars[name];
      ret = ret + sident + "<tt>" + this.escape(name.toLowerCase()) + "</tt>";
      const pos = identifier.getStart();
      ret = ret + "(" + pos.getRow().toString() + ", " + pos.getCol().toString() + ") ";
      ret = ret + identifier.getType().toText(0);
      const meta = identifier.getMeta();
      if (meta) {
        ret = ret + ", " + meta;
      }
      ret = ret + "<br>";
    }
 
    ret += sident + node.getData().cdefs.length + " class definitions<br>";
    ret += sident + node.getData().idefs.length + " interface definitions<br>";
    ret += sident + node.getData().forms.length + " form definitions<br>";
    ret += sident + node.getData().references.length + " references<br>";
    for (const r of node.getData().references) {
      ret += sident + "&nbsp;&nbsp;" + r.referenceType + ", line " + r.position.getStart().getRow() + " " + this.escape(r.position.getFilename()) + " " + this.escape(r.position.getName()) + "<br>";
    }
 
    return ret;
  }
 
// todo, refactor, this method exists in multiple classes
  private static escape(str: string) {
    str = str.replace(/&/g, "&amp;");
    str = str.replace(/>/g, "&gt;");
    str = str.replace(/</g, "&lt;");
    str = str.replace(/"/g, "&quot;");
    str = str.replace(/'/g, "&#039;");
    return str;
  }
 
}