All files / src/objects/rename rename_program.ts

94.8% Statements 73/77
85.71% Branches 12/14
100% Functions 2/2
94.8% Lines 73/77

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 781x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 1x 1x 2x     2x 2x 2x     2x 2x 2x 2x 2x 2x 2x 2x 2x 3x 1x 1x 1x 1x 1x 3x 2x 2x 1x 1x 2x 2x 2x 3x 1x 1x 1x 2x 2x 2x 1x 1x 1x 1x 1x 1x 2x 1x 1x 1x 1x 1x 3x 2x 2x 2x 2x 2x 1x 1x  
import * as Statements from "../../abap/2_statements/statements";
import * as Expressions from "../../abap/2_statements/expressions";
import {WorkspaceEdit, TextDocumentEdit, CreateFile, RenameFile, DeleteFile, TextEdit} from "vscode-languageserver-types";
import {IRegistry} from "../../_iregistry";
import {Program} from "..";
import {ObjectRenamer} from "./_object_renamer";
import {RenamerHelper} from "./renamer_helper";
import {IObject} from "../_iobject";
import {LSPUtils} from "../../lsp/_lsp_utils";
import {ABAPObject} from "../_abap_object";
 
export class RenameProgram implements ObjectRenamer {
  private readonly reg: IRegistry;
 
  public constructor(reg: IRegistry) {
    this.reg = reg;
  }
 
  public buildEdits(obj: IObject, oldName: string, newName: string): WorkspaceEdit | undefined {
    if (!(obj instanceof Program)) {
      throw new Error("RenameProgram, not a program");
    }
 
    const main = obj.getMainABAPFile();
    if (main === undefined) {
      throw new Error(`Main file not found, ${obj.getType()} ${obj.getName()}`);
    }
 
    let changes: (TextDocumentEdit | CreateFile | RenameFile | DeleteFile)[] = [];
    const helper = new RenamerHelper(this.reg);
 
    changes = changes.concat(helper.buildXMLFileEdits(obj, "NAME", oldName, newName));
    changes = changes.concat(helper.renameFiles(obj, oldName, newName));
 
    const edits: TextEdit[] = [];
    for (const s of main.getStatements()) {
      if (s.get() instanceof Statements.Report || s.get() instanceof Statements.Program) {
        const exp = s.findFirstExpression(Expressions.ReportName);
        if (exp) {
          edits.push(TextEdit.replace(LSPUtils.tokenToRange(exp.getFirstToken()), newName.toLowerCase()));
        }
      }
    }
 
    if (edits.length > 0) {
      changes.push(TextDocumentEdit.create({uri: main.getFilename(), version: 1}, edits));
    }
 
    // Rename INCLUDE statements in all ABAP objects
    for (const o of this.reg.getObjects()) {
      if (o instanceof ABAPObject && o !== obj) {
        for (const file of o.getABAPFiles()) {
          const includeEdits: TextEdit[] = [];
          for (const s of file.getStatements()) {
            if (s.get() instanceof Statements.Include ||
                s.get() instanceof Statements.Submit ||
                s.get() instanceof Statements.Perform) {
              for (const exp of s.findAllExpressions(Expressions.IncludeName)) {
                if (exp && exp.getFirstToken().getStr().toUpperCase() === oldName.toUpperCase()) {
                  includeEdits.push(TextEdit.replace(LSPUtils.tokenToRange(exp.getFirstToken()), newName.toLowerCase()));
                }
              }
            }
          }
          if (includeEdits.length > 0) {
            changes.push(TextDocumentEdit.create({uri: file.getFilename(), version: 1}, includeEdits));
          }
        }
      }
    }
 
    return {
      documentChanges: changes,
    };
  }
 
}