[
https://issues.apache.org/jira/browse/GROOVY-12708?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18139338#comment-18139338
]
ASF GitHub Bot commented on GROOVY-12708:
-----------------------------------------
testlens-app[bot] commented on PR #3238:
URL: https://github.com/apache/groovy/pull/3238#issuecomment-6675610429
## ✅ All tests passed ✅
🏷️ Commit: 0bae8b37ea3df2091144361dc9d723a928885105
▶️ Tests: 128315 executed
⚪️ Checks: 26/26 completed
---
_Learn more about TestLens at
[testlens.app/docs](https://testlens.app/docs/features/pr-comment/)._
> RegexChecker ignores the flags argument of Pattern.compile
> ----------------------------------------------------------
>
> Key: GROOVY-12708
> URL: https://issues.apache.org/jira/browse/GROOVY-12708
> Project: Groovy
> Issue Type: Bug
> Affects Versions: 5.1.3, 6.0.0
> Reporter: Paul King
> Priority: Major
>
> h2. Problem
> {{groovy.typecheckers.RegexChecker}} checks {{Pattern.compile(regex, flags)}}
> by compiling {{regex}} without {{flags}}. Most flags don't affect whether a
> regex is valid or how many groups it has, but {{Pattern.COMMENTS}} and
> {{Pattern.LITERAL}} change how the regex text is parsed, so the checker
> checks a different regex from the one that runs:
> * *Valid code is rejected* with "Bad regex", when the regex is only valid
> with the flag.
> * *Errors are missed*, when the group count without the flag is higher than
> the real one (text in a COMMENTS-mode comment, or a LITERAL regex, which has
> no groups).
> Reproducer, run with {{groovy --configscript config.groovy comments.groovy}}:
> {code:groovy|title=config.groovy}
> import groovy.transform.TypeChecked
> withConfig(configuration) {
> ast(TypeChecked, extensions: 'groovy.typecheckers.RegexChecker')
> }
> {code}
> {code:groovy|title=comments.groovy}
> import java.util.regex.Pattern
> assert Pattern.compile('(a) # (b', Pattern.COMMENTS).matcher('a').matches()
> {code}
> Actual:
> {noformat}
> [Static type checking] - Bad regex: Unclosed group near index 8
> {noformat}
> Expected: the script compiles and the assertion passes, as it does without
> the extension.
> ||Script||Actual (4.0.32, 5.1.3, 6.0.0)||Expected||
> |{{Pattern.compile('(a) # (b', Pattern.COMMENTS)}}|"Bad regex: Unclosed group
> near index 8"|compiles|
> |{{Pattern.compile('(?< first >a)', Pattern.COMMENTS)}}|"Bad regex: capturing
> group name does not start with a Latin letter near index 3"|compiles|
> |{{Pattern.compile('a(b', Pattern.LITERAL)}}|"Bad regex: Unclosed group near
> index 3"|compiles|
> |{{Matcher m = Pattern.compile('(a) # (b)', Pattern.COMMENTS).matcher('a')}},
> then {{m.group(2)}}|compiles, then {{IndexOutOfBoundsException: No group 2}}
> at runtime (6.0.0)|"Invalid group count 2 for regex with 1 group"|
> |{{Matcher m = Pattern.compile('(a)', Pattern.LITERAL).matcher('(a)')}}, then
> {{m.group(1)}}|compiles, then {{IndexOutOfBoundsException: No group 1}} at
> runtime (6.0.0)|"Invalid group count 1 for regex with 0 groups"|
> The same flags written inline, such as {{(?x)}}, are handled correctly,
> because the JDK applies them when the checker compiles the regex.
> On 4.0.32 and 5.1.3 the last two scripts instead fail with an unrelated
> general error in {{findTargetVariable}}, from a crash on
> {{Pattern.compile(...).matcher(...)}} that was fixed before 6.0.0.
> h2. Proposed fix
> Work out the flags argument at compile time and compile the regex with it.
> Then "Bad regex", the group count, the named-group check and the
> {{matcher[...][...]}} type inference all apply to the regex that actually
> runs. The flags can be written as:
> * an {{int}} constant;
> * a {{Pattern}} constant such as {{Pattern.COMMENTS}}, read from the
> {{Pattern}} class by name;
> * constants combined with {{|}};
> * a local variable or field holding one of these, as already allowed for the
> regex string.
> When the flags can't be worked out (a parameter, a method call), skip the
> checks for that call and record no group count, because the result depends on
> flags that are only known at runtime.
> A LITERAL regex has no groups at all. The named-group check (GROOVY-12707)
> works by compiling the regex with a named backreference added to the end, but
> under LITERAL that text is literal, so every name would look defined. Record
> a LITERAL regex as having no named groups instead.
> h2. Tests
> * Each row of the table above.
> * Flags written as {{Pattern.COMMENTS}}, {{Pattern.COMMENTS |
> Pattern.CASE_INSENSITIVE}}, an {{int}} constant and a local variable, with
> the same results.
> * Flags that can't be worked out (a method parameter): no "Bad regex" error
> and no group-count error.
> * A named group under COMMENTS passed as a flag ({{Pattern.compile('(?< first
> >a)', Pattern.COMMENTS)}}, then {{m.group('first')}}) compiles, and an
> undefined name is reported.
> * Flags that don't change parsing ({{CASE_INSENSITIVE}}) give the same
> results as no flags.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)