生成用于大规模重构/重命名的C++符号列表
generate a list of C++ symbols for mass refactoring/renaming
Background
我继承了一个遗留的 60kloc g++ 项目,我想重构该项目以在整个项目中强制执行一致的命名约定。
问题
是否有一个免费/开源的静态分析工具可以生成以下列表:
- 全局符号
- 类名
- 成员方法(公共/受保护/私有,如果可能(
- 成员变量
- 静态方法
- 本地符号(可能会忽略这些符号(
- 我可能错过的任何其他符号,但可能会影响代码的阅读器
方法
我的目的是使用 vim 来编辑生成的符号列表,然后使用 Ruby 脚本对符号进行非常粗略的搜索和替换/映射,以便至少命名约定是一致的。
这个过程有点丑陋,我希望初始编译会失败,但如果我可以有一组更具可读性的代码,我不介意手动完成并解决问题。
大型C++代码库的开发人员使用哪些类型的工具来执行这种重构?
C++的自动重构非常困难,部分与预处理器(宏和文件包含(有关,但主要与解析、名称查找和语义分析阶段其余部分(模板实例化、常量表达式、重载分辨率等(之间的相互依赖性有关。 在我处理过的非常大的C++代码库中,自动重构根本没有完成,并且由于固有的困难,重构工具的质量很差。
自从 clang 出现以来,它专门具有模块化前端,因此您可以以比其他工具更好的方式访问 AST,可能会有一些基于它的更好的重构工具 - 但我不会屏住呼吸。
看看 clang 中的 AST 转储,也许你可以在 XML 上编写一个脚本来给你一个转储,该转储可能构成手动重构它的起点。
Op 想要进行大规模重命名,例如,生成一个名称列表,然后在大型源代码库中重命名其中的许多名称。
擅长这一点的重构工具是一种选择,如果他能找到的话。
一个奇怪但也许有效的替代方案:C++代码源代码混淆工具。
我们公司提供其中之一,可以执行以下操作(是的,这对于任务来说似乎是错误的!
- 条评论
- 损坏格式
- 用打乱的名称一致地替换标识符(答案的种子!
- 构建标识符映射("标识符 -> scrambled_identifier"名称列表(作为结果 对于所有标识符。
此过程应用于文件,无需预处理。
因此,实际上,它是一个大规模重命名工具。 重命名为坏名字是它的目的,但是它可以被滥用以重命名为好名称。
事实上,它接受什么作为输入是一个标识符映射(可能是空的,当然在第一次运行时,通常采用从连续的模糊处理运行(,并重命名在该映射中找到的标识符根据地图,以及它找不到新的加扰名称的标识符。
如果您为其提供完整地图,则可以完全控制其重命名为的名称。
因此,要将其用于大规模重命名,以下过程应该有效:
- 运行混淆器,获取标识符映射。抛出结果源文本离开。
- 将标识符映射修改为"标识符 ->标识符"。对于像 Emacs 这样体面的编辑器来说,这是一个 30 秒的任务。 如果原封不动地使用这个修改后的地图,混淆器会将每个符号重命名为自己,例如,没有任何东西被重命名。 将"标识符 -> foo"替换为"标识符"被该工具视为"标识符 ->标识符"。
- (然后排序(查看标识符列表。 为某些标识符选择新名称。相应地修改列表:"bad_identifier_1 -> better_identifier_1"
- 使用修改后的地图重新运行混淆器。 您的bad_identifiers将被更换。
哎呀,评论和格式呢:-?
好吧,有一个命令行开关本质上说"不要扔掉评论"。就格式而言,混淆器显着地包括一个源代码格式化程序。只需作为格式化程序第二次运行它即可。 瞧,重命名的代码格式漂亮。
警告:
- 格式化程序无法处理一些放置不当的预处理器条件;大多数C++代码都没有这个,它的内容通常可以通过一行编辑来更改。
- 混淆器不区分范围。 给定 I -> J,它将把所有 I 实例重命名为 J。
- 混淆器不会检测到愚蠢的重命名。 如果你重命名 I -> J,并重命名 K -> J,如果重命名会损坏你的程序,混淆器不会告诉你。(重命名可能有效;取决于您的代码以及 I 和 K 的使用位置(。 这很容易避免:不要在任何地方生成具有相同重命名名称的地图。 这意味着您不应重命名系统包含文件中出现的标识符;您可以重命名应用程序包含文件中显示的标识符。
如果有足够的兴趣,我们的小改动可以直接保留格式和注释。
这个笨拙的过程的好处是你可以尝试获得正确的重命名集;你只需要保留最终的"混淆/格式化"结果。 当然,您可以通过每个阶段运行一个流程来重命名组中的事物集。 强烈建议在每个周期后重新编译:-}
您可以使用此过程一次重命名一个标识符,但我认为常规编辑器可以很好地为您服务。
如果OP只是想要名字列表,他显然可以在第一次混淆传递后停下来,带着标识符映射逃跑。
不,它不是正则表达式替换字符串黑客;它使用完整的C++11词法分析器,因此不会被字符串文字或注释的内容混淆。 格式化程序部分实际上使用完整的 C++(11( 解析器。
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- 将无符号char*转换为std::istream*C++
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- vscode g++链路故障:体系结构x86_64的未定义符号
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- Visual studio代码重构似乎不起作用(例如,重命名符号-f2)
- 使用gcc从静态链接的文件中查找可选符号
- C++中无符号字符溢出
- 使用无符号字符数组有效存储内存
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- VC++本机单元测试,找不到调试符号
- 为什么我必须在C++中添加一个赋值符号来声明一个数组
- 检查TCHAR数组输入是否为带符号整数C++
- 用符号版本替换对函数的所有调用
- 未解析的外部符号_MsiLocateComponentW@12.
- 如何打印boost多精度128位无符号整数
- C++模板函数,用于比较任何无符号整数和有符号整数
- 在 Mac 上使用 CMAKE 将 FFTW 和 FFTWPP 链接到项目中时未定义的符号