Я работаю над обслуживанием монолитной базы кода 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 до того, как достиг конца метода. Но я не смог заставить его работать.
Может ли кто-нибудь помочь мне?
@g00se прав, и не только субъективно, но и объективно. Это не столько «регулярное выражение не является инструментом для работы», сколько: «Регулярные выражения принципиально неспособны выполнять эту работу, и поэтому то, что вы хотите, невозможно». Помните: «Регулярные выражения не были созданы г-жой Жозефиной Регуляр». - они названы в честь класса грамматик, которые они могут анализировать - обычные грамматики. Java (язык) не является обычным. То, что вы делаете, похоже на вопрос: «Я купил услуги японского/корейского переводчика». им перевести этот русский документ?».
@rzwitserloot Я не совсем уверен, что следую. Как я уже говорил, я уже тщетно использовал регулярное выражение для поиска методов get, которые запускают сеанс записи, и я не понимаю, чем этот запрос будет принципиально отличаться. Чтобы внести ясность, я планирую вручную проверять результаты, сгенерированные регулярным выражением, и не ожидаю, что результаты будут полными, подобно тому, как я знаю, что они не были полными в исходном случае. Я также понимаю, что добавление еще одной библиотеки может дать более полный результат, но в настоящее время у меня нет возможности добавить еще одну зависимость к этому приложению.
@user9934848 user9934848 Использование регулярных выражений для анализа Java-кода нецелесообразно. То, что вы сделали, не позволило бы найти все возможные способы написания этого метода и не поможет найти эту ситуацию.
Полностью согласен с комментариями по вашему вопросу, что штатный выражение не является правильным инструментом, поскольку оно не обработает все ваши случаях и будет работать только в том случае, если анализируемый вами код написан так: ты ожидал.
Но в некоторых ситуациях, когда вы просто хотите исправить/адаптировать некоторые существующий код, ограниченный несколькими файлами и методами, то регулярное выражение может быстро решить ваши потребности.
Если и только если ваш код будет написан так, как вы упомянули, то вы можно было бы использовать этот прокомментированный шаблон:
"
^@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[^}]+startWrite"
@user9934848 user9934848 Отлично! Приятно знать, что это помогло вам решить эту проблему. Хорошая идея — добавить обратную ссылку на имя функции, соответствующую методу *Inner()
.
Regex не является инструментом для работы. Вам нужно что-то вроде ClassGraph. Там даже есть пример поиска аннотированных методов.