Skip to content

Only the outermost match in a pipe chain is reported #3

Description

@mtarnovan

ex_ast 0.12.0, Elixir 1.18.4 / OTP 27.

Repro

source = """
conn
|> assert_has(".a", checked: true)
|> assert_has(".b", checked: true)
"""

ExAST.Patcher.find_all(source, "assert_has(_, _, checked: _)")
# => 1 match (line 3)

Expected 2 matches (lines 2 and 3). Same behavior through mix ex_ast.search.

What seems to happen

With pipe normalization, the line-3 call's first argument contains the line-2 call (assert_has(assert_has(conn, ".a", ...), ".b", ...)), and only the outermost matching node is reported — inner matches nested inside an already-matched node are skipped.

Why it matters

Long |> chains are the dominant style in Phoenix test suites. We used ex_ast to audit a real suite for a misused option and it reported 9 sites where there were actually 12 — the 3 missing ones were earlier stages of pipe chains whose later stage also matched. An undercount is risky for exactly the audit/replace workflows the tool is built for.

If this is intentional overlapping-match suppression, it would be good to document it and/or offer an option to include nested matches; for pipe chains specifically, each stage feels like a distinct match to a user.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions