All files / src/lsp _lsp_utils.ts

95.19% Statements 99/104
82.6% Branches 19/23
100% Functions 6/6
95.19% Lines 99/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 341x 341x 341x     341x 341x 341x 341x 340x 340x 340x 340x 340x   1x 1x 1x 1x 1x 181x 181x 181x 181x 181x 181x 1x 1x 19x 19x 1x 1x 141x 141x 141x 141x 141x 1x 1x 156x 156x     156x 156x 156x 156x 607x 607x 153x 153x 153x 153x 153x 153x 607x 3x 3x 3x 1x 1x 1670x 1670x 1670x 3302x 2239x 2239x 2239x 2239x 153x 153x 3302x 1063x 1063x 365x 365x 1063x 3302x 1152x 1152x 1152x 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;
  }
 
}