jeremyjh / dialyxir

Mix tasks to simplify use of Dialyzer in Elixir projects.
Apache License 2.0
1.7k stars 140 forks source link

typer #245

Open English3000 opened 6 years ago

English3000 commented 6 years ago

Along with dialyzer, there's typer which prints @specs for all functions.

I couldn't find anything for this and was wondering if you had any plans to add it.

jeremyjh commented 6 years ago

I've used typer with erlang, but as far as I know it only accepts erlang source files as inputs. We're able to use dialyzer because it also accepts compiled BEAM files.

This does not mean it is impossible - we can decompile Elixir BEAM files to Erlang source, and then run typer on it and then parse and pretty print the output. That is a lot more tractable now that we have erlex, and maybe would be worth exploring.

the-mikedavis commented 5 years ago

I think the reason this would be difficult is because the dialyzer produces erl_types. For Erlang, there's a very easy erl_types:t_to_string/1 function that can print out a type or a spec. For Elixir, there's no easy conversion as far as I can tell, although erlex looks promising.

I had this idea a while ago and did some exploration. It's pretty easy to match on erl_types because they're just tuples. I did some conversion in https://github.com/the-mikedavis/ex_types and saw some good results, but it's nowhere near general-purpose yet.

I also had the thought about what the typer should produce for Elixir. Printing out strings is fine if we can give a line number where they should go, but it feels like we're missing the opportunity to cash in on quoted forms. If we can parse erl_types into quoted forms then we have a much better shot at injecting the spec into the right place automatically. Plus we get safe formatting for free from core Elixir. I tried this a bit in https://github.com/the-mikedavis/spectre, but, again, it's far from general purpose.

Given that I'm hooking into dialyxir's PLT, I'd be happy to fold in my work from spectre into dialyxir once it seems to work in general 😄

asummers commented 5 years ago

Erlex should be able to run with that just fine. If you find a place to hook it in, it should be as simple as calling Erlex.pretty_print_contract/1 with the stringified output. That's the underlying mechanism for the pretty printed contracts we're getting already in the output.