castre/README.md
2023-08-27 11:43:52 +09:00

2.2 KiB

castre

This is a python library for C++ AST-based REfactoring

  • easy
  • simple
  • minimal
  • changes only where to refactor

How to Use

  1. install this package
  2. write a script to refactor like an example below
  3. execute the script
  4. execute your formatter
  5. verify and approve the changes by git add -p
  6. save the approved changes by git commit -m ...
  7. discard the unapproved changes by git restore .

Example

refactoring script:

import castre
import re

def walker(item):
  # The actual AST json data is stored at `item.raw`
  # You can see it by `clang++ -Xclang -ast-dump=json -c [filename and options...]`
  # And you can also see an AST structure in human-readable form by -ast-dump option without any value
  # Please note that outputs of both commands are huge
  if item.raw["kind"] == "DeclStmt" and item.raw["inner"][0]["kind"] == "VarDecl":
    item.refactor(fix)
  else:
    for child in item:
      walker(child)

def fix(text):
  if text.startswith("auto"):
    text = "\n// meta comment to ignore violation in the next line\n" + text
  else:
    text = re.sub(r"^([^=]*)=(.*)$", r"\1{\2}", text, flags=re.S)
  return text

# parse cpp codes and queue refactoring tasks
fixer = castre.walk(
    ["a.cc", "-I.", "-std=c++20"],
    walker,
    path_filter=lambda x: x is not None and x.startswith("/Users/falsycat"))

# you can reuse the fixer
castre.walk(
    ["b.cc", "-I.", "-std=c++20"],
    walker,
    fixer=fixer,
    path_filter=lambda x: x is not None and x.startswith("/Users/falsycat"))

# execute the tasks and apply changes to the actual files
fixer.fix()

before:

#include <iostream>

int main() {
  struct A { void f() { int a = 123; auto b = 1+2+3+4; } };
  int x = 123;
std::cout << "helloworld"
<< std::endl;
  auto y = 123;
    std::cout << "goodbye" << std::endl;
  int
  z
  =
  123;
}

after:

#include <iostream>

int main() {
  struct A { void f() { int a { 123}; 
// meta comment to ignore violation in the next line
auto b = 1+2+3+4; } };
  int x { 123};
std::cout << "helloworld"
<< std::endl;
  
// meta comment to ignore violation in the next line
auto y = 123;
    std::cout << "goodbye" << std::endl;
  int
  z
  {
  123};
}