All files / src/lsp _lsp_utils.ts

94.23% Statements 98/104
85.18% Branches 23/27
100% Functions 6/6
94.23% Lines 98/104

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 1041x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 319x 319x 319x 1x 1x 318x 319x 319x 319x 318x 319x 318x 318x 319x         1x 1x 164x 164x 164x 164x 164x 164x 1x 1x 8x 8x 1x 1x 124x 124x 124x 124x 124x 1x 1x 143x 143x     143x 143x 143x 143x 548x 548x 140x 140x 140x 140x 140x 140x 548x 3x 3x 3x 1x 1x 1461x 1461x 1461x 2887x 1974x 1974x 1974x 1974x 140x 140x 2887x 913x 913x 313x 313x 913x 2887x 1008x 1008x 1008x 1x 1x
import {IRegistry} from "../_iregistry";
import {AbstractToken} from "../abap/1_lexer/tokens/abstract_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: AbstractToken;
  identifier: Identifier;
  stack: INode[];
  snode: StatementNode;
}
 
export class LSPUtils {
 
  public static getABAPFile(reg: IRegistry, filename: string): ABAPFile | undefined {
 
    const file = reg.getFileByName(filename);
    if (file === undefined) {
      return undefined;
    }
    const obj = reg.findObjectForFile(file);
    obj?.parse();
 
    if (obj instanceof ABAPObject) {
      for (const abapfile of obj.getABAPFiles()) {
        if (abapfile.getFilename().toUpperCase() === filename.toUpperCase()) {
          return abapfile;
        }
      }
    }

    return undefined;
  }
 
  public static tokenToRange(token: AbstractToken): LServer.Range {
    return LServer.Range.create(
      token.getStart().getRow() - 1,
      token.getStart().getCol() - 1,
      token.getEnd().getRow() - 1,
      token.getEnd().getCol() - 1);
  }
 
  public static positionToLS(pos: Position): LServer.Position {
    return LServer.Position.create(pos.getRow() - 1, pos.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: AbstractToken, 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;
  }
 
}