7

我想对代码进行一些重构,尤其是文件之间的“包含”类关系。其中有很多,要开始使用,最好有一个列表、图表,甚至是柱状图,这样我就可以一眼看出从哪里包含了什么。

(在许多情况下,给定文件包含在多个其他文件中,因此该图将是 DAG,而不是树。没有循环。)

我正在使用 TeX(实际上是 ConTeXt),但这个问题似乎适用于任何具有类似#includeC功能的编程语言。

显而易见,简单的答案是在所有 .tex 文件中为相关关键字( ,和我们定义的其他几个宏)执行一个grep或“在文件中查找” 。这总比没有好,但是输出很长,仍然很难看到包含什么的模式。例如,文件 A 通常包含在文件 B 之前吗?文件 C 是否曾多次包含在同一个文件中?\usemodule\input

我想这会带来一个额外但可选的功能:这样的工具将能够显示来自特定文件的包含序列。所以在那种情况下,DAG 可能是一个多重图,即从一个文件到另一个文件可能有多个弧。

理想情况下,最好能够对每个文件进行注释,并对其中的内容进行非常简短的总结。这将构成该文件图形节点上文本的一部分。

可能这种事情可以通过生成graphviz dot语言的脚本来完成。但我想知道它是否已经完成,而不是重新发明轮子。

4

2 回答 2

3

因为现在是我的国家的星期五,我在等我的同事去喝啤酒,所以我想我会做一些编程。

在这里http://www.luki.webzdarma.cz/up/IncludeGraph.zip您可以下载一个非常简单的实用程序的源代码,该实用程序在一个文件夹中查找所有文件,解析 #includes 并为此生成一个 .dot 文件。

它支持并正确处理相对路径,适用于 windows,也应该适用于 linux。它以非常简陋的方式编写。我的dot版本不解析生成的文件,有一些bug,但我现在真的需要去喝酒,看看你能不能修复它。我不是普通的点用户,我看不到它,但我确信它很明显。

享受 ...

PS - 如果您在编译和/或运行时遇到问题,请告诉我。谢谢。

编辑

好吧,我的错,Linux上有一些小故障。点问题是它使用“graph”而不是“digraph”。但它现在就像魅力一样工作。这是链接。只需键入 make,如果这样,make test 应该会生成程序本身的下图:

包含图

它忽略了 C++ 文件中的预处理器指令,因此直接对它不是很有用(可以通过简单地使用预处理器输出标志调用 g++ 并处理它而不是实际文件来修复)。我今天没有使用正则表达式,但是如果您有任何编程经验,您会发现修改 DotGraph.cpp 对包含令牌进行硬编码和更改文件扩展名列表应该不会很难。明天可能会使用正则表达式或其他东西。

于 2012-11-02T18:22:29.203 回答
2

一个聪明而通用的解决方案是跟踪构建系统(使用类似 strace、LD_PRELOAD、修补二进制文件或其他一些调试工具)。

一旦你收集了文件打开/关闭操作的顺序,你只需要过滤掉不感兴趣的东西,只要以下假设成立,就应该很容易为任何语言构建依赖关系树:

  1. 构建系统将在包含每个文件时打开它。
  2. 构建系统将在每个文件到达末尾时关闭它。

不幸的是,编写良好或编写不佳的编译器可能会违反这些假设,例如仅在第一次包含文件时打开文件,或者从不关闭任何文件。

也许由于这些限制,我不知道这个想法的任何实现。

另一方面,聪明的构建系统可能包括自己计算或提取依赖项的功能。gcc 可以-M选择输出依赖项,而 javac 可以自己计算依赖项(尽管我不知道如何让它输出它们)。

就 TeX 而言,我不知道足够的 TeX 来实际实现这一点,但从概念上讲,似乎应该可以重新定义低级 include 命令以:

  1. 写下即将包含的内容的日志
  2. 调用原始的包含命令来包含它
  3. 写下所包含内容的日志

然后,您可以从日志输出构建您的树。

于 2012-11-04T17:02:12.560 回答