Skip to content

Commit 9b0353a

Browse files
author
José Valim
committed
Improve error messages when there is a space in between function name and parenthesis
1 parent b6cb6ca commit 9b0353a

File tree

5 files changed

+33
-9
lines changed

5 files changed

+33
-9
lines changed

lib/elixir/src/elixir_aliases.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ expand_one(H, Aliases) ->
6868
ensure_loaded(Line, Ref, S) ->
6969
ensure_loaded(Line, S#elixir_scope.file, Ref, S#elixir_scope.context_modules).
7070

71-
ensure_loaded(_Line, _File, 'Elixir.Kernel', FileModules) ->
71+
ensure_loaded(_Line, _File, 'Elixir.Kernel', _FileModules) ->
7272
ok;
7373

7474
ensure_loaded(Line, File, Ref, FileModules) ->

lib/elixir/src/elixir_parser.yrl

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ Nonterminals
1010
open_curly close_curly
1111
open_bit close_bit
1212
base_comma_expr comma_expr optional_comma_expr matched_comma_expr
13-
call_args call_args_parens call_args_parens_not_one call_args_no_parens parens_call
13+
call_args call_args_parens parens_call
14+
call_args_no_parens call_args_no_parens_strict call_args_parens_not_one
1415
stab stab_eol stab_op stab_expr stab_maybe_expr
1516
kw_eol kw_expr kw_comma kw_base
1617
matched_kw_expr matched_kw_comma matched_kw_base
@@ -142,16 +143,16 @@ matched_op_expr -> comp_expr_op matched_expr : { '$1', '$2' }.
142143

143144
block_expr -> parens_call call_args_parens do_block : build_identifier('$1', '$2' ++ '$3').
144145
block_expr -> parens_call call_args_parens call_args_parens do_block : build_nested_parens('$1', '$2', '$3' ++ '$4').
145-
block_expr -> dot_punctuated_identifier call_args_no_parens do_block : build_identifier('$1', '$2' ++ '$3').
146+
block_expr -> dot_punctuated_identifier call_args_no_parens_strict do_block : build_identifier('$1', '$2' ++ '$3').
146147
block_expr -> dot_do_identifier do_block : build_identifier('$1', '$2').
147-
block_expr -> dot_identifier call_args_no_parens do_block : build_identifier('$1', '$2' ++ '$3').
148+
block_expr -> dot_identifier call_args_no_parens_strict do_block : build_identifier('$1', '$2' ++ '$3').
148149

149150
fn_expr -> fn_eol stab end_eol : build_fn('$1', build_stab(lists:reverse('$2'))).
150151
fn_expr -> call_expr : '$1'.
151152

152-
call_expr -> dot_punctuated_identifier call_args_no_parens : build_identifier('$1', '$2').
153-
call_expr -> dot_op_identifier call_args_no_parens : build_identifier('$1', '$2').
154-
call_expr -> dot_identifier call_args_no_parens : build_identifier('$1', '$2').
153+
call_expr -> dot_punctuated_identifier call_args_no_parens_strict : build_identifier('$1', '$2').
154+
call_expr -> dot_op_identifier call_args_no_parens_strict : build_identifier('$1', '$2').
155+
call_expr -> dot_identifier call_args_no_parens_strict : build_identifier('$1', '$2').
155156
call_expr -> dot_punctuated_identifier : build_identifier('$1', []).
156157
call_expr -> dot_do_identifier : build_identifier('$1', nil).
157158
call_expr -> var : build_identifier('$1', nil).
@@ -388,6 +389,11 @@ parens_call -> matched_expr dot_call_op : { '.', [{line,?line('$2')}], ['$1'] }.
388389
matched_comma_expr -> matched_expr : ['$1'].
389390
matched_comma_expr -> matched_comma_expr ',' matched_expr : ['$3'|'$1'].
390391

392+
call_args_no_parens_strict -> call_args_no_parens : '$1'.
393+
call_args_no_parens_strict -> open_paren ')' : throw_no_parens_strict('$1').
394+
call_args_no_parens_strict -> open_paren matched_kw_base close_paren : throw_no_parens_strict('$1').
395+
call_args_no_parens_strict -> open_paren matched_expr ',' call_args_no_parens close_paren : throw_no_parens_strict('$1').
396+
391397
call_args_no_parens -> matched_comma_expr : lists:reverse('$1').
392398
call_args_no_parens -> matched_kw_base : ['$1'].
393399
call_args_no_parens -> matched_comma_expr ',' matched_kw_base : lists:reverse(['$3'|'$1']).
@@ -584,3 +590,13 @@ build_stab([H|T], Marker, Temp, Acc) ->
584590
build_stab([], Marker, Temp, Acc) ->
585591
H = { Marker, build_block(lists:reverse(Temp)) },
586592
lists:reverse([H|Acc]).
593+
594+
%% Errors
595+
596+
throw(Line, Error, Token) ->
597+
throw({ error, { Line, ?MODULE, [Error, Token] }}).
598+
599+
throw_no_parens_strict(Token) ->
600+
throw(?line(Token), "invalid comma inside parenthesis. If you are making a "
601+
"function call, do not insert spaces in between the function name and the "
602+
"opening parentheses. Syntax error before: ", ")").

lib/elixir/src/elixir_translator.erl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
forms(String, StartLine, File, Opts) ->
1515
try elixir_tokenizer:tokenize(String, StartLine, [{ file, File }|Opts]) of
1616
{ ok, Tokens } ->
17-
case elixir_parser:parse(Tokens) of
17+
try elixir_parser:parse(Tokens) of
1818
{ ok, Forms } -> { ok, Forms };
1919
{ error, { Line, _, [Error, Token] } } -> { error, { Line, Error, Token } }
20+
catch
21+
{ error, { Line, _, [Error, Token] } } -> { error, { Line, Error, Token } }
2022
end;
2123
{ error, { _, _, _ } } = Else -> Else
2224
catch

lib/elixir/test/elixir/kernel/errors_test.exs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ defmodule Kernel.ErrorsTest do
4343
assert "nofile:1: syntax error before: '.'" == format_rescue '+.foo'
4444
end
4545

46+
test :syntax_error_on_parens_call do
47+
assert "nofile:1: invalid comma inside parenthesis. If you are making a function call, " <>
48+
"do not insert spaces in between the function name and the opening parentheses. " <>
49+
"Syntax error before: )" == format_rescue 'foo (hello, world)'
50+
end
51+
4652
test :syntax_error_with_no_token do
4753
assert "nofile:1: missing terminator: ) (for \"(\" starting at line 1)" == format_rescue 'case 1 ('
4854
end

lib/elixir/test/erlang/translator_test.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ oror_test() ->
107107
false = eval([{'||', [{line,1}], [false, false]}]),
108108
true = eval([{'||', [{line,1}], [true, {error, [{line,1}], [omg]}]}]).
109109

110-
%% Method calls
110+
%% Function calls
111111

112112
local_call_test() ->
113113
42.0 = eval([{float, [{line,1}], [42]}]).

0 commit comments

Comments
 (0)