All files / src/lsp _lsp_utils.ts

94% Statements 94/100
84.61% Branches 22/26
100% Functions 5/5
94% Lines 94/100

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 1001x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 264x 264x 264x 1x 1x 263x 264x 264x 264x 263x 264x 263x 263x 264x         1x 1x 138x 138x 138x 138x 138x 138x 1x 1x 107x 107x 107x 107x 107x 1x 1x 123x 123x     123x 123x 123x 123x 489x 489x 120x 120x 120x 120x 120x 120x 489x 3x 3x 3x 1x 1x 1297x 1297x 1297x 2568x 1760x 1760x 1760x 1760x 120x 120x 2568x 808x 808x 272x 272x 808x 2568x 905x 905x 905x 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;
}
 
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: 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;
  }
 
}