diff --git a/lib/elixir/lib/file.ex b/lib/elixir/lib/file.ex index 23cc854db4..15687946ce 100644 --- a/lib/elixir/lib/file.ex +++ b/lib/elixir/lib/file.ex @@ -308,11 +308,15 @@ defmodule File do def touch(path, time \\ :calendar.local_time) do path = IO.chardata_to_string(path) case F.change_time(path, time) do - {:error, :enoent} -> - write(path, "") - F.change_time(path, time) - other -> - other + {:error, :enoent} -> touch_new(path, time) + other -> other + end + end + + defp touch_new(path, time) do + case write(path, "", [:append]) do + :ok -> F.change_time(path, time) + {:error, _reason} = error -> error end end @@ -548,7 +552,8 @@ defmodule File do [dest|acc] {:error, :eexist} -> if callback.(src, dest) do - rm(dest) + # If rm/1 fails, copy/2 will fail + _ = rm(dest) case copy(src, dest) do {:ok, _} -> copy_file_mode!(src, dest) @@ -569,7 +574,8 @@ defmodule File do [dest|acc] {:error, :eexist} -> if callback.(src, dest) do - rm(dest) + # If rm/1 fails, iF.make_symlink/2 will fail + _ = rm(dest) case F.make_symlink(link, dest) do :ok -> [dest|acc] {:error, reason} -> {:error, reason, src} @@ -665,14 +671,20 @@ defmodule File do if match? {:win32, _}, :os.type do case F.read_file_info(IO.chardata_to_string(path)) do {:ok, file_info} when elem(file_info, 3) in [:read, :none] -> - File.chmod(path, (elem(file_info, 7) + 0200)) - F.delete(path) + change_mode_windows(path, file_info) _ -> nil end end end + defp change_mode_windows(path, file_info) do + case File.chmod(path, (elem(file_info, 7) + 0200)) do + :ok -> F.delete(path) + {:error, _reason} = error -> error + end + end + @doc """ Same as `rm/1`, but raises an exception in case of failure. Otherwise `:ok`. """ diff --git a/lib/elixir/lib/file/stream.ex b/lib/elixir/lib/file/stream.ex index 6cb91337f2..1a019a95fe 100644 --- a/lib/elixir/lib/file/stream.ex +++ b/lib/elixir/lib/file/stream.ex @@ -57,10 +57,14 @@ defmodule File.Stream do false -> IO.write(device, x) end :ok, :done -> - :file.close(device) + # If delayed_write option is used and the last write failed will + # MatchError here as {:error, _} is returned. + :ok = :file.close(device) stream :ok, :halt -> - :file.close(device) + # If delayed_write option is used and the last write failed will + # MatchError here as {:error, _} is returned. + :ok = :file.close(device) end end end diff --git a/lib/elixir/lib/gen_event.ex b/lib/elixir/lib/gen_event.ex index f18f7a0083..984d728591 100644 --- a/lib/elixir/lib/gen_event.ex +++ b/lib/elixir/lib/gen_event.ex @@ -397,7 +397,7 @@ defmodule GenEvent do def cancel_streams(%GenEvent{manager: manager, id: id}) do handlers = :gen_event.which_handlers(manager) - for {Enumerable.GenEvent, {handler_id, _}} = ref <- handlers, + _ = for {Enumerable.GenEvent, {handler_id, _}} = ref <- handlers, handler_id === id do :gen_event.delete_handler(manager, ref, :remove_handler) end diff --git a/lib/elixir/lib/kernel/cli.ex b/lib/elixir/lib/kernel/cli.ex index f88dbb47d7..d391f8a2f3 100644 --- a/lib/elixir/lib/kernel/cli.ex +++ b/lib/elixir/lib/kernel/cli.ex @@ -363,7 +363,8 @@ defmodule Kernel.CLI do end defp process_command({:compile, patterns}, config) do - :filelib.ensure_dir(:filename.join(config.output, ".")) + # If ensuring the dir returns an error no files will be found. + _ = :filelib.ensure_dir(:filename.join(config.output, ".")) case filter_multiple_patterns(patterns) do {:ok, []} -> diff --git a/lib/elixir/lib/kernel/error_handler.ex b/lib/elixir/lib/kernel/error_handler.ex index dfc1dbb58e..64bd39f72e 100644 --- a/lib/elixir/lib/kernel/error_handler.ex +++ b/lib/elixir/lib/kernel/error_handler.ex @@ -25,7 +25,7 @@ defmodule Kernel.ErrorHandler do defp ensure_loaded(module) do case Code.ensure_loaded(module) do - {:module, _} -> [] + {:module, _} -> :ok {:error, _} -> parent = :erlang.get(:elixir_compiler_pid) ref = :erlang.make_ref diff --git a/lib/elixir/lib/kernel/parallel_compiler.ex b/lib/elixir/lib/kernel/parallel_compiler.ex index 754dd9bbd4..1ca097dc07 100644 --- a/lib/elixir/lib/kernel/parallel_compiler.ex +++ b/lib/elixir/lib/kernel/parallel_compiler.ex @@ -43,7 +43,7 @@ defmodule Kernel.ParallelCompiler do end defp spawn_compilers(files, path, callbacks) do - Code.ensure_loaded(Kernel.ErrorHandler) + true = Code.ensure_loaded?(Kernel.ErrorHandler) compiler_pid = self() :elixir_code_server.cast({:reset_warnings, compiler_pid}) schedulers = max(:erlang.system_info(:schedulers_online), 2) @@ -87,7 +87,7 @@ defmodule Kernel.ParallelCompiler do :erlang.process_flag(:error_handler, Kernel.ErrorHandler) exit(try do - if output do + _ = if output do :elixir_compiler.file_to_path(h, output) else :elixir_compiler.file(h) diff --git a/lib/elixir/lib/module.ex b/lib/elixir/lib/module.ex index 3853bfeac8..ec3ca42b19 100644 --- a/lib/elixir/lib/module.ex +++ b/lib/elixir/lib/module.ex @@ -940,7 +940,8 @@ defmodule Module do end defp normalize_attribute(:behaviour, atom) when is_atom(atom) do - Code.ensure_compiled(atom) + # Attempt to compile behaviour but ignore failure (will warn later) + _ = Code.ensure_compiled(atom) atom end diff --git a/lib/elixir/lib/module/locals_tracker.ex b/lib/elixir/lib/module/locals_tracker.ex index d0e71e1389..3b5f6293dd 100644 --- a/lib/elixir/lib/module/locals_tracker.ex +++ b/lib/elixir/lib/module/locals_tracker.ex @@ -277,12 +277,12 @@ defmodule Module.LocalsTracker do end def handle_cast({:add_local, from, to}, {d, _} = state) do - handle_add_local(d, from, to) + _ = handle_add_local(d, from, to) {:noreply, state} end def handle_cast({:add_import, function, module, {name, arity}}, {d, _} = state) do - handle_import(d, function, module, name, arity) + _ = handle_import(d, function, module, name, arity) {:noreply, state} end @@ -292,7 +292,7 @@ defmodule Module.LocalsTracker do end def handle_cast({:add_defaults, kind, {name, arity}, defaults}, {d, _} = state) do - for i <- :lists.seq(arity - defaults, arity - 1) do + _ = for i <- :lists.seq(arity - defaults, arity - 1) do handle_add_definition(d, kind, {name, i}) handle_add_local(d, {name, i}, {name, i + 1}) end @@ -302,12 +302,12 @@ defmodule Module.LocalsTracker do def handle_cast({:reattach, kind, tuple, {in_neigh, out_neigh}}, {d, _} = state) do handle_add_definition(d, kind, tuple) - for from <- in_neigh do + _ = for from <- in_neigh do :digraph.add_vertex(d, from) replace_edge!(d, from, tuple) end - for to <- out_neigh do + _ = for to <- out_neigh do :digraph.add_vertex(d, to) replace_edge!(d, tuple, to) end @@ -336,7 +336,7 @@ defmodule Module.LocalsTracker do tuple = {:import, name, arity} :digraph.add_vertex(d, tuple) - replace_edge!(d, tuple, module) + _ = replace_edge!(d, tuple, module) if function != nil do replace_edge!(d, function, tuple) diff --git a/lib/elixir/lib/stream.ex b/lib/elixir/lib/stream.ex index 21285edc2a..075141454b 100644 --- a/lib/elixir/lib/stream.ex +++ b/lib/elixir/lib/stream.ex @@ -428,7 +428,7 @@ defmodule Stream do """ @spec run(Enumerable.t) :: :ok def run(stream) do - Enumerable.reduce(stream, {:cont, nil}, fn(_, _) -> {:cont, nil} end) + _ = Enumerable.reduce(stream, {:cont, nil}, fn(_, _) -> {:cont, nil} end) :ok end diff --git a/lib/elixir/src/elixir.erl b/lib/elixir/src/elixir.erl index a7548c5648..d17a1b5579 100644 --- a/lib/elixir/src/elixir.erl +++ b/lib/elixir/src/elixir.erl @@ -28,8 +28,10 @@ start(_Type, _Args) -> error -> [binary] end, - io:setopts(standard_io, Opts), - io:setopts(standard_error, [{unicode,true}]), + ok = io:setopts(standard_io, Opts), + %% Must use undocument {unicode, true} to set unicode on standard_error, more + %% info: http://erlang.org/pipermail/erlang-bugs/2014-April/004310.html + ok = io:setopts(standard_error, [{unicode,true}]), case file:native_name_encoding() of latin1 -> io:format(standard_error, @@ -51,13 +53,13 @@ config_change(_Changed, _New, _Remove) -> %% escript entry point main(Args) -> - application:start(?MODULE), + ok = application:start(?MODULE), 'Elixir.Kernel.CLI':main(Args). %% Boot and process given options. Invoked by Elixir's script. start_cli() -> - application:start(?MODULE), + ok = application:start(?MODULE), 'Elixir.Kernel.CLI':main(init:get_plain_arguments()). %% EVAL HOOKS diff --git a/lib/elixir/src/elixir_code_server.erl b/lib/elixir/src/elixir_code_server.erl index 73af363ee3..268c6aea68 100644 --- a/lib/elixir/src/elixir_code_server.erl +++ b/lib/elixir/src/elixir_code_server.erl @@ -28,9 +28,9 @@ start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, ok, []). init(ok) -> - code:ensure_loaded('Elixir.Macro.Env'), - code:ensure_loaded('Elixir.Module.LocalsTracker'), - code:ensure_loaded('Elixir.Kernel.LexicalTracker'), + _ = code:ensure_loaded('Elixir.Macro.Env'), + _ = code:ensure_loaded('Elixir.Module.LocalsTracker'), + _ = code:ensure_loaded('Elixir.Kernel.LexicalTracker'), {ok, #elixir_code_server{}}. handle_call({acquire, Path}, From, Config) -> @@ -120,7 +120,7 @@ handle_cast({loaded, Path}, Config) -> {ok, true} -> {noreply, Config}; {ok, {Ref, List}} when is_list(List), is_reference(Ref) -> - [Pid ! {elixir_code_server, Ref, loaded} || {Pid, _Tag} <- lists:reverse(List)], + _ = [Pid ! {elixir_code_server, Ref, loaded} || {Pid, _Tag} <- lists:reverse(List)], Done = orddict:store(Path, true, Current), {noreply, Config#elixir_code_server{loaded=Done}}; error -> diff --git a/lib/elixir/src/elixir_compiler.erl b/lib/elixir/src/elixir_compiler.erl index cd5f52700a..8435fdb5fd 100644 --- a/lib/elixir/src/elixir_compiler.erl +++ b/lib/elixir/src/elixir_compiler.erl @@ -40,7 +40,7 @@ file(Relative) when is_binary(Relative) -> file_to_path(File, Path) when is_binary(File), is_binary(Path) -> Lists = file(File), - [binary_to_path(X, Path) || X <- Lists], + _ = [binary_to_path(X, Path) || X <- Lists], Lists. %% Evaluation @@ -144,7 +144,7 @@ module(Forms, File, Options, Bootstrap, Callback) when case compile:noenv_forms([no_auto_import()|Forms], [return,{source,Listname}|Options]) of {ok, ModuleName, Binary, Warnings} -> format_warnings(Bootstrap, Warnings), - code:load_binary(ModuleName, Listname, Binary), + {module, ModuleName} = code:load_binary(ModuleName, Listname, Binary), Callback(ModuleName, Binary); {error, Errors, Warnings} -> format_warnings(Bootstrap, Warnings), @@ -157,14 +157,14 @@ no_auto_import() -> %% CORE HANDLING core() -> - application:start(elixir), + ok = application:start(elixir), elixir_code_server:cast({compiler_options, [{docs,false},{internal,true}]}), [core_file(File) || File <- core_main()]. core_file(File) -> try Lists = file(File), - [binary_to_path(X, "lib/elixir/ebin") || X <- Lists], + _ = [binary_to_path(X, "lib/elixir/ebin") || X <- Lists], io:format("Compiled ~ts~n", [File]) catch Kind:Reason -> diff --git a/lib/elixir/src/elixir_def.erl b/lib/elixir/src/elixir_def.erl index f75f2744bd..284c1939d8 100644 --- a/lib/elixir/src/elixir_def.erl +++ b/lib/elixir/src/elixir_def.erl @@ -83,13 +83,13 @@ store_definition(Line, Kind, CheckClauses, Name, Args, Guards, Body, MetaFile, # Arity = length(Args), Tuple = {Name, Arity}, E = ER#{function := Tuple}, - elixir_locals:record_definition(Tuple, Kind, Module), + _ = elixir_locals:record_definition(Tuple, Kind, Module), Location = retrieve_location(Line, MetaFile, Module), {Function, Defaults, Super} = translate_definition(Kind, Line, Module, Name, Args, Guards, Body, E), DefaultsLength = length(Defaults), - elixir_locals:record_defaults(Tuple, Kind, Module, DefaultsLength), + _ = elixir_locals:record_defaults(Tuple, Kind, Module, DefaultsLength), File = ?m(E, file), Table = table(Module), @@ -115,13 +115,16 @@ run_on_definition_callbacks(Kind, Line, Module, Name, Args, Guards, Expr, E) -> _ -> Env = elixir_env:linify({Line, E}), Callbacks = 'Elixir.Module':get_attribute(Module, on_definition), - [Mod:Fun(Env, Kind, Name, Args, Guards, Expr) || {Mod, Fun} <- Callbacks] + _ = [Mod:Fun(Env, Kind, Name, Args, Guards, Expr) || {Mod, Fun} <- Callbacks], + ok end. make_struct_available(def, Module, '__struct__', []) -> case erlang:get(elixir_compiler_pid) of undefined -> ok; - Pid -> Pid ! {struct_available, Module} + Pid -> + Pid ! {struct_available, Module}, + ok end; make_struct_available(_, _, _, _) -> ok. @@ -304,7 +307,8 @@ warn_bodyless_function(_Line, _File, Special, _Kind, _Tuple) when Special == 'Elixir.Kernel.SpecialForms'; Special == 'Elixir.Module' -> ok; warn_bodyless_function(Line, File, _Module, Kind, Tuple) -> - elixir_errors:handle_file_warning(File, {Line, ?MODULE, {bodyless_fun, Kind, Tuple}}). + _ = elixir_errors:handle_file_warning(File, {Line, ?MODULE, {bodyless_fun, Kind, Tuple}}), + ok. %% Store each definition in the table. %% This function also checks and emit warnings in case diff --git a/lib/elixir/src/elixir_def_overridable.erl b/lib/elixir/src/elixir_def_overridable.erl index 7aece602c6..e4adda28e6 100644 --- a/lib/elixir/src/elixir_def_overridable.erl +++ b/lib/elixir/src/elixir_def_overridable.erl @@ -58,8 +58,9 @@ store(Module, Function, GenerateName) -> %% Store pending declarations that were not manually made concrete. store_pending(Module) -> - [store(Module, X, false) || {X, {_, _, _, false}} <- overridable(Module), - not 'Elixir.Module':'defines?'(Module, X)]. + _ = [store(Module, X, false) || {X, {_, _, _, false}} <- overridable(Module), + not 'Elixir.Module':'defines?'(Module, X)], + ok. %% Error handling diff --git a/lib/elixir/src/elixir_dispatch.erl b/lib/elixir/src/elixir_dispatch.erl index c469fe8a3c..e86eacae9a 100644 --- a/lib/elixir/src/elixir_dispatch.erl +++ b/lib/elixir/src/elixir_dispatch.erl @@ -37,11 +37,11 @@ find_import(Meta, Name, Arity, E) -> case find_dispatch(Meta, Tuple, [], E) of {function, Receiver} -> elixir_lexical:record_import(Receiver, ?m(E, lexical_tracker)), - elixir_locals:record_import(Tuple, Receiver, ?m(E, module), ?m(E, function)), + _ = elixir_locals:record_import(Tuple, Receiver, ?m(E, module), ?m(E, function)), Receiver; {macro, Receiver} -> elixir_lexical:record_import(Receiver, ?m(E, lexical_tracker)), - elixir_locals:record_import(Tuple, Receiver, ?m(E, module), ?m(E, function)), + _ = elixir_locals:record_import(Tuple, Receiver, ?m(E, module), ?m(E, function)), Receiver; _ -> false @@ -54,7 +54,7 @@ import_function(Meta, Name, Arity, E) -> case find_dispatch(Meta, Tuple, [], E) of {function, Receiver} -> elixir_lexical:record_import(Receiver, ?m(E, lexical_tracker)), - elixir_locals:record_import(Tuple, Receiver, ?m(E, module), ?m(E, function)), + _ = elixir_locals:record_import(Tuple, Receiver, ?m(E, module), ?m(E, function)), remote_function(Meta, Receiver, Name, Arity, E); {macro, _Receiver} -> false; @@ -64,7 +64,7 @@ import_function(Meta, Name, Arity, E) -> case elixir_import:special_form(Name, Arity) of true -> false; false -> - elixir_locals:record_local(Tuple, ?m(E, module), ?m(E, function)), + _ = elixir_locals:record_local(Tuple, ?m(E, module), ?m(E, function)), {local, Name, Arity} end end. @@ -139,7 +139,7 @@ expand_import(Meta, {Name, Arity} = Tuple, Args, E, Extra) -> %% Dispatch to the local. _ -> - elixir_locals:record_local(Tuple, Module, Function), + _ = elixir_locals:record_local(Tuple, Module, Function), {ok, Module, expand_macro_fun(Meta, Local(), Module, Name, Args, E)} end. @@ -147,7 +147,7 @@ do_expand_import(Meta, {Name, Arity} = Tuple, Args, Module, E, Result) -> case Result of {function, Receiver} -> elixir_lexical:record_import(Receiver, ?m(E, lexical_tracker)), - elixir_locals:record_import(Tuple, Receiver, Module, ?m(E, function)), + _ = elixir_locals:record_import(Tuple, Receiver, Module, ?m(E, function)), case rewrite(Receiver, Name, Args, Arity) of {ok, _, _, _} = Res -> Res; @@ -156,7 +156,7 @@ do_expand_import(Meta, {Name, Arity} = Tuple, Args, Module, E, Result) -> {macro, Receiver} -> check_deprecation(Meta, Receiver, Name, Arity, E), elixir_lexical:record_import(Receiver, ?m(E, lexical_tracker)), - elixir_locals:record_import(Tuple, Receiver, Module, ?m(E, function)), + _ = elixir_locals:record_import(Tuple, Receiver, Module, ?m(E, function)), {ok, Receiver, expand_macro_named(Meta, Receiver, Name, Arity, Args, E)}; {import, Receiver} -> case expand_require([{require,false}|Meta], Receiver, Tuple, Args, E) of diff --git a/lib/elixir/src/elixir_exp.erl b/lib/elixir/src/elixir_exp.erl index ba786b4b88..1d9bfbd1df 100644 --- a/lib/elixir/src/elixir_exp.erl +++ b/lib/elixir/src/elixir_exp.erl @@ -452,7 +452,7 @@ expand_local(Meta, Name, Args, #{local := nil, function := nil} = E) -> {EArgs, EA} = expand_args(Args, E), {{Name, Meta, EArgs}, EA}; expand_local(Meta, Name, Args, #{local := nil, module := Module, function := Function} = E) -> - elixir_locals:record_local({Name, length(Args)}, Module, Function), + _ = elixir_locals:record_local({Name, length(Args)}, Module, Function), {EArgs, EA} = expand_args(Args, E), {{Name, Meta, EArgs}, EA}; expand_local(Meta, Name, Args, E) -> diff --git a/lib/elixir/src/elixir_lexical.erl b/lib/elixir/src/elixir_lexical.erl index 7f299442de..8bdc895e21 100644 --- a/lib/elixir/src/elixir_lexical.erl +++ b/lib/elixir/src/elixir_lexical.erl @@ -64,14 +64,16 @@ if_tracker(Pid, Callback) when is_pid(Pid) -> Callback(Pid). %% ERROR HANDLING warn_unused_imports(File, Pid) -> - [ begin + _ = [ begin elixir_errors:handle_file_warning(File, {L, ?MODULE, {unused_import, M}}) - end || {M, L} <- ?tracker:collect_unused_imports(Pid)]. + end || {M, L} <- ?tracker:collect_unused_imports(Pid)], + ok. warn_unused_aliases(File, Pid) -> - [ begin + _ = [ begin elixir_errors:handle_file_warning(File, {L, ?MODULE, {unused_alias, M}}) - end || {M, L} <- ?tracker:collect_unused_aliases(Pid)]. + end || {M, L} <- ?tracker:collect_unused_aliases(Pid)], + ok. format_error({unused_alias, Module}) -> io_lib:format("unused alias ~ts", [elixir_aliases:inspect(Module)]); diff --git a/lib/elixir/src/elixir_locals.erl b/lib/elixir/src/elixir_locals.erl index da9b11f3a4..075216f075 100644 --- a/lib/elixir/src/elixir_locals.erl +++ b/lib/elixir/src/elixir_locals.erl @@ -146,7 +146,7 @@ get_cached_env(Env) -> Env. ensure_no_import_conflict(_Line, _File, 'Elixir.Kernel', _All) -> ok; ensure_no_import_conflict(Line, File, Module, All) -> - if_tracker(Module, fun(Pid) -> + _ = if_tracker(Module, fun(Pid) -> [ begin elixir_errors:form_error(Line, File, ?MODULE, {function_conflict, Error}) end || Error <- ?tracker:collect_imports_conflicts(Pid, All) ] @@ -160,7 +160,7 @@ warn_unused_local(File, Module, Private) -> {Unreachable, Warnings} = ?tracker:collect_unused_locals(Pid, Args), - [ begin + _ = [ begin {_, _, Line, _, _} = lists:keyfind(element(2, Error), 1, Private), elixir_errors:handle_file_warning(File, {Line, ?MODULE, Error}) end || Error <- Warnings ], diff --git a/lib/elixir/src/elixir_module.erl b/lib/elixir/src/elixir_module.erl index 8fc16ed1a2..6f95f5f30e 100644 --- a/lib/elixir/src/elixir_module.erl +++ b/lib/elixir/src/elixir_module.erl @@ -52,7 +52,7 @@ do_compile(Line, Module, Block, Vars, E) -> try {Result, NE} = eval_form(Line, Module, Block, Vars, E), - case ets:lookup(data_table(Module), 'on_load') of + _ = case ets:lookup(data_table(Module), 'on_load') of [] -> ok; [{on_load,OnLoad}] -> [elixir_locals:record_local(Tuple, Module) || Tuple <- OnLoad] @@ -79,7 +79,7 @@ do_compile(Line, Module, Block, Vars, E) -> Binary = load_form(Line, Final, compile_opts(Module), NE), {module, Module, Binary, Result} after - elixir_locals:cleanup(Module), + _ = elixir_locals:cleanup(Module), elixir_def:cleanup(Module), ets:delete(docs_table(Module)), ets:delete(data_table(Module)) @@ -101,7 +101,7 @@ build(Line, File, Module, Lexical) -> [] end, - ets:new(DataTable, [set, named_table, public]), + DataTable = ets:new(DataTable, [set, named_table, public]), ets:insert(DataTable, {before_compile, []}), ets:insert(DataTable, {after_compile, []}), @@ -310,14 +310,14 @@ load_form(Line, Forms, Opts, #{file := File} = E) -> put(elixir_compiled, [{Module,Binary}|Current]), case get(elixir_compiler_pid) of - undefined -> []; + undefined -> ok; PID -> Ref = make_ref(), PID ! {module_available, self(), Ref, File, Module, Binary}, receive {Ref, ack} -> ok end end; _ -> - [] + ok end, Binary @@ -355,7 +355,8 @@ check_module_availability(Line, File, Module) -> false -> case code:ensure_loaded(Module) of {module, _} -> - elixir_errors:handle_file_warning(File, {Line, ?MODULE, {module_defined, Module}}); + _ = elixir_errors:handle_file_warning(File, {Line, ?MODULE, {module_defined, Module}}), + ok; {error, _} -> ok end; diff --git a/lib/ex_unit/lib/ex_unit.ex b/lib/ex_unit/lib/ex_unit.ex index 4bd9684210..7e1d9046af 100644 --- a/lib/ex_unit/lib/ex_unit.ex +++ b/lib/ex_unit/lib/ex_unit.ex @@ -132,8 +132,7 @@ defmodule ExUnit do If you want to run tests manually, you can set `:autorun` to `false`. """ def start(options \\ []) do - Application.start(:elixir) - Application.start(:ex_unit) + {:ok, _} = Application.ensure_all_started(:ex_unit) configure(options) diff --git a/lib/ex_unit/lib/ex_unit/runner.ex b/lib/ex_unit/lib/ex_unit/runner.ex index 4bed446d6e..33bb0b7e83 100644 --- a/lib/ex_unit/lib/ex_unit/runner.ex +++ b/lib/ex_unit/lib/ex_unit/runner.ex @@ -255,7 +255,7 @@ defmodule ExUnit.Runner do end defp shuffle(%{seed: seed}, list) do - :random.seed(3172, 9814, seed) + _ = :random.seed(3172, 9814, seed) Enum.shuffle(list) end diff --git a/lib/iex/lib/iex.ex b/lib/iex/lib/iex.ex index e104879bc4..142dba5c43 100644 --- a/lib/iex/lib/iex.ex +++ b/lib/iex/lib/iex.ex @@ -450,9 +450,9 @@ defmodule IEx do _ -> :init.wait_until_started() end - start_iex() - set_expand_fun() - run_after_spawn() + :ok = start_iex() + :ok = set_expand_fun() + :ok = run_after_spawn() IEx.Server.start(opts, mfa) end end @@ -464,8 +464,7 @@ defmodule IEx do defp start_iex() do unless started? do - Application.start(:elixir) - Application.start(:iex) + {:ok, _} = Application.ensure_all_started(:iex) Application.put_env(:iex, :started, true) colors = [enabled: IO.ANSI.terminal?] ++ @@ -478,12 +477,13 @@ defmodule IEx do gl = Process.group_leader glnode = node gl - if glnode != node do - ensure_module_exists glnode, IEx.Remsh - expand_fun = IEx.Remsh.expand node - else - expand_fun = &IEx.Autocomplete.expand(&1) - end + expand_fun = + if glnode != node do + _ = ensure_module_exists glnode, IEx.Remsh + IEx.Remsh.expand node + else + &IEx.Autocomplete.expand(&1) + end :io.setopts gl, [expand_fun: expand_fun, binary: true, encoding: :unicode] end @@ -496,7 +496,8 @@ defmodule IEx do end defp run_after_spawn do - for fun <- Enum.reverse(after_spawn), do: fun.() + _ = for fun <- Enum.reverse(after_spawn), do: fun.() + :ok end # Used by default on evaluation cycle diff --git a/lib/iex/lib/iex/introspection.ex b/lib/iex/lib/iex/introspection.ex index c5653b39ac..c68170419d 100644 --- a/lib/iex/lib/iex/introspection.ex +++ b/lib/iex/lib/iex/introspection.ex @@ -186,7 +186,7 @@ defmodule IEx.Introspection do Print types in module. """ def t(module) when is_atom(module) do - case Kernel.Typespec.beam_types(module) do + _ = case Kernel.Typespec.beam_types(module) do nil -> nobeam(module) [] -> notypes(inspect module) types -> for type <- types, do: print_type(type) diff --git a/lib/mix/lib/mix.ex b/lib/mix/lib/mix.ex index c88d4aae16..a2cb8bfa11 100644 --- a/lib/mix/lib/mix.ex +++ b/lib/mix/lib/mix.ex @@ -15,8 +15,8 @@ defmodule Mix do @doc false def start do - Application.start(:elixir) - Application.start(:mix) + {:ok, _} = Application.ensure_all_started(:mix) + :ok end @doc false diff --git a/lib/mix/lib/mix/cli.ex b/lib/mix/lib/mix/cli.ex index bf231356e9..bbb228a418 100644 --- a/lib/mix/lib/mix/cli.ex +++ b/lib/mix/lib/mix/cli.ex @@ -19,7 +19,7 @@ defmodule Mix.CLI do end defp proceed(args) do - Mix.Tasks.Local.Hex.maybe_update() + _ = Mix.Tasks.Local.Hex.ensure_updated?() load_dot_config() args = load_mixfile(args) {task, args} = get_task(args) @@ -29,7 +29,7 @@ defmodule Mix.CLI do defp load_mixfile(args) do file = System.get_env("MIX_EXS") || "mix.exs" - if File.regular?(file) do + _ = if File.regular?(file) do Code.load_file(file) end args diff --git a/lib/mix/lib/mix/compilers/elixir.ex b/lib/mix/lib/mix/compilers/elixir.ex index f85ae9cc78..de64e775a3 100644 --- a/lib/mix/lib/mix/compilers/elixir.ex +++ b/lib/mix/lib/mix/compilers/elixir.ex @@ -80,7 +80,7 @@ defmodule Mix.Compilers.Elixir do end) try do - Kernel.ParallelCompiler.files :lists.usort(stale), + _ = Kernel.ParallelCompiler.files :lists.usort(stale), each_module: &each_module(pid, dest, cwd, &1, &2, &3), each_file: &each_file(&1) Agent.cast pid, fn entries -> @@ -140,7 +140,7 @@ defmodule Mix.Compilers.Elixir do defp remove_stale_entries([{beam, module, source, _d, _f} = entry|t], changed, removed, acc) do if source in changed do - File.rm(beam) + File.rm!(beam) remove_stale_entries(t, changed, [module|removed], acc) else remove_stale_entries(t, changed, removed, [entry|acc]) diff --git a/lib/mix/lib/mix/dep/fetcher.ex b/lib/mix/lib/mix/dep/fetcher.ex index 9e42b762ad..ccf1ef10f3 100644 --- a/lib/mix/lib/mix/dep/fetcher.ex +++ b/lib/mix/lib/mix/dep/fetcher.ex @@ -27,7 +27,7 @@ defmodule Mix.Dep.Fetcher do {apps, deps} = do_finalize(result, old_lock, opts) # Check if all given dependencies are loaded or fail - Mix.Dep.loaded_by_name(names, deps, opts) + _ = Mix.Dep.loaded_by_name(names, deps, opts) apps end @@ -117,9 +117,10 @@ defmodule Mix.Dep.Fetcher do # file to it. Each build, regardless of the environment and location, # will compared against this .fetch file to know if the depednency # needs recompiling. - for %Mix.Dep{scm: scm, opts: opts} <- deps, scm.fetchable? do - File.touch Path.join opts[:dest], ".fetch" + _ = for %Mix.Dep{scm: scm, opts: opts} <- deps, scm.fetchable? do + File.touch! Path.join opts[:dest], ".fetch" end + :ok end defp with_depending(deps, all_deps) do diff --git a/lib/mix/lib/mix/dep/loader.ex b/lib/mix/lib/mix/dep/loader.ex index febf499b4d..ae5c5b0976 100644 --- a/lib/mix/lib/mix/dep/loader.ex +++ b/lib/mix/lib/mix/dep/loader.ex @@ -125,9 +125,8 @@ defmodule Mix.Dep.Loader do {scm, opts} = get_scm(app, opts) - unless scm do - Mix.Tasks.Local.Hex.maybe_install(app) - Mix.Tasks.Local.Hex.maybe_start() + if !scm && Mix.Tasks.Local.Hex.ensure_installed?(app) do + _ = Mix.Tasks.Local.Hex.start() {scm, opts} = get_scm(app, opts) end diff --git a/lib/mix/lib/mix/project.ex b/lib/mix/lib/mix/project.ex index 3b99b95c2c..76d5f9ece5 100644 --- a/lib/mix/lib/mix/project.ex +++ b/lib/mix/lib/mix/project.ex @@ -302,18 +302,18 @@ defmodule Mix.Project do source = Path.expand("ebin") target = Path.join(app, "ebin") - cond do + _ = cond do opts[:symlink_ebin] -> - Mix.Utils.symlink_or_copy(source, target) + _ = Mix.Utils.symlink_or_copy(source, target) match?({:ok, _}, :file.read_link(target)) -> - File.rm_rf!(target) + _ = File.rm_rf!(target) File.mkdir_p!(target) true -> File.mkdir_p!(target) end - Mix.Utils.symlink_or_copy(Path.expand("include"), Path.join(app, "include")) - Mix.Utils.symlink_or_copy(Path.expand("priv"), Path.join(app, "priv")) + _ = Mix.Utils.symlink_or_copy(Path.expand("include"), Path.join(app, "include")) + _ = Mix.Utils.symlink_or_copy(Path.expand("priv"), Path.join(app, "priv")) :ok end @@ -341,7 +341,7 @@ defmodule Mix.Project do file = Path.expand("mix.exs") old_proj = get - if File.regular?(file) do + _ = if File.regular?(file) do Code.load_file(file) end diff --git a/lib/mix/lib/mix/scm/git.ex b/lib/mix/lib/mix/scm/git.ex index 36c55245bf..d4277091f5 100644 --- a/lib/mix/lib/mix/scm/git.ex +++ b/lib/mix/lib/mix/scm/git.ex @@ -73,7 +73,7 @@ defmodule Mix.SCM.Git do path = opts[:dest] location = opts[:git] - File.rm_rf!(path) + _ = File.rm_rf!(path) command = ~s(git clone --no-checkout --progress "#{location}" "#{path}") run_cmd_or_raise(command) @@ -151,7 +151,8 @@ defmodule Mix.SCM.Git do end defp update_origin(location) do - :os.cmd('git --git-dir=.git config remote.origin.url #{location}') + _ = :os.cmd('git --git-dir=.git config remote.origin.url #{location}') + :ok end defp run_cmd_or_raise(command) do diff --git a/lib/mix/lib/mix/tasks/archive.install.ex b/lib/mix/lib/mix/tasks/archive.install.ex index eee1a3d0ff..c8bdc21806 100644 --- a/lib/mix/lib/mix/tasks/archive.install.ex +++ b/lib/mix/lib/mix/tasks/archive.install.ex @@ -28,7 +28,7 @@ defmodule Mix.Tasks.Archive.Install do intended for automation in build systems like make """ - + @spec run(OptionParser.argv) :: boolean def run(argv) do {opts, argv, _} = OptionParser.parse(argv, switches: [force: :boolean]) @@ -59,7 +59,9 @@ defmodule Mix.Tasks.Archive.Install do File.mkdir_p!(dest) archive = Path.join(dest, basename(src)) create_file archive, Mix.Utils.read_path!(src) - Code.append_path(Mix.Archive.ebin(archive)) + true = Code.append_path(Mix.Archive.ebin(archive)) + else + false end end diff --git a/lib/mix/lib/mix/tasks/clean.ex b/lib/mix/lib/mix/tasks/clean.ex index c3ea131320..cfd56a9701 100644 --- a/lib/mix/lib/mix/tasks/clean.ex +++ b/lib/mix/lib/mix/tasks/clean.ex @@ -20,7 +20,7 @@ defmodule Mix.Tasks.Clean do def run(args) do {opts, _, _} = OptionParser.parse(args) - for compiler <- Mix.Tasks.Compile.compilers() do + _ = for compiler <- Mix.Tasks.Compile.compilers() do module = Mix.Task.get!("compile.#{compiler}") if function_exported?(module, :clean, 0) do module.clean diff --git a/lib/mix/lib/mix/tasks/compile.elixir.ex b/lib/mix/lib/mix/tasks/compile.elixir.ex index f36d0c4448..8e96f78203 100644 --- a/lib/mix/lib/mix/tasks/compile.elixir.ex +++ b/lib/mix/lib/mix/tasks/compile.elixir.ex @@ -57,7 +57,7 @@ defmodule Mix.Tasks.Compile.Elixir do || Mix.Utils.stale?(configs, [manifest]) result = Mix.Compilers.Elixir.compile(manifest, srcs, [:ex], dest, force, fn -> - Code.prepend_path(dest) + true = Code.prepend_path(dest) set_compiler_opts(project, opts, []) end) diff --git a/lib/mix/lib/mix/tasks/compile.erlang.ex b/lib/mix/lib/mix/tasks/compile.erlang.ex index 0e2da67b4c..7bf50f2e5d 100644 --- a/lib/mix/lib/mix/tasks/compile.erlang.ex +++ b/lib/mix/lib/mix/tasks/compile.erlang.ex @@ -127,18 +127,19 @@ defmodule Mix.Tasks.Compile.Erlang do defp sort_dependencies(erls) do graph = :digraph.new - for erl <- erls do + _ = for erl <- erls do :digraph.add_vertex(graph, erl.module, erl) end - for erl <- erls do - for b <- erl.behaviours, do: :digraph.add_edge(graph, b, erl.module) - for c <- erl.compile do + _ = for erl <- erls do + _ = for b <- erl.behaviours, do: :digraph.add_edge(graph, b, erl.module) + _ = for c <- erl.compile do case c do {:parse_transform, transform} -> :digraph.add_edge(graph, transform, erl.module) _ -> :ok end end + :ok end result = diff --git a/lib/mix/lib/mix/tasks/compile.ex b/lib/mix/lib/mix/tasks/compile.ex index d29403af5a..7a0a52d61f 100644 --- a/lib/mix/lib/mix/tasks/compile.ex +++ b/lib/mix/lib/mix/tasks/compile.ex @@ -56,7 +56,7 @@ defmodule Mix.Tasks.Compile do List.wrap Mix.Task.run("compile.#{compiler}", args) end) - Code.prepend_path(Mix.Project.compile_path) + true = Code.prepend_path(Mix.Project.compile_path) unless "--no-readd" in args, do: Code.readd_paths() if Enum.any?(res, &(:ok in &1)), do: :ok, else: :noop end diff --git a/lib/mix/lib/mix/tasks/compile.protocols.ex b/lib/mix/lib/mix/tasks/compile.protocols.ex index fc2409b02d..e858e22f8b 100644 --- a/lib/mix/lib/mix/tasks/compile.protocols.ex +++ b/lib/mix/lib/mix/tasks/compile.protocols.ex @@ -47,7 +47,7 @@ defmodule Mix.Tasks.Compile.Protocols do defp consolidate(protocols, paths, output) do File.mkdir_p!(output) - for protocol <- protocols do + _ = for protocol <- protocols do impls = Protocol.extract_impls(protocol, paths) maybe_reload(protocol) {:ok, binary} = Protocol.consolidate(protocol, impls) diff --git a/lib/mix/lib/mix/tasks/deps.check.ex b/lib/mix/lib/mix/tasks/deps.check.ex index f60c5d5073..8f11772ee7 100644 --- a/lib/mix/lib/mix/tasks/deps.check.ex +++ b/lib/mix/lib/mix/tasks/deps.check.ex @@ -21,7 +21,7 @@ defmodule Mix.Tasks.Deps.Check do lock = Mix.Dep.Lock.read all = Enum.map(loaded(env: Mix.env), &check_lock(&1, lock)) - prune_deps(all) + _ = prune_deps(all) {not_ok, compile} = partition_deps(all, [], []) cond do @@ -79,9 +79,12 @@ defmodule Mix.Tasks.Deps.Check do to_prune = Enum.reduce(all, paths, &(&2 -- Mix.Dep.load_paths(&1))) Enum.map(to_prune, fn path -> - Code.delete_path(path) + # path may not be in code path + _ = Code.delete_path(path) File.rm_rf!(path |> Path.dirname) end) + else + [] end end diff --git a/lib/mix/lib/mix/tasks/deps.compile.ex b/lib/mix/lib/mix/tasks/deps.compile.ex index 7d95199a78..2b57f4d892 100644 --- a/lib/mix/lib/mix/tasks/deps.compile.ex +++ b/lib/mix/lib/mix/tasks/deps.compile.ex @@ -119,8 +119,8 @@ defmodule Mix.Tasks.Deps.Compile do "dependency #{app}, please ensure rebar is available" end - Mix.Tasks.Local.Rebar.run [] - Mix.Rebar.local_rebar_cmd || Mix.raise "rebar installation failed" + (Mix.Tasks.Local.Rebar.run([]) && Mix.Rebar.local_rebar_cmd) || + Mix.raise "rebar installation failed" end defp do_make(dep) do diff --git a/lib/mix/lib/mix/tasks/local.hex.ex b/lib/mix/lib/mix/tasks/local.hex.ex index cf6c62a8f3..8a558ca146 100644 --- a/lib/mix/lib/mix/tasks/local.hex.ex +++ b/lib/mix/lib/mix/tasks/local.hex.ex @@ -16,40 +16,56 @@ defmodule Mix.Tasks.Local.Hex do * `--force` - forces installation without a shell prompt; primarily intended for automation in build systems like make """ + @spec run(OptionParser.argv) :: boolean def run(args) do Mix.Tasks.Archive.Install.run [@hex_url|args] end @doc false - def maybe_install(app) do - unless Code.ensure_loaded?(Hex) do + # Returns true if Hex is loaded or installed, otherwise returns false. + @spec ensure_installed?(atom) :: boolean + def ensure_installed?(app) do + if Code.ensure_loaded?(Hex) do + true + else shell = Mix.shell shell.info "Could not find hex, which is needed to build dependency #{inspect app}" if shell.yes?("Shall I install hex?") do run ["--force"] + else + false end end end @doc false - def maybe_update do + # Returns true if have required Hex, returns false if don't and don't update, + # if update then exits. + @spec ensure_updated?() :: boolean + def ensure_updated?() do if Code.ensure_loaded?(Hex) do - unless Version.match?(Hex.version, @hex_requirement) do + if Version.match?(Hex.version, @hex_requirement) do + true + else Mix.shell.info "Mix requires hex #{@hex_requirement} but you have #{Hex.version}" if Mix.shell.yes?("Shall I abort the current command and update hex?") do run ["--force"] exit({:shutdown, 0}) + else + false end end + else + false end end @doc false - def maybe_start do + def start do try do - Code.ensure_loaded?(Hex) && Hex.start + Hex.start catch kind, reason -> stacktrace = System.stacktrace diff --git a/lib/mix/lib/mix/tasks/local.rebar.ex b/lib/mix/lib/mix/tasks/local.rebar.ex index 37a0b5157d..26a8cc2f7f 100644 --- a/lib/mix/lib/mix/tasks/local.rebar.ex +++ b/lib/mix/lib/mix/tasks/local.rebar.ex @@ -14,7 +14,7 @@ defmodule Mix.Tasks.Local.Rebar do The local copy is stored in your MIX_HOME (defaults to ~/.mix). This version of rebar will be used as required by `mix deps.compile`. """ - + @spec run(OptionParser.argv) :: true def run(argv) do {_, argv, _} = OptionParser.parse(argv) do_install(case argv do @@ -28,6 +28,7 @@ defmodule Mix.Tasks.Local.Rebar do local_rebar_path = Mix.Rebar.local_rebar_path File.mkdir_p! Path.dirname(local_rebar_path) create_file local_rebar_path, rebar - :file.change_mode local_rebar_path, 0755 + :ok = :file.change_mode local_rebar_path, 0755 + true end end diff --git a/lib/mix/lib/mix/tasks/run.ex b/lib/mix/lib/mix/tasks/run.ex index c4f7a8eddc..68fb7e3248 100644 --- a/lib/mix/lib/mix/tasks/run.ex +++ b/lib/mix/lib/mix/tasks/run.ex @@ -56,7 +56,7 @@ defmodule Mix.Tasks.Run do Mix.Task.run "app.start", args process_load opts - if file do + _ = if file do if File.regular?(file) do Code.require_file(file) else diff --git a/lib/mix/lib/mix/tasks/test.ex b/lib/mix/lib/mix/tasks/test.ex index 20e938e80b..6afc8f1b75 100644 --- a/lib/mix/lib/mix/tasks/test.ex +++ b/lib/mix/lib/mix/tasks/test.ex @@ -4,15 +4,20 @@ defmodule Mix.Tasks.Test do def start(compile_path, opts) do Mix.shell.info "Cover compiling modules ... " - :cover.start - :cover.compile_beam_directory(compile_path |> to_char_list) + {:ok, _} = :cover.start + case :cover.compile_beam_directory(compile_path |> to_char_list) do + results when is_list(results) -> + :ok + {:error, _} -> + Mix.raise "Failed to cover compile directory: " <> compile_path + end output = opts[:output] fn() -> Mix.shell.info "\nGenerating cover results ... " File.mkdir_p!(output) Enum.each :cover.modules, fn(mod) -> - :cover.analyse_to_file(mod, '#{output}/#{mod}.html', [:html]) + {:ok, _} = :cover.analyse_to_file(mod, '#{output}/#{mod}.html', [:html]) end end end @@ -155,7 +160,12 @@ defmodule Mix.Tasks.Test do # that command line options override test_helper.exs Mix.shell.print_app Mix.Task.run "app.start", args - Application.load(:ex_unit) + + # Ensure ex_unit is loaded. + case Application.load(:ex_unit) do + :ok -> :ok + {:error, {:already_loaded, :ex_unit}} -> :ok + end opts = ex_unit_opts(opts) ExUnit.configure(opts) diff --git a/lib/mix/lib/mix/utils.ex b/lib/mix/lib/mix/utils.ex index a884ecd022..fd623df61c 100644 --- a/lib/mix/lib/mix/utils.ex +++ b/lib/mix/lib/mix/utils.ex @@ -308,7 +308,7 @@ defmodule Mix.Utils do {:error, :enoent} -> do_symlink_or_copy(source, target) {:error, _} -> - File.rm_rf!(target) + _ = File.rm_rf!(target) do_symlink_or_copy(source, target) end else @@ -367,8 +367,8 @@ defmodule Mix.Utils do end defp read_url(path) do - :ssl.start - :inets.start + :ok = :ssl.start + :ok = :inets.start # Starting a http client profile allows us to scope # the effects of using a http proxy to this function @@ -399,8 +399,8 @@ defmodule Mix.Utils do defp proxy(proxy) do uri = URI.parse(proxy) - :httpc.set_options([{ proxy_scheme(uri.scheme), - { { uri.host |> String.to_char_list, uri.port }, [] } }], :mix) + :ok = :httpc.set_options([{ proxy_scheme(uri.scheme), + { { uri.host |> String.to_char_list, uri.port }, [] } }], :mix) end defp proxy_scheme(scheme) do