Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Dive into Elixir v1.6 Code Formatter

Dive into Elixir v1.6 Code Formatter

Speaking about that Elixir code formatter is safe.

M3 Tech Talk #87 2018/02/16 #m3dev

Takayuki Matsubara

February 16, 2018
Tweet

More Decks by Takayuki Matsubara

Other Decks in Programming

Transcript

  1. Who am I? me |> name # Takayuki "Taka" Matsubara

    |> job # Software Engineer |> work_at # M3, Inc. |> like # Ruby, Elixir and OSS |> twitter # ma2ge |> github # ma2gedev |> oss # PowerAssertEx, bundle-star, breadcrumble, # chrono_logger, faraday-encoding
  2. Formatting code in Elixir • The mix format command formats

    your code # Elixir lang example ## before IO . puts ("Elixir is Nice") ## after `mix format` IO.puts("Elixir is Nice")
  3. It's safe with --check-equivalent option $ mix format --check-equivalent check

    if the file after formatting has the same AST. If the ASTs are not equivalent, it is a bug in the code formatter. This option is recommended if you are automatically formatting files. — https:/ /hexdocs.pm/mix/1.6.1/ Mix.Tasks.Format.html
  4. What is AST? • AST is Abstract Syntax Tree !

    • Elixir's internal representation of code • Elixir parses code into AST before executing your program • Same AST means that code behavior is also same Code ! -> AST " -> ... -> Execute #
  5. Detail of formatting process with --check-equivalent option 1. generate formatted

    code from original code • ! -> " 2. generate AST both the codes • ! -> # • " -> # 3. then compare • # ≒ #
  6. Example code # before defmodule My do; def coooolest do;

    "one-liner"; end; end # after `mix format` defmodule My do def coooolest do "one-liner" end end
  7. Original code's AST iex(1)> string1 = "defmodule My do; def

    coooolest do; \"one-liner\"; end; end" "defmodule My do; def coooolest do; \"one-liner\"; end; end" iex(2)> :elixir.string_to_quoted!(to_charlist(string1), 1, "nofile", []) { :defmodule, [line: 1], [ {:__aliases__, [line: 1], [:My]}, [do: {:def, [line: 1], [{:coooolest, [line: 1], nil}, [do: "one-liner"]]}] ] }
  8. Formatted code's AST iex(1)> string2 = """ ...(1)> defmodule My

    do ...(1)> def coooolest do ...(1)> "one-liner" ...(1)> end ...(1)> end ...(1)> """ "defmodule My do\n def coooolest do\n \"one-liner\"\n end\nend\n" iex(2)> :elixir.string_to_quoted!(to_charlist(string2), 1, "nofile", []) { :defmodule, [line: 1], [ {:__aliases__, [line: 1], [:My]}, [do: {:def, [line: 2], [{:coooolest, [line: 2], nil}, [do: "one-liner"]]}] ] }
  9. Compare both of ASTs • The diff shows almost same

    but [line: X] is indifferent ! • But this is metadata so it does not affect behavior " # diff + [do: {:def, [line: 2], [{:coooolest, [line: 2], nil}, [do: "one-liner"]]}] - [do: {:def, [line: 1], [{:coooolest, [line: 1], nil}, [do: "one-liner"]]}]
  10. Recap • Elixir's code formatter can compare formatted code with

    original one at AST level so its safely to use