Problem
When using regex patterns with the alternation operator | in the OrganizeImports groups configuration, the regex fails to match imports that individual patterns (without alternation) match correctly.
Example
Given this .scalafix.conf:
OrganizeImports {
groups = [
"re:^(org\\.apache\\.pekko\\.?|pekko\\.)",
"org.slf4j.",
"*"
]
removeUnused = true
}
The regex ^(org\.apache\.pekko\.?|pekko\.) should match both:
import org.apache.pekko (syntax string: org.apache.pekko)
import pekko.actor.Actor (syntax string: pekko.actor.Actor)
Expected: Both imports go to group 0.
Actual: Neither import goes to group 0. Both fall through to the * catch-all group.
What works
Each pattern works correctly when used standalone (without alternation):
# This matches `import org.apache.pekko` correctly:
groups = ["re:org\\.apache\\.pekko", "*"]
# This matches `import pekko.*` correctly:
groups = ["pekko.", "*"]
What doesn't work
Combining them with | fails:
# Neither pattern matches when combined:
groups = ["re:org\\.apache\\.pekko|pekko\\.", "*"]
# Also fails with ^ anchor:
groups = ["re:^(org\\.apache\\.pekko|pekko\\.)", "*"]
# Also fails with \\.? optional dot:
groups = ["re:^(org\\.apache\\.pekko\\.?|pekko\\.)", "*"]
Root cause analysis
Looking at ImportMatcher.scala, the RE matcher uses:
pattern findPrefixMatchOf i.syntax map (_.end) getOrElse 0
The findPrefixMatchOf method should handle alternation correctly since it uses Java's java.util.regex engine. I verified with a standalone Java test that Pattern.compile("^(org\\.apache\\.pekko\\.?|pekko\\.)").matcher("org.apache.pekko").lookingAt() returns true with end() = 16.
The bug may be in how the HOCON config parser handles the | character in quoted strings, or in how the Regex is constructed from the parsed pattern string. Specifically, the parse function:
case p if p.startsWith("re:") => RE(new Regex(p stripPrefix "re:"))
may produce an incorrectly escaped regex string when | is present in the HOCON value.
Environment
- scalafix version: 0.14.7
- sbt-scalafix version: 0.14.7
- Scala versions tested: 2.13.18, 3.3.x
Workaround
Use two separate group entries instead of regex alternation:
groups = [
"re:org\\.apache\\.pekko",
"pekko.",
"*"
]
This places the imports in adjacent groups (with a blank line between them when using blankLines = Auto), which is not ideal but functional.
Problem
When using regex patterns with the alternation operator
|in theOrganizeImportsgroupsconfiguration, the regex fails to match imports that individual patterns (without alternation) match correctly.Example
Given this
.scalafix.conf:The regex
^(org\.apache\.pekko\.?|pekko\.)should match both:import org.apache.pekko(syntax string:org.apache.pekko)import pekko.actor.Actor(syntax string:pekko.actor.Actor)Expected: Both imports go to group 0.
Actual: Neither import goes to group 0. Both fall through to the
*catch-all group.What works
Each pattern works correctly when used standalone (without alternation):
What doesn't work
Combining them with
|fails:Root cause analysis
Looking at
ImportMatcher.scala, theREmatcher uses:pattern findPrefixMatchOf i.syntax map (_.end) getOrElse 0The
findPrefixMatchOfmethod should handle alternation correctly since it uses Java'sjava.util.regexengine. I verified with a standalone Java test thatPattern.compile("^(org\\.apache\\.pekko\\.?|pekko\\.)").matcher("org.apache.pekko").lookingAt()returnstruewithend() = 16.The bug may be in how the HOCON config parser handles the
|character in quoted strings, or in how theRegexis constructed from the parsed pattern string. Specifically, theparsefunction:may produce an incorrectly escaped regex string when
|is present in the HOCON value.Environment
Workaround
Use two separate group entries instead of regex alternation:
This places the imports in adjacent groups (with a blank line between them when using
blankLines = Auto), which is not ideal but functional.