asummers / erlex

Convert Erlang style structs and error messages to equivalent Elixir.
Other
34 stars 16 forks source link

Do not print type vars as atom literals. #39

Closed jeremyjh closed 5 years ago

jeremyjh commented 5 years ago

This addresses the second part of jeremyjh/dialyxir#346. The issue there is contract type vars used in when clauses are formatted like they are an atom literal.

e.g.

@spec do_stuff(avar) :: res when avar: term(), res: binary()

would get printed as

@spec do_stuff(:avar) :: :res when avar: term, res: binary

My fix is not beautiful, but I think its straightforward and low risk. We just make a list of all the names used in the when clause, and strip those names of a leading :.

I didn't pursue it too deeply but I think a possible alternative would be treat what gets lexed as atom_part as a name - in contracts atom literals come single quoted and lex as :atom_full. I really only looked at the contracts, you may already know this is is a non-starter.

But for example the spec

  @spec ok(km, :fnord) :: km when km: term

comes to us Erlangified in the contract arg as

(km, s, 'fnord') -> km when km :: term(), s :: atom()

Everything coming out of the lex() as :atom_part are non-atom-literals that we'll have to strip of ":" downstream.

[
  {:"(", 1},
  {:atom_part, 1, 'k'},
  {:atom_part, 1, 'm'},
  {:",", 1},
  {:atom_part, 1, 's'},
  {:",", 1},
  {:atom_full, 1, '\'fnord\''},
  {:")", 1},
  {:->, 1},
  {:atom_part, 1, 'k'},
  {:atom_part, 1, 'm'},
  {:when, 1},
  {:atom_part, 1, 'k'},
  {:atom_part, 1, 'm'},
  {:::, 1},
  {:atom_part, 1, 't'},
  {:atom_part, 1, 'e'},
  {:atom_part, 1, 'r'},
  {:atom_part, 1, 'm'},
  {:"(", 1},
  {:")", 1},
  {:",", 1},
  {:atom_part, 1, 's'},
  {:::, 1},
  {:atom_part, 1, 'a'},
  {:atom_part, 1, 't'},
  {:atom_part, 1, 'o'},
  {:atom_part, 1, 'm'},
  {:"(", 1},
  {:")", 1}
]