StackOverflowError с проверкой регулярного выражения Checkstyle 4.4
-
05-07-2019 - |
Вопрос
Здравствуйте,
Предыстория:
Я использую 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
{...}
Проблема:
Когда совпадение не найдено, (т.е.когда заголовок, содержащий "Файл:Bar.java " копируется в файл Bat.java ) Я получаю StackOverflowError для очень длинных файлов (мой тестовый пример составляет 1300 строк).
Я экспериментировал с несколькими визуальными тестерами регулярных выражений и могу видеть, что в несоответствующий случай когда механизм регулярных выражений передает строку, содержащую имя класса или интерфейса, он снова начинает поиск в следующей строке и выполняет некоторый откат, который, вероятно, вызывает StackOverflowError
Этот Вопрос:
Как предотвратить StackOverflowError, изменив регулярное выражение
Есть ли какой-нибудь способ изменить мое регулярное выражение таким образом, чтобы в несоответствующий случай (т.е.когда заголовок, содержащий "Файл:Bar.java " копируется в файл Bat.java ) что сопоставление прекратится, как только он проверит строку, содержащую имя интерфейса или класса, и увидит, что "\1" не соответствует первой группе.
В качестве альтернативы, если это можно сделать, возможно ли минимизировать поиск и сопоставление, которые выполняются после проверки строки, содержащей интерфейс или класс, таким образом минимизируя обработку и (надеюсь) ошибку StackOverflow?
Решение
Попробуй
File: (\w+)\.java\n.*^[\w \t]+(?:class|interface) \1
в режиме совпадения точек со всеми.Обоснование:
[\w\s]
(| там не место) соответствует чему угодно, включая разрывы строк.Это приводит к большому количеству возвратов к строкам, которым соответствовала предыдущая часть регулярного выражения.
Если вы позволите жадной точке поглотить все до конца файла (быстро), а затем вернетесь назад, пока не найдете строку, начинающуюся со слов или пробелов / табуляции (но без перевода строк), а затем class
или interface
и \1, то для этого не требуется столько места в стеке.
Другим и, вероятно, даже лучшим решением было бы разделить проблему на части.
Первое совпадение с File: (\w+)\.java
часть.Затем выполните второй поиск с помощью ^[\w \t]+(?:class|interface)
плюс ко всему , \1
совпадение с первым поиском по одному и тому же файлу.
Другие советы
Последующие действия:
Я подключил приведенное выше предложение Тима Пьецчера, и его жадное решение действительно сработало быстрее и без StackOverflowError, когда совпадение не было найдено.Однако в положительном случае ошибка StackOverflowError все равно произошла.
Я взглянул на исходный код RegexpCheck.java.Шаблон classes создается в многострочном режиме таким образом, что выражения ^ и $ совпадают сразу после или непосредственно перед, соответственно, завершителем строки или концом входной последовательности.Затем он считывает весь файл класса в строку и выполняет рекурсивный поиск шаблона (см. findMatch()).Это, несомненно, является источником исключения StackOverflowException .
В конце концов, я не смог заставить это работать (и сдался) С тех пор, как Maven 2 выпустил maven-checkstyle-plugin-2.4 / Checkstyle 5.0 около 6 недель назад, мы решили обновить наши инструменты.Возможно, это не решит проблему StackOverflowError, но это даст мне еще кое-что для работы, пока кто-нибудь не решит, что нам нужно продолжить это снова.