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 306x 306x 306x 1x 1x 305x 306x 306x 306x 305x 306x 305x 305x 306x         1x 1x 162x 162x 162x 162x 162x 162x 1x 1x 8x 8x 1x 1x 123x 123x 123x 123x 123x 1x 1x 137x 137x     137x 137x 137x 137x 529x 529x 134x 134x 134x 134x 134x 134x 529x 3x 3x 3x 1x 1x 1403x 1403x 1403x 2778x 1904x 1904x 1904x 1904x 134x 134x 2778x 874x 874x 304x 304x 874x 2778x 965x 965x 965x 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;
  }
 
}