How can I refactor C++ source code using emacs?

C++EmacsRefactoring

C++ Problem Overview


I'm interested mostly in C++ and method/class name/signature automatic changes.

C++ Solutions


Solution 1 - C++

In recent Emacs versions (24), Semantic is able to this.

  1. Possibly activate semantic mode M-x semantic-mode RET.
  2. Bring up the Symref buffer with C-c , g.
  3. Press C-c C-e to open all references.
  4. Rename with R.

Solution 2 - C++

If you can program in elisp, you can look to combination of cedet + srecode from CEDET libraries - it provide all instruments for this task - find callers of functions, get signature, etc. But you need to create refactory tool yourself, using these instruments

Solution 3 - C++

I do this a lot, so I'm axiously awaiting other replies too.

The only tricks I know are really basic. Here are my best friends in Emacs when refactoring code:

M-x query-replace

This allows you to do a global search and replace. You'll be doing this a ton when you move methods and commonly-accessed data to other classes or namespaces.

C-x 3

This gives you a display with two buffers side-by side. You can then proceed to load different files in them, and move your cursor from one to the other with C-x o. This is pretty basic stuff, but I mention it because of how powerful it makes the next one...

C-x (
(type any amount of stuff and/or emacs commands here)
C-x )

This is how you define a macro in emacs. Any time you find yourself needing to do the same thing over and over to a bunch of code (and it is too complex for query-replace), this is a lifesaver. If you mess up, you can hit C-g to stop the macro definition, and then undo (C-_) until you are back to where you started. The keys to invoke the macro are C-x e. If you want to do it a bunch of times, you can hit Esc and type in a number first. Eg: Esc 100 C-x e will try to invoke your macro 100 times.

(Note: On Windows you can get "Meta" by hitting the Esc key, or holding down Alt).

Solution 4 - C++

For somewhere in between refactoring tools and simple regex, since Emacs 22 you can embed arbitrary elisp expressions in your replacement text, which allows you to do incredibly powerful text manipulation. Steve Yegge wrote a http://steve-yegge.blogspot.com/2006/06/shiny-and-new-emacs-22.html">good article on this a while ago.

Solution 5 - C++

The current (2022) state of the art is, I would say, using emacs lsp-mode with a suitable language server.

With the clangd or ccls, which provide the "language server protocol" (lsp) and connect to lsp-mode, you can refactor names with:

M-x lsp-rename

To simplify this setup, I'd recommend using Spacemacs with c-c++ and lsp layers (and using clangd).

Solution 6 - C++

A friend of mine was playing with xrefactory and said it worked pretty well. It isn't cheap though.

Solution 7 - C++

Build cscope symbols.

lookup the symbol you want to refactor.

get into the cscope window, and start a macro after placing cursor on first occurence

  • ret
  • c-f your symbol start
  • navigate to start of your symbol
  • modify the word
  • c-x o (back to cscope)
  • n (for next cscope symbol)

you have to just c-x c-e now

Solution 8 - C++

I totally agree that find-and-replace work fine. However , a really nice feature of cedet is 'semantic-symref-list'.

With the cursor on a method, run this command, and you will be presented with a buffer that lists all of the places in your code that reference this tag.

You can still use find-and-replace tricks, and this will confirm that you have changed all the references.

Solution 9 - C++

I've been using cquery for my C++ completion which uses Microsoft LSP for IDE <-> Tool communication. cquery server satisfies the requests of the LSP protocol using a clang backend.

lsp-emacs is the package that sits between emacs and the cquery backend (cquery-emacs) which exposes an lsp-rename function. As a completion system, cquery has been very reliable and fast by the way, highly recommended.

Give it a try, follow the getting-started guide on the cquery github: https://github.com/cquery-project/cquery/wiki/Emacs

Once you've got cquery setup:

  1. Hover your cursor over an identifier (class, var, whatever) you'd like to rename.
  2. M-x lsp-rename
  3. Enter the new name for the identifier.
  4. Do C-x s (save some buffers), which will prompt you to save all the buffers that were touched by the refactor.

You should probably go through all modified buffers and check what was done after refactoring with any tool/language.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionŁukasz LewView Question on Stackoverflow
Solution 1 - C++muedeView Answer on Stackoverflow
Solution 2 - C++Alex OttView Answer on Stackoverflow
Solution 3 - C++T.E.D.View Answer on Stackoverflow
Solution 4 - C++jamesnvcView Answer on Stackoverflow
Solution 5 - C++TheJJView Answer on Stackoverflow
Solution 6 - C++Greg RogersView Answer on Stackoverflow
Solution 7 - C++VijayenderView Answer on Stackoverflow
Solution 8 - C++user7957View Answer on Stackoverflow
Solution 9 - C++nenchevView Answer on Stackoverflow