3

我有一个用 C# 编写的程序,当给定一个 C++ 或 C# 文件时,它会计算文件中的行数,计算注释和设计器生成的代码块中有多少行。我想添加计算文件中有多少函数以及这些函数中有多少行的功能。我不太清楚如何确定一行(或一系列行)是否是函数(或方法)的开始。

至少,函数声明是一个返回类型,后跟标识符和参数列表。有没有办法在 C# 中确定令牌是有效的返回类型?如果不是,有什么方法可以轻松判断一行代码是否是函数的开始?基本上我需要能够可靠地区分类似的东西。

bool isThere() 
{
...
}

bool isHere = isThere()

并从

isThere()

以及任何其他类似的函数声明。

4

5 回答 5

2

这样做的问题是要准确地做到这一点,您必须考虑到可以定义 C# 函数的所有可能方式。本质上,您需要编写一个解析器。这样做超出了简单的 SO 答案的范围。

这个问题可能会有很多正则表达式形式的答案,它们适用于常见情况,但可能会在极端情况下爆炸,如下所示

int
?
/* this 
is */
main /* legal */ (code c) { 
}
于 2010-01-18T21:33:17.530 回答
1

我可能会使用正则表达式,尽管考虑到数据类型和声明选项的数量以及用户定义的类型/类,这将是不平凡的。为了简单地避免从函数调用中捕获分配,您可以从正则表达式(未经测试)开始,例如:

(private|public|internal|protected|virtual)?\s+(static)?\s+(int|bool|string|byte|char|double|long)\s+([A-Za-z][A-Za-z_0-9]*)\s*\(

这并不能(从长远来看)捕获所有内容,您需要对其进行调整。

另一种方法可能涉及反射来确定函数声明,但是当您想要进行静态源代码分析时,这可能不合适。

于 2010-01-18T21:33:22.557 回答
1

从扫描范围开始。您需要在浏览文件时计算左大括号 { 和右大括号 },以便您知道您在哪个范围内。您还需要在扫描文件时解析 // 和 /* ... */ ,因此您可以判断某些内容何时出现在注释中,而不是真正的代码。还有#if,但你必须编译代码才能知道如何解释这些。

然后,您需要在一些范围开括号之前立即解析文本以找出它们是什么。您的函数可能在全局范围、类范围或命名空间范围内,因此您必须能够解析命名空间和类以识别您正在查看的范围类型。您通常可以使用相当简单的解析(大多数程序员使用类似的样式 - 例如,很少有人在“class Fred”和它的左大括号之间放置空行。但他们可能会写“class Fred {”。那里也有可能他们会在线路上添加额外的垃圾 - 例如'模板类__DECLSPEC MYWEIRDMACRO Fred {'。但是,您可以使用一个非常简单的“该行是否包含两边都有空格的'class'这个词?在大多数情况下都可以使用的启发式方法。

好的,所以您现在知道您在一个命名空间和一个类中,并且您找到了一个新的开放范围。它是一种方法吗?

方法的主要识别特征是:

  • 返回类型。这可以是任何字符序列,也可以是许多标记(“__DLLEXPORT const unsigned myInt32typedef * &”)。除非你编译整个项目,否则你没有机会。
  • 函数名。单个令牌(但要注意“operator =”等)
  • 一对包含零个或多个参数或“void”的括号。这是你最好的线索。
  • 函数声明将不包括某些在许多范围之前的保留字(例如枚举、类、结构等)。并且它可能会使用一些您不能绊倒的保留字(模板、常量等)。

So you could search up for a blank line, or a line ending in ; { or } that indicates the end of the previous statement/scope. Then grab all the text between that point and the open brace of your scope. Then extract a list of tokens, and try to match the parameter-list brackets. Check that none of the tokens are reserved words (enum, struct, class etc).

This will give you a "reasonable degree of confidence" that you have a method. You don't need much parsing to get a pretty high degree of accuracy. You could spend a lot of time finding all the special cases that confuse your "parser", but if you are working on a reasonably consistent code-base (i.e. just your own company's code) then you'll probably be able to identify all the methods in the code fairly easily.

于 2010-01-18T22:04:52.470 回答
0

If you want to write a real parser (I know you might not want to) then try ANTLR. If nothing else it will be a fun project

于 2010-01-18T22:19:49.737 回答
-1

有没有办法在 C# 中确定令牌是有效的返回类型?

您可以很容易地确定它是返回类型还是错误(通过确保它不是可能处于该位置的其他任何东西)。而且您可能不需要保证无效代码的“正确”行为。

然后你寻找括号。

于 2010-01-18T21:32:53.963 回答