Skip to content

Fix multiline function signature parsing #580

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/julia/parser.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2197,7 +2197,15 @@ function parse_function_signature(ps::ParseState, is_function::Bool)
is_empty_tuple = peek(ps, skip_newlines=true) == K")"
opts = parse_brackets(ps, K")") do had_commas, had_splat, num_semis, num_subexprs
_parsed_call = was_eventually_call(ps)
_needs_parse_call = peek(ps, 2) ∈ KSet"( ."
# Check if we should skip newlines - only for specific cases
# where we have a single type annotation like (::T)
_skip_newlines = !had_commas && num_subexprs == 1 &&
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll be honest in that I don't really know what is going on here...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same condition as the maybe_grouping_parens below - should be refactored if that's intended.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the odd thing about this is that it needs to ignore whitespace before the first peek token, but not the second one. I don't know that these conditions here make any sense. We don't have a peek api like that, but I think that's what's needed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the correct solution is to move the _needs_parse_call outside the do block - it seems weird that it would affect needs_parameters, because if there are parameters, the peek will never actually see the parenthesis.

!had_splat && num_semis == 0
_needs_parse_call = if _skip_newlines
peek(ps, 2, skip_newlines=true) ∈ KSet"( ."
else
peek(ps, 2) ∈ KSet"( ."
end
_is_anon_func = (!_needs_parse_call && !_parsed_call) || had_commas
return (needs_parameters = _is_anon_func,
is_anon_func = _is_anon_func,
Expand Down
5 changes: 5 additions & 0 deletions test/parser.jl
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,11 @@ tests = [
"function (::g(x))() end" => "(function (call (parens (::-pre (call g x)))) (block))"
"function (f::T{g(i)})() end" => "(function (call (parens (::-i f (curly T (call g i))))) (block))"
"function (::T)() end" => "(function (call (parens (::-pre T))) (block))"
"function (\n ::T\n )() end" => "(function (call (parens (::-pre T))) (block))"
"function (\n x::T\n )() end" => "(function (call (parens (::-i x T))) (block))"
"function (\n ::T\n )(x, y) end" => "(function (call (parens (::-pre T)) x y) (block))"
"function (\n f::T{g(i)}\n )() end" => "(function (call (parens (::-i f (curly T (call g i))))) (block))"
"function (\n x, y\n ) x + y end" => "(function (tuple-p x y) (block (call-i x + y)))"
"function (:*=(f))() end" => "(function (call (parens (call (quote-: *=) f))) (block))"
"function begin() end" => "(function (call (error begin)) (block))"
"function f() end" => "(function (call f) (block))"
Expand Down
Loading