Skip to content

Warn on parentheses in query field access#4746

Merged
josevalim merged 2 commits into
elixir-ecto:masterfrom
arpitjain099:chore/warn-parens-field-access
Jul 7, 2026
Merged

Warn on parentheses in query field access#4746
josevalim merged 2 commits into
elixir-ecto:masterfrom
arpitjain099:chore/warn-parens-field-access

Conversation

@arpitjain099

Copy link
Copy Markdown
Contributor

Closes #4588. Writing a field access with empty parentheses like q.title() is currently accepted and behaves exactly like q.title, which is almost always a typo. Per josevalim's note on the issue ("we should definitely warn and then convert to an error in the future"), this warns instead of raising for now.

The two forms only differ by no_parens: true on the outer call metadata (confirmed in the thread), so the escape clause now binds that metadata and emits a deprecation warning via IO.warn/2 when it is absent, then proceeds unchanged. Added a builder test asserting the warning fires for x.y() and stays quiet for x.y.

One heads-up: I don't have an Elixir toolchain on this machine, so I verified by code-read rather than running mix test locally, and I am counting on CI here. Also, a handful of existing builder tests use the parenthesized form (x.y()), so they will now print this warning during the run without failing; happy to follow up and quiet those if you would like.

A field access written with empty parentheses such as q.title() is
silently accepted and treated identically to q.title. The two only
differ by the no_parens: true metadata on the outer call, so bind that
metadata and emit a deprecation warning when it is absent, then proceed
as before. Closes elixir-ecto#4588.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
@greg-rychlewski

Copy link
Copy Markdown
Member

Thanks for the PR @arpitjain099. I think we have a bunch of tests that unfortunately trigger this warning. If you run locally you will see a lot of these

Warning:   test/ecto/query/builder/distinct_test.exs:19: Ecto.Query.Builder.DistinctTest."test escape handles expressions and params"/1

warning: using parentheses after a field access, such as `x.x()`, is deprecated and will raise in future Ecto versions. Remove the parentheses to keep the current behaviour: `x.x`

and the test is like this

 assert {Macro.escape(quote(do: [asc: &0.x(), asc: &1.y()])), {[], %{}}} ==
               escape(quote(do: [x.x(), y.y()]), {[], %{}}, [x: 0, y: 1], __ENV__)

Would you have time to change the tests as well? If not it's ok I can do a cleanup PR right after.

The new deprecation warning for parenthesized query field access fired
across the builder test suite, since many escape/1 cases wrote fields as
x.x() instead of x.x on the input side. Drop the empty parentheses so the
tests exercise the same expressions without emitting the warning. The
escaped output is identical either way, so the assertions are unchanged.
The intentional case in builder_test.exs that verifies the warning keeps
its parentheses.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
@arpitjain099

Copy link
Copy Markdown
Contributor Author

Thanks @greg-rychlewski, happy to. I went through the builder tests and dropped the empty parens from the field accesses that were emitting the warning (distinct, filter, group_by, order_by, select, update, windows, and the main builder_test). Those were all on the escape/1 input side, and since the escaped output is the same either way the assertions didn't need to change. I left the parens on the one case in builder_test that intentionally checks the warning is raised.

Ran the full suite locally and it's green again with no more using parentheses warnings. Let me know if you'd rather I split the test cleanup into its own commit or anything else.

@josevalim josevalim merged commit ca66f38 into elixir-ecto:master Jul 7, 2026
8 checks passed
@josevalim

Copy link
Copy Markdown
Member

💚 💙 💜 💛 ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ecto allows parentheses in field names without raising an error

3 participants