NobbZ

NobbZ

Raise warnings during compile time

I’ve forked an abondoned hex-package and continue to maintain it under a new name.

The old code-base does provide a macro that we call finalize/0 for the purpose of this thread. This macro does its work depending on some module-attributes which are filled by other macros (which I do not need to explain here, just consider them similar to the test macro of ex_unit).

Now I want to move the functionallity of this finalize/0-macro into __before_compile__/1-macro and add a proper deprecation warning to finalize/0.

Such that a warning is emitted during compiletime when someone still uses finalize/0 and the hint that it is handled automatically in the current version and that the feature will get completely removed with version X. But how? I did not find anything in the documentation.

Marked As Solved

josevalim

josevalim

Creator of Elixir

TL;DR - Don’t do this. Use IO.warn(msg, Macro.Env.stacktrace(env)).

Please don’t do this.

:elixir_errors is a private module. It is undocumented. It is internal to Elixir only. It is not meant to be accessed by other libraries besides Elixir. There is no guarantee it will continue working on future releases.

Relying on private functions it is very harmful. In the future, if such practices are wide-spread, one of the two things will happen:

  1. We won’t be able to improve Elixir, or improving it will be more complex, because developers are relying on APIs they should not, and we will need to phase them out first

  2. Packages will break on new Elixir versions, which will make it harder for people to migrate to future Elixir versions, or give the impression the ecosystem is fragile (which would be if new Elixir versions are breaking supposedly valid code).

Please don’t rely on private APIs. Not for Elixir, not for other libraries. It is more harmful than you may think.

12
Post #5

Also Liked

hubertlepicki

hubertlepicki

You can do this:

warn.ex:

defmodule Foo do
  defmacro __using__(_opts) do
    :elixir_errors.warn __ENV__.line, __ENV__.file, "this is compilation warning"
  end
end

defmodule Bar do
  use Foo
end

and when compiling you get:

$ elixirc --warnings-as-errors warn.ex 
warn.ex:3: warning: this is compilation warning
Compilation failed due to warnings while using the --warnings-as-errors option
$ rm *.beam                           
$ elixirc warn.ex                     
warn.ex:3: warning: this is compilation warning

In both cases warning is printed to the stderr while compilation. In first case, however, compilation fails and appropriate shell exit code is set. In second case only warning is printed.

@Edit: https://github.com/search?utf8=✓&q=elixir_errors+language%3Aelixir&type=Code&ref=searchresults

Looks like it’s ok to do that, but better in this form:

%{file: file, line: line} = __CALLER__
:elixir_errors.warn(line, file, "error")
josevalim

josevalim

Creator of Elixir

No problem! Although Discourse shows I replied to you, it was really to everyone that is using private APIs, here or on GitHub. :wink:

hubertlepicki

hubertlepicki

This is great. I am terribly sorry to post misleading message, it was the thing I saw somewhere and adopted.

➜  elixir  cat warn.ex                         
defmodule Foo do
  defmacro __using__(_opts) do
    msg = "this is compilation error"
    IO.warn(msg, Macro.Env.stacktrace(__ENV__))
  end
end

defmodule Bar do
  use Foo
end
➜  elixir  elixirc --warnings-as-errors warn.ex
warning: this is compilation error
  warn.ex:4: Foo.__using__/1

Compilation failed due to warnings while using the --warnings-as-errors option

This is way better, however!

Edit: ah yeah it’s plenty of wrong usage in different libs then:
https://github.com/search?utf8=✓&q=elixir_errors+language%3Aelixir&type=Code&ref=searchresults

low hanging fruits if someone wants to make some pull requests.

arjan

arjan

On a more general note, you could write a function decorator for this, like this:

  defmodule DeprecationDecorator do
    use Decorator.Define, deprecated: 0

    def deprecated(body, context) do
      :elixir_errors.warn __ENV__.line, __ENV__.file, "Function #{context.module}.#{context.name}/#{context.arity} is deprecated"
      body
    end
  end

Which you would use like this:

defmodule SomeModule do
  use DeprecationDecorator

  @decorate deprecated
  def old_function_do_not_use() do
    # ...
  end
end

[/end shameless library-plug] :slight_smile:

Where Next?

Popular in Questions Top

pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
Mooodi
Given a string, how can I get access to its character by index? Enum.at("my_string", 2) doesn't work. Or rather, not char, but a substr...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

Other popular topics Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 27727 240
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New

We're in Beta

About us Mission Statement