Gradualizer
Gradualizer copied to clipboard
Define g.erl for interactive work with Gradualizer
This is another batch of convenience stuff for working with Gradualizer. We could say it expands on the idea of user_default.erl that's already present in src, but at least for now I placed the new file under test, so that it doesn't pollute the module namespace for non-interactive use of Gradualizer as a dependency (that is, for ErlangLS).
See also a screenshot of how the docs would be rendered in #456.
The idea is to make it handy in the shell, similar to r3, that's why the terseness.
Another idea is that if we use that convention, then we could rewrite the tests in test/typechecker_tests.erl from:
?_assert(subtype(?t( pos_integer() ), ?t( non_neg_integer()))),
?_assert(subtype(?t( 0..5 ), ?t( non_neg_integer()))),
to something like:
?_assert(subtype(g:type( "pos_integer()" ), g:type( "non_neg_integer()" ))),
?_assert(subtype(g:type( "0..5" ), g:type( "non_neg_integer()" ))),
The reason is that the former cannot be copy-pasted to a shell to troubleshoot / debug in isolation, but the latter can. Now, we could use an -import(gradualizer, [...]), but then the call sites wouldn't be copy-pastable again, so a short module name (not a macro) offers the best source-vs-shell compatibility.
Maybe shell_default and user_default can be used to make things nice in the shell. See doc for shell_default
I implemented h() for documentation access in docsh as a user_default extension before shell_docs existed and I think it's a viable option. However, I think user_default itself doesn't scale well in some scenarios, especially when working across multiple projects/repos:
- When
user_defaultis compiled with a newer Erlang version, but we switch to a project using an old enough version, we have to recompileuser_defaultand when we switch back, we have to recompile again. - When using
user_defaultwe have to manage the Erlang code path manually, for example we have to put Gradualizer inERL_LIBS. However, this might lead to issues when both developing Gradualizer (when I want to use the local copy to test it, soERL_LIBSstands in the way) and using Gradualizer (as part of ErlangLS, which is invoked in the background of a text editor - here we would like a stable version to run, not the locally developed one that might be unstable). - When we want to use different shell extensions in different Erlang projects/repos. We could still resort to something like https://direnv.net/ to manage the path to different
user_defaultinstances, but then we fall again into point 2., i.e. managingERL_LIBS.
I think we can provide a user_default file for people who prefer using it, but I also think a standalone module like the one proposed in this PR together with Rebar3 solve all of the above issues.
I've moved the utils to gradualizer and adjusted the module description. What do you think, @zuiderkwast?