Question about writing a refactoring tool

I’m interested in writing a simple refactor that will find all uses of a symbol Foo and replace it with either true or false, then simplify the conditional constructs in which they appeared. For example, if I have some code:

if (!Foo)
{
// Do thing A
}
else
{
// Do thing B
}

And I run the tool to replace Foo with True, I would expect my refactor to transform the above block into:

// Do thing B

Similarly, if the code was:

if (Foo || Bar)
{
// Do thing
}

and I replace Foo with true, I would expect it to transform the code into:

if (Bar)
{
// Do thing
}

I’ve got a simple refactoring command integrated into clang-refactor, but it currently doesn’t do anything other than appear in the --help output. I’ve got a couple of questions:

  1. What is the difference between clang-tidy and clang-refactor? Conceptually I get it, clang-refactor is for “larger” stuff, but why? What about clang-refactor makes it more suitable for large refactors? I’m already a little familiar with the ASTMatcher interface, and it seems like clang-refactor doesn’t make use of it, so using clang-refactor I’m sort of at ground 0 with very few examples to go off of, whereas if I were using clang-tidy I would be able to make faster progress because I’m already a little familiar with it.

  2. What does USR mean? I see references to this acronym all over the place in the implementation of the local-rename command, but it’s not explained anywhere.

  3. Does the refactoring tooling in general contain sufficient information for me be able to accomplish the specific refactor I’m looking into? And are there any other examples of refactors people have written besides local-rename and extract?

Hi Zachary,

To get started, you can probably ignore clang-refactor. Internally it
uses the same/similar API as clang-tidy, but the later has much more
material available.

For example, I found 2015 LLVM Developers’ Meeting: D. Jasper & M. Klimek “An update on Clang-based C++ Tooling" - YouTube as a
great overview; after that, you can just use clang-query / API docs to
figure out the details. That all talks about clang-tidy.

Regards,

Miklos

+1 You can pro-actively run clang-tidy over your code base and apply the edits to get the result you want. That is, it’s not just for giving diagnostics, suggestions, etc. in an IDE setting.

As for sophistication – yes, clang-tidy and clang Tooling more generally have been used for very sophisticated edits. To get a sense, I’d recommend looking at the clang-tidy check tests. They are lit tests, so essentially each test is example code with the expected fixes: https://github.com/llvm/llvm-project/tree/main/clang-tools-extra/test/clang-tidy/checkers

A possibly-relevant example:

https://github.com/llvm/llvm-project/blob/main/clang-tools-extra/test/clang-tidy/checkers/readability-redundant-control-flow.cpp

and it’s corresponding code:

https://github.com/llvm/llvm-project/blob/main/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.h

https://github.com/llvm/llvm-project/blob/main/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp

You might also find the Clang Transformer is an easier interface to writing the refactoring. You can find that here:

https://github.com/llvm/llvm-project/tree/main/clang/include/clang/Tooling/Transformer

And it ties into clang-tidy here:
https://github.com/llvm/llvm-project/blob/main/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.h

For example,
https://github.com/llvm/llvm-project/blob/main/clang-tools-extra/clang-tidy/abseil/StringFindStrContainsCheck.h

If you find you’re interested in clang-transformer, please let me know and I can send along a tutorial which I’m working on but haven’t yet published upstream.

I am wondering is it possible for you to share the tutorials.

I have got an idea about the function makeRule from this tutorial. I am looking for some a example that helps me to understand the process to add transformer to a let’s say tool based on ASTMatcher.

Actually, the tutorial you pointed to is exactly the one I had mentioned in this earlier thread. It just took me a while to post it to the clang docs.

for integrating with an existing tool (not clang-tidy), see llvm-project/Transformer.h at 325426d72ce50c35e52ce801dcbfabc4a5a2afb3 · llvm/llvm-project · GitHub It should plug in wherever you’re currently creating a MatchFinder.