Code.require_file("../test_helper.exs", __DIR__) defmodule Kernel.ErrorsTest do use ExUnit.Case, async: true import ExUnit.CaptureIO defmacro hello do quote location: :keep do def hello, do: :world end end test "no optional arguments in fn" do assert_eval_raise CompileError, "nofile:1: anonymous functions cannot have optional arguments", 'fn x \\\\ 1 -> x end' assert_eval_raise CompileError, "nofile:1: anonymous functions cannot have optional arguments", 'fn x, y \\\\ 1 -> x + y end' end test "invalid __CALLER__" do assert_eval_raise CompileError, "nofile:1: __CALLER__ is available only inside defmacro and defmacrop", 'defmodule Sample do def hello do __CALLER__ end end' end test "invalid __STACKTRACE__" do assert_eval_raise CompileError, "nofile:1: __STACKTRACE__ is available only inside catch and rescue clauses of try expressions", 'defmodule Sample do def hello do __STACKTRACE__ end end' assert_eval_raise CompileError, "nofile:1: __STACKTRACE__ is available only inside catch and rescue clauses of try expressions", 'defmodule Sample do try do raise "oops" rescue _ -> def hello do __STACKTRACE__ end end end' end test "clause with defaults" do message = ~r"nofile:3: def hello/1 defines defaults multiple times" assert_eval_raise CompileError, message, ~C''' defmodule Kernel.ErrorsTest.ClauseWithDefaults do def hello(_arg \\ 0) def hello(_arg \\ 1) end ''' assert_eval_raise CompileError, message, ~C''' defmodule Kernel.ErrorsTest.ClauseWithDefaults do def hello(_arg \\ 0), do: nil def hello(_arg \\ 1), do: nil end ''' assert_eval_raise CompileError, message, ~C''' defmodule Kernel.ErrorsTest.ClauseWithDefaults do def hello(_arg \\ 0) def hello(_arg \\ 1), do: nil end ''' assert_eval_raise CompileError, message, ~C''' defmodule Kernel.ErrorsTest.ClauseWithDefaults do def hello(_arg \\ 0), do: nil def hello(_arg \\ 1) end ''' assert_eval_raise CompileError, ~r"nofile:4: undefined function foo/0", ~C''' defmodule Kernel.ErrorsTest.ClauseWithDefaults5 do def hello( foo, bar \\ foo() ) def hello(foo, bar), do: foo + bar end ''' end test "different defs with defaults" do assert_eval_raise CompileError, "nofile:3: def hello/3 defaults conflicts with hello/2", ~C''' defmodule Kernel.ErrorsTest.DifferentDefsWithDefaults1 do def hello(a, b \\ nil), do: a + b def hello(a, b \\ nil, c \\ nil), do: a + b + c end ''' assert_eval_raise CompileError, "nofile:3: def hello/2 conflicts with defaults from hello/3", ~C''' defmodule Kernel.ErrorsTest.DifferentDefsWithDefaults2 do def hello(a, b \\ nil, c \\ nil), do: a + b + c def hello(a, b \\ nil), do: a + b end ''' end test "undefined function" do assert_eval_raise CompileError, "hello.ex:4: undefined function bar/0", ''' defmodule Kernel.ErrorsTest.BadForm do @file "hello.ex" def foo do bar() end end ''' assert_eval_raise CompileError, "nofile:2: undefined function module_info/0 (this function is auto-generated by the compiler and must always be called as a remote, as in __MODULE__.module_info/0)", ''' defmodule Kernel.ErrorsTest.Info do def foo, do: module_info() end ''' assert_eval_raise CompileError, "nofile:3: undefined function behaviour_info/1 (this function is auto-generated by the compiler and must always be called as a remote, as in __MODULE__.behaviour_info/1)", ''' defmodule Kernel.ErrorsTest.BehaviourInfo do @callback dummy() :: :ok def foo, do: behaviour_info(:callbacks) end ''' assert capture_io(:stderr, fn -> assert_eval_raise CompileError, "nofile:3: undefined function bar/1", ''' defmodule Kernel.ErrorsTest.BadForm do def foo do bar( baz(1, 2) ) end end ''' end) =~ "undefined function baz/2" assert_eval_raise CompileError, "nofile:8: undefined function baz/0", ''' defmodule Sample do def foo do bar() end defoverridable [foo: 0] def foo do baz() end end ''' end test "undefined non-local function" do assert_eval_raise CompileError, "nofile:1: undefined function call/2", 'call foo, do: :foo' end test "function without definition" do assert_eval_raise CompileError, "nofile:2: implementation not provided for predefined def foo/0", ''' defmodule Kernel.ErrorsTest.FunctionWithoutDefition do def foo end ''' assert_eval_raise CompileError, "nofile:10: implementation not provided for predefined def example/2", ''' defmodule Kernel.ErrorsTest.FunctionTemplate do defmacro __using__(_) do quote do def example(foo, bar \\\\ []) end end end defmodule Kernel.ErrorsTest.UseFunctionTemplate do use Kernel.ErrorsTest.FunctionTemplate end ''' end test "guard without definition" do assert_eval_raise CompileError, "nofile:2: implementation not provided for predefined defmacro foo/1", ''' defmodule Kernel.ErrorsTest.GuardWithoutDefition do defguard foo(bar) end ''' end test "literal on map and struct" do assert_eval_raise CompileError, "nofile:1: expected key-value pairs in a map, got: put_in(foo.bar.baz, nil)", 'foo = 1; %{put_in(foo.bar.baz, nil), foo}' end test "expression after keyword lists" do assert_eval_raise SyntaxError, ~r"unexpected expression after keyword list", 'call foo: 1, :bar' assert_eval_raise SyntaxError, ~r"unexpected expression after keyword list", 'call(foo: 1, :bar)' assert_eval_raise SyntaxError, ~r"unexpected expression after keyword list", '[foo: 1, :bar]' assert_eval_raise SyntaxError, ~r"unexpected expression after keyword list", '%{foo: 1, :bar => :bar}' end test "struct fields on defstruct" do assert_eval_raise ArgumentError, "struct field names must be atoms, got: 1", ''' defmodule Kernel.ErrorsTest.StructFieldsOnDefstruct do defstruct [1, 2, 3] end ''' end test "struct access on body" do assert_eval_raise CompileError, "nofile:3: cannot access struct Kernel.ErrorsTest.StructAccessOnBody, " <> "the struct was not yet defined or the struct " <> "is being accessed in the same context that defines it", ''' defmodule Kernel.ErrorsTest.StructAccessOnBody do defstruct %{name: "Brasilia"} %Kernel.ErrorsTest.StructAccessOnBody{} end ''' end describe "struct errors" do test "bad errors" do assert_eval_raise CompileError, ~r"nofile:1: BadStruct.__struct__/1 is undefined, cannot expand struct BadStruct", '%BadStruct{}' assert_eval_raise CompileError, ~r"nofile:1: BadStruct.__struct__/0 is undefined, cannot expand struct BadStruct", '%BadStruct{} = %{}' bad_struct_type_error = ~r"expected Kernel.ErrorsTest.BadStructType.__struct__/(0|1) to return a map.*, got: :invalid" defmodule BadStructType do def __struct__, do: :invalid def __struct__(_), do: :invalid assert_raise CompileError, bad_struct_type_error, fn -> Macro.struct!(__MODULE__, __ENV__) end end assert_eval_raise CompileError, bad_struct_type_error, '%#{BadStructType}{} = %{}' assert_eval_raise CompileError, bad_struct_type_error, '%#{BadStructType}{}' assert_raise ArgumentError, bad_struct_type_error, fn -> struct(BadStructType) end assert_raise ArgumentError, bad_struct_type_error, fn -> struct(BadStructType, foo: 1) end end test "missing struct key" do missing_struct_key_error = ~r"expected Kernel.ErrorsTest.MissingStructKey.__struct__/(0|1) to return a map.*, got: %\{\}" defmodule MissingStructKey do def __struct__, do: %{} def __struct__(_), do: %{} assert_raise CompileError, missing_struct_key_error, fn -> Macro.struct!(__MODULE__, __ENV__) end end assert_eval_raise CompileError, missing_struct_key_error, '%#{MissingStructKey}{} = %{}' assert_eval_raise CompileError, missing_struct_key_error, '%#{MissingStructKey}{}' assert_raise ArgumentError, missing_struct_key_error, fn -> struct(MissingStructKey) end assert_raise ArgumentError, missing_struct_key_error, fn -> struct(MissingStructKey, foo: 1) end invalid_struct_key_error = ~r"expected Kernel.ErrorsTest.InvalidStructKey.__struct__/(0|1) to return a map.*, got: %\{__struct__: 1\}" defmodule InvalidStructKey do def __struct__, do: %{__struct__: 1} def __struct__(_), do: %{__struct__: 1} assert_raise CompileError, invalid_struct_key_error, fn -> Macro.struct!(__MODULE__, __ENV__) end end assert_eval_raise CompileError, invalid_struct_key_error, '%#{InvalidStructKey}{} = %{}' assert_eval_raise CompileError, invalid_struct_key_error, '%#{InvalidStructKey}{}' assert_raise ArgumentError, invalid_struct_key_error, fn -> struct(InvalidStructKey) end assert_raise ArgumentError, invalid_struct_key_error, fn -> struct(InvalidStructKey, foo: 1) end end test "invalid struct" do invalid_struct_name_error = ~r"expected struct name returned by Kernel.ErrorsTest.InvalidStructName.__struct__/(0|1) to be Kernel.ErrorsTest.InvalidStructName, got: InvalidName" defmodule InvalidStructName do def __struct__, do: %{__struct__: InvalidName} def __struct__(_), do: %{__struct__: InvalidName} assert_raise CompileError, invalid_struct_name_error, fn -> Macro.struct!(__MODULE__, __ENV__) end end assert_eval_raise CompileError, invalid_struct_name_error, '%#{InvalidStructName}{} = %{}' assert_eval_raise CompileError, invalid_struct_name_error, '%#{InvalidStructName}{}' assert_raise ArgumentError, invalid_struct_name_error, fn -> struct(InvalidStructName) end assert_raise ArgumentError, invalid_struct_name_error, fn -> struct(InvalidStructName, foo: 1) end end test "good struct" do defmodule GoodStruct do defstruct name: "john" end assert_eval_raise KeyError, "key :age not found", '%#{GoodStruct}{age: 27}' assert_eval_raise CompileError, "nofile:1: unknown key :age for struct Kernel.ErrorsTest.GoodStruct", '%#{GoodStruct}{age: 27} = %{}' end test "enforce @enforce_keys" do defmodule EnforceKeys do @enforce_keys [:foo] defstruct(foo: nil) end assert_raise ArgumentError, "@enforce_keys required keys ([:fo, :bar]) that are not defined in defstruct: [foo: nil]", fn -> defmodule EnforceKeysError do @enforce_keys [:foo, :fo, :bar] defstruct(foo: nil) end end end end test "name for defmodule" do assert_eval_raise CompileError, "nofile:1: invalid module name: 3", 'defmodule 1 + 2, do: 3' end test "invalid unquote" do assert_eval_raise CompileError, "nofile:1: unquote called outside quote", 'unquote 1' end test "invalid unquote splicing in oneliners" do assert_eval_raise ArgumentError, "unquote_splicing only works inside arguments and block contexts, " <> "wrap it in parens if you want it to work with one-liners", ''' defmodule Kernel.ErrorsTest.InvalidUnquoteSplicingInOneliners do defmacro oneliner2 do quote do: unquote_splicing 1 end def callme do oneliner2 end end ''' end test "invalid attribute" do msg = ~r"cannot inject attribute @foo into function/macro because cannot escape " assert_raise ArgumentError, msg, fn -> defmodule InvalidAttribute do @foo fn -> nil end def bar, do: @foo end end end test "typespec attributes set via Module.put_attribute/4" do message = "attributes type, typep, opaque, spec, callback, and macrocallback " <> "must be set directly via the @ notation" for kind <- [:type, :typep, :opaque, :spec, :callback, :macrocallback] do assert_eval_raise ArgumentError, message, """ defmodule PutTypespecAttribute do Module.put_attribute(__MODULE__, #{inspect(kind)}, {}) end """ end end test "invalid struct field value" do msg = ~r"invalid value for struct field baz, cannot escape " assert_raise ArgumentError, msg, fn -> defmodule InvalidStructFieldValue do defstruct baz: fn -> nil end end end end test "invalid case clauses" do assert_eval_raise CompileError, "nofile:1: expected one argument for :do clauses (->) in \"case\"", 'case nil do 0, z when not is_nil(z) -> z end' end test "invalid fn args" do assert_eval_raise TokenMissingError, "nofile:1:5: missing terminator: end (for \"fn\" starting at line 1)", 'fn 1' end test "invalid escape" do assert_eval_raise TokenMissingError, "nofile:1:3: invalid escape \\ at end of file", '1 \\' end test "function local conflict" do assert_eval_raise CompileError, "nofile:3: imported Kernel.&&/2 conflicts with local function", ''' defmodule Kernel.ErrorsTest.FunctionLocalConflict do def other, do: 1 && 2 def _ && _, do: :error end ''' end test "macro local conflict" do assert_eval_raise CompileError, "nofile:6: call to local macro &&/2 conflicts with imported Kernel.&&/2, " <> "please rename the local macro or remove the conflicting import", ''' defmodule Kernel.ErrorsTest.MacroLocalConflict do def hello, do: 1 || 2 defmacro _ || _, do: :ok defmacro _ && _, do: :error def world, do: 1 && 2 end ''' end test "macro with undefined local" do assert_eval_raise UndefinedFunctionError, "function Kernel.ErrorsTest.MacroWithUndefinedLocal.unknown/1" <> " is undefined (function not available)", ''' defmodule Kernel.ErrorsTest.MacroWithUndefinedLocal do defmacrop bar, do: unknown(1) def baz, do: bar() end ''' end test "private macro" do assert_eval_raise UndefinedFunctionError, "function Kernel.ErrorsTest.PrivateMacro.foo/0 is undefined (function not available)", ''' defmodule Kernel.ErrorsTest.PrivateMacro do defmacrop foo, do: 1 defmacro bar, do: __MODULE__.foo() defmacro baz, do: bar() end ''' end test "macro invoked before its definition" do assert_eval_raise CompileError, ~r"nofile:2: cannot invoke macro bar/0 before its definition", ''' defmodule Kernel.ErrorsTest.IncorrectMacroDispatch do def foo, do: bar() defmacro bar, do: :bar end ''' assert_eval_raise CompileError, ~r"nofile:2: cannot invoke macro bar/0 before its definition", ''' defmodule Kernel.ErrorsTest.IncorrectMacropDispatch do def foo, do: bar() defmacrop bar, do: :ok end ''' assert_eval_raise CompileError, ~r"nofile:2: cannot invoke macro bar/1 before its definition", ''' defmodule Kernel.ErrorsTest.IncorrectMacroDispatch do defmacro bar(a) when is_atom(a), do: bar([a]) end ''' end test "macro captured before its definition" do assert_eval_raise CompileError, ~r"nofile:3: cannot invoke macro is_ok/1 before its definition", ''' defmodule Kernel.ErrorsTest.IncorrectMacroDispatch.Capture do def foo do predicate = &is_ok/1 Enum.any?([:ok, :error, :foo], predicate) end defmacro is_ok(atom), do: atom == :ok end ''' end test "function definition with alias" do assert_eval_raise CompileError, "nofile:2: function names should start with lowercase characters or underscore, invalid name Bar", ''' defmodule Kernel.ErrorsTest.FunctionDefinitionWithAlias do def Bar do :baz end end ''' end test "function import conflict" do assert_eval_raise CompileError, "nofile:3: function exit/1 imported from both :erlang and Kernel, call is ambiguous", ''' defmodule Kernel.ErrorsTest.FunctionImportConflict do import :erlang, only: [exit: 1], warn: false def foo, do: exit(:test) end ''' end test "duplicated function on import options" do assert_eval_raise CompileError, "nofile:2: invalid :only option for import, flatten/1 is duplicated", ''' defmodule Kernel.ErrorsTest.DuplicatedFunctionOnImportOnly do import List, only: [flatten: 1, keyfind: 4, flatten: 1] end ''' assert_eval_raise CompileError, "nofile:2: invalid :except option for import, flatten/1 is duplicated", ''' defmodule Kernel.ErrorsTest.DuplicatedFunctionOnImportExcept do import List, except: [flatten: 1, keyfind: 4, flatten: 1] end ''' end test "ensure valid import :only option" do assert_eval_raise CompileError, "nofile:3: invalid :only option for import, expected value to be an atom " <> ":functions, :macros, or a list literal, got: x", ''' defmodule Kernel.ErrorsTest.Only do x = [flatten: 1] import List, only: x end ''' end test "ensure valid import :except option" do assert_eval_raise CompileError, "nofile:3: invalid :except option for import, expected value to be a list " <> "literal, got: Module.__get_attribute__(Kernel.ErrorsTest.Only, :x, 3)", ''' defmodule Kernel.ErrorsTest.Only do @x [flatten: 1] import List, except: @x end ''' end test "unrequired macro" do assert_eval_raise CompileError, "nofile:2: you must require Kernel.ErrorsTest before invoking " <> "the macro Kernel.ErrorsTest.hello/0", ''' defmodule Kernel.ErrorsTest.UnrequiredMacro do Kernel.ErrorsTest.hello() end ''' end test "def defmacro clause change" do assert_eval_raise CompileError, "nofile:3: defmacro foo/1 already defined as def in nofile:2", ''' defmodule Kernel.ErrorsTest.DefDefmacroClauseChange do def foo(1), do: 1 defmacro foo(x), do: x end ''' end test "def defp clause change from another file" do assert_eval_raise CompileError, ~r"nofile:4: def hello/0 already defined as defp", ''' defmodule Kernel.ErrorsTest.DefDefmacroClauseChange do require Kernel.ErrorsTest defp hello, do: :world Kernel.ErrorsTest.hello() end ''' end test "internal function overridden" do assert_eval_raise CompileError, "nofile:2: cannot define def __info__/1 as it is automatically defined by Elixir", ''' defmodule Kernel.ErrorsTest.InternalFunctionOverridden do def __info__(_), do: [] end ''' end test "no macros" do assert_eval_raise CompileError, "nofile:2: could not load macros from module :lists", ''' defmodule Kernel.ErrorsTest.NoMacros do import :lists, only: :macros end ''' end test "invalid macro" do assert_eval_raise CompileError, ~r"nofile: invalid quoted expression: {:foo, :bar, :baz, :bat}", ''' defmodule Kernel.ErrorsTest.InvalidMacro do defmacrop oops do {:foo, :bar, :baz, :bat} end def test, do: oops() end ''' end test "unloaded module" do assert_eval_raise CompileError, "nofile:1: module Certainly.Doesnt.Exist is not loaded and could not be found", 'import Certainly.Doesnt.Exist' end test "module imported from the context it was defined in" do assert_eval_raise CompileError, ~r"nofile:4: module Kernel.ErrorsTest.ScheduledModule.Hygiene is not loaded but was defined.", ''' defmodule Kernel.ErrorsTest.ScheduledModule do defmodule Hygiene do end import Kernel.ErrorsTest.ScheduledModule.Hygiene end ''' end test "module imported from the same module" do assert_eval_raise CompileError, ~r"nofile:3: you are trying to use the module Kernel.ErrorsTest.ScheduledModule.Hygiene which is currently being defined", ''' defmodule Kernel.ErrorsTest.ScheduledModule do defmodule Hygiene do import Kernel.ErrorsTest.ScheduledModule.Hygiene end end ''' end test "already compiled module" do assert_eval_raise ArgumentError, "could not call Module.eval_quoted/4 because the module Record is already compiled", 'Module.eval_quoted Record, quote(do: 1), [], file: __ENV__.file' end test "@compile inline with undefined function" do assert_eval_raise CompileError, "nofile:1: inlined function foo/1 undefined", 'defmodule Test do @compile {:inline, foo: 1} end' end test "invalid @dialyzer options" do assert_eval_raise CompileError, "nofile:1: undefined function foo/1 given to @dialyzer :nowarn_function", 'defmodule Test do @dialyzer {:nowarn_function, {:foo, 1}} end' assert_eval_raise CompileError, "nofile:1: undefined function foo/1 given to @dialyzer :no_opaque", 'defmodule Test do @dialyzer {:no_opaque, {:foo, 1}} end' assert_eval_raise ArgumentError, "invalid value for @dialyzer attribute: :not_an_option", 'defmodule Test do @dialyzer :not_an_option end' end test "@on_load attribute format" do assert_raise ArgumentError, ~r/should be an atom or a {atom, 0} tuple/, fn -> defmodule BadOnLoadAttribute do Module.put_attribute(__MODULE__, :on_load, "not an atom") end end end test "duplicated @on_load attribute" do assert_raise ArgumentError, "the @on_load attribute can only be set once per module", fn -> defmodule DuplicatedOnLoadAttribute do @on_load :foo @on_load :bar end end end test "@on_load attribute with undefined function" do assert_eval_raise CompileError, "nofile:1: @on_load function foo/0 is undefined", 'defmodule UndefinedOnLoadFunction do @on_load :foo end' end test "wrong kind for @on_load attribute" do assert_eval_raise CompileError, "nofile:1: expected @on_load function foo/0 to be a function, " <> "got \"defmacro\"", ''' defmodule PrivateOnLoadFunction do @on_load :foo defmacro foo, do: :ok end ''' end test "in definition module" do assert_eval_raise CompileError, "nofile:2: cannot define module Kernel.ErrorsTest.InDefinitionModule " <> "because it is currently being defined in nofile:1", ''' defmodule Kernel.ErrorsTest.InDefinitionModule do defmodule Elixir.Kernel.ErrorsTest.InDefinitionModule, do: true end ''' end test "invalid definition" do assert_eval_raise CompileError, "nofile:1: invalid syntax in def 1.(hello)", 'defmodule Kernel.ErrorsTest.InvalidDefinition, do: (def 1.(hello), do: true)' end test "invalid size in bitstrings" do assert_eval_raise CompileError, "nofile:1: cannot use ^x outside of match clauses", 'x = 8; <> = <>' end test "function head with guard" do assert_eval_raise CompileError, "nofile:2: missing :do option in \"def\"", ''' defmodule Kernel.ErrorsTest.BodyessFunctionWithGuard do def foo(n) when is_number(n) end ''' assert_eval_raise CompileError, "nofile:2: missing :do option in \"def\"", ''' defmodule Kernel.ErrorsTest.BodyessFunctionWithGuard do def foo(n) when is_number(n), true end ''' end test "invalid args for function head" do assert_eval_raise CompileError, ~r"nofile:2: only variables and \\\\ are allowed as arguments in function head.", ''' defmodule Kernel.ErrorsTest.InvalidArgsForBodylessClause do def foo(nil) def foo(_), do: :ok end ''' end test "bad multi-call" do assert_eval_raise CompileError, "nofile:1: invalid argument for alias, expected a compile time atom or alias, got: 42", 'alias IO.{ANSI, 42}' assert_eval_raise CompileError, "nofile:1: :as option is not supported by multi-alias call", 'alias Elixir.{Map}, as: Dict' assert_eval_raise UndefinedFunctionError, "function List.\"{}\"/1 is undefined or private", '[List.{Chars}, "one"]' end test "macros error stacktrace" do assert [ {:erlang, :+, [1, :foo], _}, {Kernel.ErrorsTest.MacrosErrorStacktrace, :sample, 1, _} | _ ] = rescue_stacktrace(""" defmodule Kernel.ErrorsTest.MacrosErrorStacktrace do defmacro sample(num), do: num + :foo def other, do: sample(1) end """) end test "macros function clause stacktrace" do assert [{__MODULE__, :sample, 1, _} | _] = rescue_stacktrace(""" defmodule Kernel.ErrorsTest.MacrosFunctionClauseStacktrace do import Kernel.ErrorsTest sample(1) end """) end test "macros interpreted function clause stacktrace" do assert [{Kernel.ErrorsTest.MacrosInterpretedFunctionClauseStacktrace, :sample, 1, _} | _] = rescue_stacktrace(""" defmodule Kernel.ErrorsTest.MacrosInterpretedFunctionClauseStacktrace do defmacro sample(0), do: 0 def other, do: sample(1) end """) end test "macros compiled callback" do assert [{Kernel.ErrorsTest, :__before_compile__, [env], _} | _] = rescue_stacktrace(""" defmodule Kernel.ErrorsTest.MacrosCompiledCallback do Module.put_attribute(__MODULE__, :before_compile, Kernel.ErrorsTest) end """) assert %Macro.Env{module: Kernel.ErrorsTest.MacrosCompiledCallback} = env end test "failed remote call stacktrace includes file/line info" do try do bad_remote_call(1) rescue ArgumentError -> assert [ {:erlang, :apply, [1, :foo, []], _}, {__MODULE__, :bad_remote_call, 1, [file: _, line: _]} | _ ] = __STACKTRACE__ end end test "def fails when rescue, else or catch don't have clauses" do assert_eval_raise CompileError, ~r"expected -> clauses for :rescue in \"def\"", """ defmodule Example do def foo do bar() rescue baz() end end """ end test "duplicate map keys" do assert_eval_raise CompileError, "nofile:1: key :a will be overridden in map", """ %{a: :b, a: :c} = %{a: :c} """ assert_eval_raise CompileError, "nofile:1: key :a will be overridden in map", """ %{a: :b, a: :c, a: :d} = %{a: :c} """ end test "| outside of cons" do assert_eval_raise CompileError, ~r"nofile:1: misplaced operator |/2", "1 | 2" assert_eval_raise CompileError, ~r"nofile:1: misplaced operator |/2", "defmodule MisplacedOperator, do: (def bar(1 | 2), do: :ok)" end defp bad_remote_call(x), do: x.foo defmacro sample(0), do: 0 defmacro before_compile(_) do quote(do: _) end ## Helpers defp assert_eval_raise(given_exception, given_message, string) do assert_raise given_exception, given_message, fn -> Code.eval_string(string) end end defp rescue_stacktrace(string) do try do Code.eval_string(string) nil rescue _ -> __STACKTRACE__ else _ -> flunk("Expected expression to fail") end end end