C# 中的源代码取消注释器






2.09/5 (6投票s)
首批删除多种 C 风格语言(C、C++、Java 和 C#)中注释的 C# 应用程序之一
引言
您是否是一名开发人员,觉得阅读代码比阅读注释更容易,但发现分析代码有多困难,以及一个函数/过程有多简单?您是否曾经想过重新编写包含 20 多页(或更多)代码的文档,并且知道逐行删除注释有多么繁琐?或者您是否正在考虑在传输代码之前如何“稀释”您的代码,以减少网络传输时间。
编译程序时,代码中的注释会发生什么情况?本文深入介绍了这些内容,并提供了一个工具,用于删除 ASCII 源代码文件中的现有注释。
工作原理
普通的编译器不理解注释。它只是简单地跳过它们。但是,在纯文本源代码中保留它们很可能会在编译过程中引起问题。因此,为了克服这种情况,大多数 C 风格的语言使用 /* */ 或 // 来表示注释。这将标记编译器/解释器不要“读取”后面的内容
int x; //commentary about an unknown alien x, in one line
或者
int x; /* Tell me more about the stars and the moon, in an essay */
那么,您是否想知道在您按下编译按钮的那一刻,那些讨厌的注释会发生什么?它们被丢弃了!好吧,我的意思是它们保留在源文件中。惊讶吗?如前所述,注释不是为编译器准备的!话虽如此,可以将注释存储在二进制文件的元数据部分。(尽管我不知道有哪个编译器实现了这个功能,即使有,也会牺牲很多性能)
以 Java 中的这段代码为例
/**
* {@link Class#getSimpleName()} is not GWT compatible yet, so we
* provide our own implementation.
*/
@VisibleForTesting
static String simpleName(Class<?> clazz) {
String name = clazz.getName();
// we want the name of the inner class all by its lonesome
int start = name.lastIndexOf('$');
//if this isn't an inner class, just find the start of the
// top level class name.
if (start == -1) {
start = name.lastIndexOf('.');
}
return name.substring(start + 1);
}
当您编译代码时,编译器会看到它像这样
@VisibleForTesting
static String simpleName(Class<?> clazz) {
String name = clazz.getName();
int start = name.lastIndexOf('$');
if (start == -1) {
start = name.lastIndexOf('.');
}
return name.substring(start + 1);
}
因为注释是在运行时被删除的。这就是编译器生成对象和/或机器代码所需要的一切!删除注释总是在编译之前完成的,而且通常对开发人员来说是透明的。
我今天在这里介绍的应用程序实现了这个功能。给定一个文本源文件,它可以删除注释,留下可以编译的代码。当您希望重新编写别人的或您自己的代码,而无需手动逐行删除代码时,这会很方便。在示例屏幕截图中,所有单行、多行甚至 Javadoc 注释都被删除。同样,在 C# 中,XML 注释也被删除。
算法概述
基本规则是,当在代码行中找到单行 (//) 注释时,程序应停止读取,直到遇到新行 ('\n'),然后读取下一行。
当找到多行 (/*) 标记时,程序应停止处理,直到找到 */ 为止。"\n" 或 "*/" 将状态恢复正常。
在此实现中,使用 StreamReader
读取我们的 ASCII 源代码。由于代码是使用 readLine()
方法逐行处理的,因此检测和处理注释分隔符变得稍微困难一些。许多用 C 编写的编译器实现(例如 gcc)都在逐字符地解析代码,以提高性能和优化。但是,我们正在开发的远不是一个成熟的编译器,因此逐行处理应该足够了。
我设法将其保持在最少的 2 个方法,即主方法 doUncomment()
和一个用于处理字符串文字的内部方法。所有方法都实现为 static
,因此无需创建实例。有关更多信息,请参阅 Uncommenter
类。
使用代码
要使用该代码,请插入指令
using UcommenterCS;
然后简单地调用 static
函数来完成工作。例如
Uncommenter.doUncomment("src.cpp"); //specify full path
就是这样。
但是,如果您希望“开箱即用”地单独运行它,或者只是想尝试一下,我包含了一个编译后的二进制文件,它同样好。它位于 /bin
文件夹中。要使用它,请发出以下命令
UcommenterCS <source.cpp/c/cs/java/h/js>
解析能力
应避免在字符串分隔符中使用注释。此应用程序能够正确地确保注释不是字符串的一部分!它忽略 "
和 "
块之间的注释分隔符。
未来的功能包括检测和警告未终止的块注释和字符串文字,并可以选择在发现它们时中断执行。
因为我不是编译器语言学家,所以我无法想到代码可能失败的所有可能情况。但是,如果您愿意接受挑战,欢迎您尝试破解我的代码。如果发生这种情况,请务必告诉我。
历史
- 第一个版本 - 7 月 9 日
- 第二次更新(在不同的类名和命名空间下重新打包并更改为静态方法) - 9 月 14 日
我计划在不久的将来编写一个 Window Forms 版本。还在开发中的是 Java 版本。