Skip to content

OrganizeImports: regex alternation (|) in groups config doesn't match imports correctly #2477

Description

@He-Pin

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions