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

Move fast and fix things

Move fast and fix things

An introduction to Scalafix, presented at Scala IO 2017

Gabriele Petronella

November 02, 2017
Tweet

More Decks by Gabriele Petronella

Other Decks in Programming

Transcript

  1. Move fast and
    BREAK FIX
    things

    View full-size slide

  2. STUFF I DO (BY DAY)

    View full-size slide

  3. STUFF I DO (BY NIGHT)
    Scala and JS open-source

    View full-size slide

  4. AGENDA
    1. Intro and context
    2. ASTs and related workflows
    3. Scalameta
    4. Scalafix
    5. Live examples

    View full-size slide

  5. WHAT IS SCALAFIX
    Scalafix is a rewrite and linting tool for Scala
    — scalacenter.github.io/scalafix

    View full-size slide

  6. EXAMPLE 1 - NOPROCEDURESYNTAX
    // before
    def main(args: Seq[String]) {
    println("Hello world!")
    }
    // after
    def main(args: Seq[String]): Unit = {
    println("Hello world!")
    }

    View full-size slide

  7. EXAMPLE 2 - NOAUTOTUPLING
    // before
    def someMethod(t: (Int, String)) = ???
    someMethod(1, "something")
    // after
    def someMethod(t: (Int, String)) = ???
    someMethod((1, "something"))

    View full-size slide

  8. EXAMPLE 3 - REMOVECARTESIANBUILDER
    // before
    import cats.syntax.cartesian._
    val o1: Option[Int] = Some(42)
    val o2: Option[String] = Some("hello")
    o1 |@| o2 map (_ + _)
    // after
    import cats.syntax.apply._
    val o1: Option[Int] = Some(42)
    val o2: Option[String] = Some("hello")
    (o1, o2).mapN(_ + _)

    View full-size slide

  9. EXAMPLE 4 - NOINFER
    val myList = List(Some(42), Right("foo"))
    // ^
    // |__

    Product with Serializable

    View full-size slide

  10. LET'S TALK ABOUT
    MAINTAINERS

    View full-size slide

  11. PURE EVIL
    BREAK CODE WITHOUT
    DOCUMENTING WHAT
    BROKE

    View full-size slide

  12. MILD EVIL
    BREAK CODE
    DOCUMENTING WHAT
    BROKE
    (OR LINKING TO A SUPER-LONG ISSUE)

    View full-size slide

  13. GOOD EFFORT
    BREAK CODE AND
    DOCUMENT HOW TO FIX IT

    View full-size slide

  14. YOU ROCK!
    BREAK CODE AFTER A
    DEPRECATION CYCLE AND
    EXPLAIN HOW TO FIX IT

    View full-size slide

  15. SUPERHERO
    BREAK CODE AFTER A
    DEPRECATION CYCLE AND
    PROVIDE AN AUTOMATIC
    REWRITE

    View full-size slide

  16. MEANWHILE IN SWIFT

    View full-size slide

  17. MEANWHILE IN
    JAVASCRIPT

    View full-size slide

  18. MEANWHILE IN JAVASCRIPT
    3 paragraphs later

    View full-size slide

  19. The JS tooling landscape is living in the
    future
    — Ólafur Páll Geirsson, author of Scalafix

    View full-size slide

  20. IT'S TIME WE JUMP INTO THE
    FUTURE

    View full-size slide

  21. HOW?
    LET'S TAKE A STEP BACK

    View full-size slide

  22. A WORD ABOUT
    ASTS
    SO... AST?

    View full-size slide

  23. ABSTRACT
    SYNTAX
    TREE

    View full-size slide

  24. WHY ABSTRACT?

    View full-size slide

  25. val answer = 42;
    val answer = 42
    val answer =
    42
    val
    answer
    =
    42

    View full-size slide

  26. ASTS...
    WHY SHOULD I
    CARE?

    View full-size slide

  27. AST WORKFLOW 1: SCALAC

    View full-size slide

  28. AST WORKFLOW 2: MACROS

    View full-size slide

  29. AST WORKFLOW 3: SCALAFMT

    View full-size slide

  30. AST WORKFLOW 4: SCALAFIX

    View full-size slide

  31. AST WORKFLOW 4: SCALAFIX
    Woops, copy-paste?

    View full-size slide

  32. WHAT SCALAFIX COULD DO:
    // before
    def someMethod(string: String) { // I like trees
    println(string.trim.split("/").lastOption)
    }
    // after
    def someMethod(string: String): Unit =
    println(
    string
    .trim
    .split("/")
    .lastOption
    )

    View full-size slide

  33. WHAT SCALAFIX DOES INSTEAD:
    // before
    def someMethod(string: String) { // I like trees
    println(string.trim.split("/").lastOption)
    }
    // after
    def someMethod(string: String): Unit = { // I like trees
    println(string.trim.split("/").lastOption)
    }

    View full-size slide

  34. "AST" WORKFLOW 4: SCALAFIX

    View full-size slide

  35. OK, LET'S DO
    THIS!

    View full-size slide

  36. Introducing
    SCALAMETA

    View full-size slide

  37. Scalameta is a modern
    metaprogramming library for Scala
    — scalameta.org

    View full-size slide

  38. METAPROGRAMMING?

    View full-size slide

  39. METAPROGRAMMING DEVTOOLS!
    ▸ code formatting
    ▸ code fixing
    ▸ code browsing
    ▸ and many more applications!

    View full-size slide

  40. SCALAMETA VADEMECUM
    ▸ Trees
    ▸ Tokens
    ▸ Parser
    ▸ Tree manipulation primitives
    ▸ Semantic API
    ▸ (pretty-printer)

    View full-size slide

  41. SEMANTIC INFORMATION
    List(1, 2, 3)
    // Symbol
    _root_.scala.collection.immutable.List.
    // Denotation
    final object List
    // Synthetic
    [2..7): apply => _root_.scala.collection.immutable.List.apply
    (Lscala/collection/Seq;)

    View full-size slide

  42. SCALAFIX
    FINALLY!

    View full-size slide

  43. Rule
    A rule can be:
    ▸ checked
    ▸ fixed

    View full-size slide

  44. Patch
    A Scalafix Patch is a patch in the diff sense of patch.
    It boils down to a list of -/+ to apply to the source code.

    View full-size slide

  45. RuleCtx
    The toolbox for writing rules.
    It provides the API for producing patches.

    View full-size slide

  46. SemanticdbIndex

    View full-size slide

  47. SemanticdbIndex
    A index for looking up data in a scalameta's Semantic Database.
    It contains all the available semantic information.

    View full-size slide

  48. WHAT'S NEXT?

    View full-size slide

  49. SHORT-TERM
    ▸ more linter rules
    ▸ rule "bundles"
    ▸ more robust expansion of inferred types / implicits

    View full-size slide

  50. MEDIUM TERM
    ▸ editor integrations
    ▸ stable API

    View full-size slide

  51. Questions?
    @gabro27
    @buildoHQ
    @ScalaItaly

    View full-size slide