Regex для поиска методов, имеющих «внутренний» метод

Я работаю над обслуживанием монолитной базы кода Java, где было обнаружено, что некоторые из методов @GET фактически запускают сеанс записи и, следовательно, на самом деле должны быть методами @POST. Я написал следующее регулярное выражение, чтобы облегчить мой поиск:

@GET[^}]+startWrite

Это дало мне все вхождения аннотации @GET, которая достигла строки «startWrite» (которая является частью имен методов, запускающих сеанс записи) до достижения «}», которая используется для закрытия метода в Java. Это решение не идеально, так как возможно, что } используется внутри метода перед началом сеанса записи (например, в операторе if), но оно оказалось достаточно эффективным для работы.

Однако с тех пор я обратил внимание на то, что многие методы следуют этому формату:

@GET
@Path("/methodName")
public ObjectName methodName(...){
    ...
    return methodNameInner(...);
}
private methodNameInner(...){
    startWriteSession();
    ...
}

Другими словами, команда сеанса записи перемещается в другой метод, который всегда имеет то же имя, что и исходный метод (и путь), за которым следует «Inner». этот внутренний метод всегда находится ниже исходного метода. Я попытался написать регулярное выражение, которое искало вхождения @GET, за которым следовали несколько строк до имени пути или имени метода (которое я выделил в отдельную группу), за которым следовали дополнительные символы, затем \1Inner, а затем тот же [^}]+startWrite, что означает, что внутренний метод достиг строки startWrite до того, как достиг конца метода. Но я не смог заставить его работать.

Может ли кто-нибудь помочь мне?

Regex не является инструментом для работы. Вам нужно что-то вроде ClassGraph. Там даже есть пример поиска аннотированных методов.

g00se 05.07.2024 11:49

@g00se прав, и не только субъективно, но и объективно. Это не столько «регулярное выражение не является инструментом для работы», сколько: «Регулярные выражения принципиально неспособны выполнять эту работу, и поэтому то, что вы хотите, невозможно». Помните: «Регулярные выражения не были созданы г-жой Жозефиной Регуляр». - они названы в честь класса грамматик, которые они могут анализировать - обычные грамматики. Java (язык) не является обычным. То, что вы делаете, похоже на вопрос: «Я купил услуги японского/корейского переводчика». им перевести этот русский документ?».

rzwitserloot 05.07.2024 12:25

@rzwitserloot Я не совсем уверен, что следую. Как я уже говорил, я уже тщетно использовал регулярное выражение для поиска методов get, которые запускают сеанс записи, и я не понимаю, чем этот запрос будет принципиально отличаться. Чтобы внести ясность, я планирую вручную проверять результаты, сгенерированные регулярным выражением, и не ожидаю, что результаты будут полными, подобно тому, как я знаю, что они не были полными в исходном случае. Я также понимаю, что добавление еще одной библиотеки может дать более полный результат, но в настоящее время у меня нет возможности добавить еще одну зависимость к этому приложению.

user9934848 05.07.2024 14:25

@user9934848 user9934848 Использование регулярных выражений для анализа Java-кода нецелесообразно. То, что вы сделали, не позволило бы найти все возможные способы написания этого метода и не поможет найти эту ситуацию.

rzwitserloot 05.07.2024 15:34
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Личные мысли

Полностью согласен с комментариями по вашему вопросу, что штатный выражение не является правильным инструментом, поскольку оно не обработает все ваши случаях и будет работать только в том случае, если анализируемый вами код написан так: ты ожидал.

Но в некоторых ситуациях, когда вы просто хотите исправить/адаптировать некоторые существующий код, ограниченный несколькими файлами и методами, то регулярное выражение может быстро решить ваши потребности.

Регулярное выражение, без гарантии

Если и только если ваш код будет написан так, как вы упомянули, то вы можно было бы использовать этот прокомментированный шаблон:

"
^@GET\r?\n                     # A line with @GET
@Path\(\"(?<path>[^\"]*)\"\)   # Followed by @Path, and capture this path.
.*?                            # Match anything, in an ungreedy way.
# Capture the name of the method and its parameters.
public\s+ObjectName\s+(?<method>\w+)\((?<params>[^)]+)\)\s*\{
.*?                            # Match anything, in an ungreedy way.
\bstartWriteSession\(\);       # match a call to startWriteSession().
"gmxsi

Небольшой тест онлайн: https://regex101.com/r/4Jpg1B/2

Ваше здоровье! Мне пришлось немного адаптировать его, чтобы он соответствовал моему конкретному сценарию использования, и он закончился на "(?s)\@GET\n\t\@Path(\"/(?<path>[^\"]*)\ ").*\k<path‌​>Inner[^}]+startWrit‌​e"

user9934848 08.07.2024 13:31

@user9934848 user9934848 Отлично! Приятно знать, что это помогло вам решить эту проблему. Хорошая идея — добавить обратную ссылку на имя функции, соответствующую методу *Inner().

Patrick Janser 08.07.2024 13:59

Другие вопросы по теме