Typesafe (sorta) templating

Coming from the play framework and would like to give phoenix another try. A really nice thing about play is the typesafe template engine (Twirl). I’ve noticed phoenix will show me mistakes I’ve made when I’m loading the page that I’ve made a mistake on but I’d like for there to be a way if it would tell me when I’m not making a request to that page. Is that possible?

For most languages on the beam typing is handled via the positive typing system included with the beam called Dialyzer. Elixir has a fantastic library that makes it so easy to use (it’s not otherwise terribly simple) called Dialyxir. :slight_smile:

And yes, it works on templates as well since templates get compiled to normal code. :slight_smile:

I just gave it a shot and it did not catch my (contrived) template errors. Is there a configuration that I’m missing?

Hmm, sounds like a bug if so… Let me try a highly simplified test. Given this file:

defmodule EexDialyzeTest do
  @doc """

      iex> EexDialyzeTest.blah()
      Result: 42

  """
  def blah() do
    unquote(EEx.compile_string("Result: <%= 2+thingy() %>"))
  end

  def thingy() do
    :an_atom
  end
end

And the failing test:

  1) doctest EexDialyzeTest.blah/0 (1) (EexDialyzeTestTest)
     test/eex_dialyze_test_test.exs:3
     Doctest failed: got ArithmeticError with message "bad argument in arithmetic expression"
     code: EexDialyzeTest.blah()
     stacktrace:
       (eex_dialyze_test) lib/eex_dialyze_test.ex:1: EexDialyzeTest.blah/0
       (for doctest at) lib/eex_dialyze_test.ex:4: (test)

Then dialyzer ‘should’ catch that, let’s try…

╰─➤  mix dialyzer
Finding suitable PLTs
Checking PLT...
[:compiler, :crypto, :dialyxir, :dialyzer, :elixir, :hipe, :kernel, :logger, :mix, :stdlib, :wx]
PLT is up to date!
Starting Dialyzer
[
  check_plt: false,
  init_plt: '/home/overminddl1/tmp/eex_dialyze_test/_build/dev/dialyxir_erlang-21.0.1_elixir-1.7.0-rc.0_deps-dev.plt',
  files_rec: ['/home/overminddl1/tmp/eex_dialyze_test/_build/dev/lib/eex_dialyze_test/ebin'],
  warnings: [:unknown]
]
Total errors: 2, Skipped: 0
done in 0m2.58s
lib/eex_dialyze_test.ex:1:call
The call:
:erlang.+(2, :an_atom)

will never return since it differs in arguments with
positions 2 from the success typing arguments:

(number(), number())
________________________________________________________________________________
lib/eex_dialyze_test.ex:8:no_return
Function blah/0 has no local return.
________________________________________________________________________________
done (warnings were emitted)

It looks like it caught it just fine? Do you have a reproduceable test case?

1 Like