Skip to content

Commit 4b317a7

Browse files
author
José Valim
committed
Save typespecs attributes with proper line numbers, closes #1613
1 parent 2977a46 commit 4b317a7

File tree

3 files changed

+29
-6
lines changed

3 files changed

+29
-6
lines changed

lib/elixir/src/elixir_errors.erl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ handle_file_error(File, {Line,erl_lint,{unsafe_var,Var,{In,_Where}}}) ->
169169
Message = io_lib:format("cannot define variable ~ts inside ~ts", [format_var(Var), Translated]),
170170
raise(Line, File, 'Elixir.CompileError', iolist_to_binary(Message));
171171

172+
handle_file_error(File, {Line,erl_lint,{spec_fun_undefined,{M,F,A}}}) ->
173+
Message = io_lib:format("spec for undefined function ~ts.~ts/~B", [inspect(M), F, A]),
174+
raise(Line, File, 'Elixir.CompileError', iolist_to_binary(Message));
175+
172176
handle_file_error(File, {Line,Module,Desc}) ->
173177
form_error(Line, File, Module, Desc).
174178

lib/elixir/src/elixir_module.erl

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ compile(Line, Module, Block, Vars, #elixir_scope{context_modules=FileModules} =
6868
{ Base, Export, Private, Def, Defmacro, Functions } = elixir_def:unwrap_stored_definitions(FileList, Module),
6969

7070
{ All, Forms0 } = functions_form(Line, File, Module, Base, Export, Def, Defmacro, Functions, C),
71-
Forms1 = specs_form(Line, Module, Private, Defmacro, Forms0, C),
71+
Forms1 = specs_form(Module, Private, Defmacro, Forms0, C),
7272
Forms2 = attributes_form(Line, File, Module, Forms1),
7373
Forms3 = typedocs_form(Module, Forms2),
7474

@@ -213,7 +213,7 @@ typedocs_form(Module, Current) ->
213213

214214
%% Specs
215215

216-
specs_form(Line, Module, Private, Defmacro, Forms, C) ->
216+
specs_form(Module, Private, Defmacro, Forms, C) ->
217217
Defmacrop = [Tuple || { Tuple, defmacrop, _, _, _ } <- Private],
218218
case elixir_compiler:get_opt(internal, C) of
219219
true -> Forms;
@@ -225,16 +225,17 @@ specs_form(Line, Module, Private, Defmacro, Forms, C) ->
225225
'Elixir.Module':delete_attribute(Module, spec),
226226
'Elixir.Module':delete_attribute(Module, callback),
227227

228-
Temp = specs_attributes(Line, spec, Forms, Specs),
229-
specs_attributes(Line, callback, Temp, Callbacks)
228+
Temp = specs_attributes(spec, Forms, Specs),
229+
specs_attributes(callback, Temp, Callbacks)
230230
end.
231231

232-
specs_attributes(Line, Type, Forms, Specs) ->
232+
specs_attributes(Type, Forms, Specs) ->
233233
Keys = lists:foldl(fun({ Tuple, Value }, Acc) ->
234-
lists:keystore(Tuple, 1, Acc, { Tuple, Value } )
234+
lists:keystore(Tuple, 1, Acc, { Tuple, Value })
235235
end, [], Specs),
236236
lists:foldl(fun({ Tuple, _ }, Acc) ->
237237
Values = [V || { K, V } <- Specs, K == Tuple],
238+
{ type, Line, _, _ } = hd(Values),
238239
[{ attribute, Line, Type, { Tuple, Values } }|Acc]
239240
end, Forms, Keys).
240241

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,24 @@ defmodule Kernel.ErrorsTest do
575575
'case [] do; [] when Hello.something_that_does_not_exist == [] -> :ok; end'
576576
end
577577

578+
test :typespec_errors do
579+
assert_compile_fail CompileError,
580+
"nofile:2: type foo() undefined",
581+
'''
582+
defmodule Example do
583+
@type omg :: foo
584+
end
585+
'''
586+
587+
assert_compile_fail CompileError,
588+
"nofile:2: spec for undefined function Example.omg/0",
589+
'''
590+
defmodule Example do
591+
@spec omg :: atom
592+
end
593+
'''
594+
end
595+
578596
test :macros_error_stacktrace do
579597
assert [{:erlang, :+, [1, :foo], _}, {ErrorsTest, :sample, 1, _}|_] =
580598
rescue_stacktrace(""")

0 commit comments

Comments
 (0)