All files / src/lsp rename.ts

89.36% Statements 42/47
80.56% Branches 29/36
100% Functions 5/5
89.36% Lines 42/47

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 931x   1x   1x 1x 1x 1x 1x   1x     1x 1x 1x 1x                   1x       7x       8x 8x     8x 8x       8x 8x 2x     6x 6x 6x 1x 5x 4x 1x       1x       5x 5x 1x     4x   3x       1x                 1x 1x 1x 2x 2x 2x   1x      
import * as LServer from "vscode-languageserver-types";
import {ITextDocumentPositionParams, IRenameParams} from "./_interfaces";
import {LSPUtils} from "./_lsp_utils";
import {IRegistry} from "../_iregistry";
import {ABAPObject} from "../objects/_abap_object";
import {LSPLookup} from "./_lookup";
import {TypedIdentifier} from "../abap/types/_typed_identifier";
import {ClassDefinition, InterfaceDefinition} from "../abap/types";
import {References} from "./references";
import {IFile} from "../files/_ifile";
import {Renamer} from "../objects/rename/renamer";
 
 
export enum RenameType {
  GlobalClass = 1,
  Variable = 2,
  GlobalInterface = 3,
}
 
export interface IPrepareResult {
  range: LServer.Range,
  placeholder: string,
  type: RenameType,
  file: IFile,
}
 
export class Rename {
  private readonly reg: IRegistry;
 
  public constructor(reg: IRegistry) {
    this.reg = reg;
  }
 
  public prepareRename(params: ITextDocumentPositionParams): IPrepareResult | undefined {
    const file = LSPUtils.getABAPFile(this.reg, params.textDocument.uri);
    Iif (file === undefined) {
      return undefined;
    }
    const obj = this.reg.getObject(file.getObjectType(), file.getObjectName());
    Iif (!(obj instanceof ABAPObject)) {
      return undefined;
    }
 
    const cursor = LSPUtils.findCursor(this.reg, params);
    if (cursor === undefined) {
      return undefined;
    }
 
    const range = LSPUtils.tokenToRange(cursor.token);
    const lookup = LSPLookup.lookup(cursor, this.reg, obj);
    if (lookup?.definitionId instanceof TypedIdentifier) {
      return {range, placeholder: cursor.token.getStr(), type: RenameType.Variable, file};
    } else if (lookup?.definitionId instanceof ClassDefinition) {
      return {range, placeholder: cursor.token.getStr(), type: RenameType.GlobalClass, file};
    } else Iif (lookup?.definitionId instanceof InterfaceDefinition) {
      return {range, placeholder: cursor.token.getStr(), type: RenameType.GlobalInterface, file};
    }
 
    return undefined;
  }
 
  public rename(params: IRenameParams): LServer.WorkspaceEdit | undefined {
    const prepare = this.prepareRename(params);
    if (prepare === undefined) {
      return undefined;
    }
 
    switch (prepare.type) {
      case RenameType.GlobalClass:
        return new Renamer(this.reg).buildEdits("CLAS", prepare.placeholder, params.newName);
      case RenameType.GlobalInterface:
        return new Renamer(this.reg).buildEdits("INTF", prepare.placeholder, params.newName);
      case RenameType.Variable:
        return this.renameVariable(params);
      default:
        return undefined;
    }
  }
 
////
 
  private renameVariable(params: IRenameParams): LServer.WorkspaceEdit | undefined {
    const workspace: LServer.WorkspaceEdit = {documentChanges: []};
    const refs = new References(this.reg).references(params);
    for (const r of refs) {
      const doc: LServer.VersionedTextDocumentIdentifier = {uri: r.uri, version: 1};
      const edit = LServer.TextDocumentEdit.create(doc, [LServer.TextEdit.replace(r.range, params.newName)]);
      workspace.documentChanges?.push(edit);
    }
    return workspace;
  }
 
}