All files / src/lsp dump_scope.ts

87.1% Statements 54/62
83.33% Branches 10/12
100% Functions 4/4
87.1% Lines 54/62

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     4x 4x 4x       13x 13x   13x   13x   13x 13x   11x   2x     13x   13x 4x 4x   9x   13x   13x 9x     13x       9x 9x   9x 9x 9x         9x                 9x 9x 8x   1x     9x 1x 1x 1x 1x 1x 1x 1x 1x   1x     9x 9x 9x 9x 9x       9x         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;
    Eif (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();
      Eif (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;
  }
 
}