All files / src/lsp _lsp_utils.ts

98.03% Statements 100/102
96% Branches 24/25
100% Functions 6/6
98.03% Lines 100/102

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 1021x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 235x 235x 235x 248x 240x 240x 248x 235x 235x 1x 1x 1x 1x 235x 235x 236x 237x 234x 234x 237x 2x 1x 1x 1x 1x 124x 124x 124x 124x 124x 124x 1x 1x 95x 95x 95x 95x 95x 1x 1x 109x 109x     109x 109x 109x 109x 419x 419x 106x 106x 106x 106x 106x 106x 419x 3x 3x 3x 1x 1x 1143x 1143x 1143x 2225x 1501x 1501x 1501x 1501x 106x 106x 2225x 724x 724x 248x 248x 724x 2225x 789x 789x 789x 1x 1x
import {IRegistry} from "../_iregistry";
import {Token} from "../abap/1_lexer/tokens/_token";
import {StatementNode, TokenNode} from "../abap/nodes";
import {Identifier} from "../abap/4_file_information/_identifier";
import {ABAPObject} from "../objects/_abap_object";
import {ITextDocumentPositionParams} from "./_interfaces";
import {INode} from "../abap/nodes/_inode";
import {Position} from "../position";
import * as LServer from "vscode-languageserver-types";
import {ABAPFile} from "../abap/abap_file";
 
export interface ICursorData {
  token: Token;
  identifier: Identifier;
  stack: INode[];
  snode: StatementNode;
}
 
function getABAPObjects(reg: IRegistry): ABAPObject[] {
  const ret: ABAPObject[] = [];
  for (const o of reg.getObjects()) {
    if (o instanceof ABAPObject) {
      ret.push(o);
    }
  }
  return ret;
}
 
export class LSPUtils {
 
  public static getABAPFile(reg: IRegistry, name: string): ABAPFile | undefined {
    const obj = getABAPObjects(reg);
    for (const o of obj) {
      for (const file of o.getABAPFiles()) {
        if (file.getFilename().toUpperCase() === name.toUpperCase()) {
          return file;
        }
      }
    }
    return undefined;
  }
 
  public static tokenToRange(token: Token): LServer.Range {
    return LServer.Range.create(
      token.getStart().getRow() - 1,
      token.getStart().getCol() - 1,
      token.getEnd().getRow() - 1,
      token.getEnd().getCol() - 1);
  }
 
  public static identiferToLocation(identifier: Identifier): LServer.Location {
    return {
      uri: identifier.getFilename(),
      range: LSPUtils.tokenToRange(identifier.getToken()),
    };
  }
 
  public static findCursor(reg: IRegistry, pos: ITextDocumentPositionParams): ICursorData | undefined {
    const file = LSPUtils.getABAPFile(reg, pos.textDocument.uri);
    if (file === undefined) {
      return undefined;
    }
 
    const search = new Position(pos.position.line + 1, pos.position.character + 1);
 
    for (const statement of file.getStatements()) {
      const res = this.buildStack(statement, search, [statement]);
      if (res !== undefined) {
        return {
          token: res.token,
          identifier: new Identifier(res.token, file.getFilename()),
          stack: res.stack,
          snode: statement};
      }
    }
 
    return undefined;
  }
 
  private static buildStack(node: INode, search: Position, parents: INode[]): {token: Token, stack: INode[]} | undefined {
    const stack: INode[] = parents;
 
    for (const c of node.getChildren()) {
      if (c instanceof TokenNode) {
        const token = c.getFirstToken();
        if (token.getRow() === search.getRow()
            && token.getCol() <= search.getCol()
            && token.getCol() + token.getStr().length > search.getCol()) {
          return {token, stack};
        }
      } else {
        const res = this.buildStack(c, search, stack.concat([c]));
        if (res !== undefined) {
          return res;
        }
      }
    }
 
    return undefined;
  }
 
}