Skip to content

Commit

Permalink
Implement the Any2StringAdd rewrite (#10)
Browse files Browse the repository at this point in the history
Implement the Any2StringAdd rewrite
  • Loading branch information
dwijnand authored Jun 18, 2019
2 parents 2f763d8 + f36f999 commit 57f1e61
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 0 deletions.
54 changes: 54 additions & 0 deletions input/src/main/scala/fix/scala213/Any2StringAdd.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
rule = fix.scala213.Any2StringAdd
*/
package fix.scala213

abstract class Any2StringAdd {
// Strings: leave as-is, both literal strings and non-literal
def s = "bob"
def str1 = s + s
def str2 = s + "bob"
def str3 = "bob" + s
def str4 = "bob" + "fred"

// Non-strings: add toString
def nil = Nil + s

// Non-string, generic type: add toString
type A
def x: A
def generic = x + "bob"

// Primitives: add toString
def unit = ()
def bool = true
def byte = 1.toByte
def short = 1.toShort
def char = 'a'
def int = 1
def long = 1L
def float = 1.0F
def double = 1.0
//
def unit1 = unit + s
def bool1 = bool + s
def byte1 = byte + s
def byte2 = byte + byte
def short1 = short + s
def short2 = short + short
def char1 = char + s
def char2 = char + char
def int1 = int + s
def int2 = int + int
def long1 = long + s
def long2 = long + long
def float1 = float + s
def float2 = float + float
def double1 = double + s
def double2 = double + double

// With infix operators, make sure to use parens
def parens1 = Nil ++ Nil + s
def parens2 = int + int + s
def parens3 = {Nil ++ Nil} + s
}
51 changes: 51 additions & 0 deletions output/src/main/scala/fix/scala213/Any2StringAdd.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package fix.scala213

abstract class Any2StringAdd {
// Strings: leave as-is, both literal strings and non-literal
def s = "bob"
def str1 = s + s
def str2 = s + "bob"
def str3 = "bob" + s
def str4 = "bob" + "fred"

// Non-strings: add toString
def nil = Nil.toString + s

// Non-string, generic type: add toString
type A
def x: A
def generic = x.toString + "bob"

// Primitives: add toString
def unit = ()
def bool = true
def byte = 1.toByte
def short = 1.toShort
def char = 'a'
def int = 1
def long = 1L
def float = 1.0F
def double = 1.0
//
def unit1 = unit.toString + s
def bool1 = bool.toString + s
def byte1 = "" + byte + s
def byte2 = byte + byte
def short1 = "" + short + s
def short2 = short + short
def char1 = "" + char + s
def char2 = char + char
def int1 = "" + int + s
def int2 = int + int
def long1 = "" + long + s
def long2 = long + long
def float1 = "" + float + s
def float2 = float + float
def double1 = "" + double + s
def double2 = double + double

// With infix operators, make sure to use parens
def parens1 = (Nil ++ Nil).toString + s
def parens2 = "" + (int + int) + s
def parens3 = {Nil ++ Nil}.toString + s
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
fix.scala213.Any2StringAdd
fix.scala213.Core
fix.scala213.ScalaSeq
fix.scala213.Varargs
39 changes: 39 additions & 0 deletions rewrites/src/main/scala/fix/scala213/Any2StringAdd.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package fix.scala213

import scalafix.v1._

import scala.meta._

object Any2StringAdd {
val any2stringaddPlusString = SymbolMatcher.exact("scala/Predef.any2stringadd#`+`().")
val primitivePlusString = SymbolMatcher.exact(
"scala/Byte#`+`().",
"scala/Short#`+`().",
"scala/Char#`+`().",
"scala/Int#`+`().",
"scala/Long#`+`().",
"scala/Float#`+`().",
"scala/Double#`+`().",
)
}

final class Any2StringAdd extends SemanticRule("fix.scala213.Any2StringAdd") {
import Any2StringAdd._

override def fix(implicit doc: SemanticDocument): Patch = {
doc.tree.collect {
case any2stringaddPlusString(Term.ApplyInfix(lhs, _, _, _)) => addToString(lhs)
case primitivePlusString(Term.ApplyInfix(lhs, _, _, _)) => blankStringPlus(lhs)
}.asPatch
}

private def addToString(term: Term) = term match {
case _: Term.Name | _: Term.Select | _: Term.Block => Patch.addRight(term, ".toString")
case _ => Patch.addLeft(term, "(") + Patch.addRight(term, ").toString")
}

private def blankStringPlus(term: Term) = term match {
case _: Term.Name | _: Term.Select | _: Term.Block => Patch.addLeft(term, """"" + """)
case _ => Patch.addLeft(term, """"" + (""") + Patch.addRight(term, ")")
}
}

0 comments on commit 57f1e61

Please sign in to comment.