All files / src/lsp _lsp_utils.ts

97.37% Statements 37/38
94.12% Branches 16/17
100% Functions 6/6
97.37% Lines 37/38

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    1x 1x 1x     1x 1x                     201x 201x 212x 206x     201x     1x     201x 201x 202x 203x 200x       1x       110x               85x             93x 93x       93x   93x 363x 363x 90x               3x       937x   937x 1801x 1227x 1227x     90x     574x 574x 200x         647x      
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);
    Iif (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;
  }
 
}