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

Dive into Elixir v1.6 Code Formatter

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Dive into Elixir v1.6 Code Formatter

Speaking about that Elixir code formatter is safe.

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

Avatar for Takayuki Matsubara

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