使用Checkstyle 4.4 RegExp检查StackOverflowError

时间:2009-11-25 21:26:23

标签: regex checkstyle

你好日

背景:

我正在使用带有RegExp检查器模块的Checkstyle 4.4.2来检测java源头中的文件名何时与它们所在的类或接口的文件名不匹配。当开发人员将标题从一个类复制到另一个类而不修改“File:”标记时,就会发生这种情况。

在RexExp检查程序中使用正则表达式已经通过了很多化身,并且(虽然此时可能有点过分)看起来像这样:

File: (\w+)\.java\n(?:.*\n)*?(?:[\w|\s]*?(?: class | interface )\1)

我正在检查的文件的基本形式(虽然大大简化)看起来像这样

/*
 *
 *  Copyright 2009
 *  ...
 *  File: Bar.java
 *  ... 
 */
package foo
... 
import ..
...
/**
 * ...
 */
public class Bar
{...} 

问题:

找不到匹配项时,(当包含“File:Bar.java”的标题被复制到文件Bat.java中时)我收到很长文件的StackOverflowError(我的测试用例是@ 1300行)。

我已经尝试了几个可视正则表达式测试器,当正则表达式引擎通过包含类或接口名称的行时,可以在 非匹配情况 中看到它开始在下一行再次搜索并进行一些可能导致StackOverflowError

的回溯

问题:

如何通过修改正则表达式来防止StackOverflowError

是否有某种方法可以修改我的正则表达式,使其在 不匹配的情况下 (即当包含“File:Bar.java”的标题被复制到文件Bat.java)匹配将在检查包含接口或类名的行时停止,并看到“\ 1”与第一组不匹配。

或者,如果可以这样做,可以在检查包含接口或类的行之后最小化搜索和匹配,从而最小化处理和(希望)StackOverflow错误吗?

2 个答案:

答案 0 :(得分:0)

尝试

File: (\w+)\.java\n.*^[\w \t]+(?:class|interface) \1

以点匹配全部模式。理由:

[\w\s](|不属于那里)匹配任何内容,包括换行符。这导致大量的回溯备份到正则表达式的前一部分匹配的行中。

如果让贪婪的小点吞噬文件末尾的所有内容(快速)然后回溯,直到找到以单词或空格/标签(但没有换行符)开头的行,然后class或者interface和\ 1,那么不需要那么多的堆栈空间。

一个不同的,甚至可能更好的解决方案是将问题分成几部分。

首先匹配File: (\w+)\.java部分。然后使用^[\w \t]+(?:class|interface)以及同一文件中第一次搜索的\1匹配进行第二次搜索。

答案 1 :(得分:0)

跟进:

我插入了Tim Pietzcher的上述建议,他的贪婪解决方案确实失败得更快,没有找到匹配时没有StackOverflowError。但是,在肯定的情况下,仍然会发生StackOverflowError。

我看了一下源代码RegexpCheck.java。类模式以多行模式构造,使得表达式^和$分别在行终止符之后或之前或输入序列的末尾匹配。然后它将整个类文件读入一个字符串,并对该模式进行递归搜索(请参阅findMatch())。这无疑是StackOverflowException的来源。

最后我没有让它工作(并且放弃了)因为Maven 2在大约6周前发布了maven-checkstyle-plugin-2.4 / Checkstyle 5.0,所以我们决定升级我们的工具。这可能无法解决StackOverflowError问题,但它会给我一些其他工作,直到有人决定我们需要再次追求它。