0

你好,

背景:

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

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

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

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

4

2 回答 2

0

尝试

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

在点匹配所有模式下。理由:

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

如果你让贪婪的点吞噬所有文件直到文件末尾(快速)然后回溯,直到找到以单词或空格/制表符(但没有换行符)开头的行,然后是classorinterface和 \1,那么这不会不需要太多的堆栈空间。

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

首先匹配File: (\w+)\.java零件。然后在同一个文件上^[\w \t]+(?:class|interface)加上\1第一次搜索的匹配项进行第二次搜索。

于 2009-11-25T22:16:11.373 回答
0

跟进:

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

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

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

于 2009-12-30T20:33:27.253 回答