你好日
背景:
我正在使用带有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错误吗?
答案 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问题,但它会给我一些其他工作,直到有人决定我们需要再次追求它。