StackOverflowError с Checkstyle 4.4 RegExp проверяет - PullRequest
0 голосов
/ 26 ноября 2009

Hello

Справочная информация:

Я использую Checkstyle 4.4.2 с модулем проверки RegExp, чтобы определить, не совпадают ли имена файлов в исходных заголовочных файлах 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 голосов
/ 30 декабря 2009

Продолжение:

Я включил приведенное выше предложение Тима Пицчера, и его жадное решение действительно провалилось быстрее и без ошибки StackOverflowError, когда совпадений не было найдено. Тем не менее, в положительном случае, StackOverflowError все еще произошла.

Я взглянул на исходный код RegexpCheck.java . Шаблон классов создается в многострочном режиме так, что выражения ^ и $ совпадают сразу после или непосредственно перед, соответственно, разделителем строки или концом входной последовательности. Затем он читает весь файл класса в строку и выполняет рекурсивный поиск шаблона (см. FindMatch ()). Это, несомненно, источник StackOverflowException.

В конце концов я не получил его (и сдался). Так как Maven 2 выпустил maven-checkstyle-plugin-2.4 / Checkstyle 5.0 около 6 недель назад, мы решили обновить наши инструменты. Это может не решить проблему StackOverflowError, но это даст мне еще кое-что для работы, пока кто-нибудь не решит, что нам нужно продолжить это снова.

0 голосов
/ 26 ноября 2009

Попробуйте

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

в режиме точка-совпадение-все. Обоснование:

[\w\s] (| не принадлежит) соответствует чему-либо, включая разрывы строк. Это приводит к тому, что мы возвращаемся назад к строкам, которым соответствовала предыдущая часть регулярного выражения.

Если вы позволите жадной точке сожрать все до конца файла (быстро), а затем вернуться назад, пока не найдете строку, начинающуюся со слов или пробелов / табуляции (но без перевода строки), а затем class или interface и \ 1, тогда для этого не требуется много места в стеке.

Другое, и, возможно, даже лучшее решение состоит в том, чтобы разбить проблему на части.

Первое совпадение с частью File: (\w+)\.java. Затем выполните второй поиск с помощью ^[\w \t]+(?:class|interface) плюс совпадение \1 из первого поиска по тому же файлу.

...