Skip to content

Commit 8e58f3a

Browse files
authored
Merge pull request #194 from scalacenter/no-autotupling-functions
Handle auto-tupling on functions
2 parents c7d1846 + 02f5973 commit 8e58f3a

File tree

3 files changed

+76
-40
lines changed

3 files changed

+76
-40
lines changed

scalafix-core/src/main/scala/scalafix/rewrite/NoAutoTupling.scala

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,68 @@ case class NoAutoTupling(mirror: Mirror) extends SemanticRewrite(mirror) {
1515
ctx.addLeft(args.head.tokens.head, "(") +
1616
ctx.addRight(args.last.tokens.last, ")")
1717

18+
private[this] def fixMethods(ctx: RewriteCtx,
19+
jvmSignature: String,
20+
argss: Seq[Seq[Term.Arg]],
21+
fixed: mutable.Set[Seq[Term.Arg]]): Patch = {
22+
val argListSignatures =
23+
jvmSignature.stripPrefix("(").takeWhile(_ != ')').split(';')
24+
argListSignatures
25+
.zip(argss)
26+
.foldLeft(Patch.empty) {
27+
case (patches, (argListSignature, args)) =>
28+
if (!fixed(args) && singleTuplePattern
29+
.matcher(argListSignature)
30+
.matches && args.length > 1) {
31+
fixed += args // dirty hack, see explanation above
32+
patches + addWrappingParens(ctx, args)
33+
} else {
34+
patches
35+
}
36+
}
37+
}
38+
39+
private[this] def fixFunctions(ctx: RewriteCtx,
40+
symbol: Symbol,
41+
argss: Seq[Seq[Term.Arg]],
42+
fixed: mutable.Set[Seq[Term.Arg]],
43+
mirror: Mirror): Patch =
44+
mirror.database.denotations
45+
.get(symbol)
46+
.map { denot =>
47+
val argListSignatures =
48+
denot.info.split("=>").map(_.trim).toList.dropRight(1)
49+
argListSignatures
50+
.zip(argss)
51+
.foldLeft(Patch.empty) {
52+
case (patches, (argListSignature, args)) =>
53+
if (!fixed(args) && argListSignature.startsWith("((") && argListSignature
54+
.endsWith("))")
55+
&& args.length > 1) {
56+
fixed += args
57+
patches + addWrappingParens(ctx, args)
58+
} else {
59+
patches
60+
}
61+
}
62+
}
63+
.asPatch
64+
1865
override def rewrite(ctx: RewriteCtx): Patch = {
1966
// "hack" to avoid fixing an argument list more than once due
2067
// to recursive matching of multiple parameters lists.
2168
val fixed = mutable.Set.empty[Seq[Term.Arg]]
2269
ctx.tree.collect {
2370
case q"${fun: Term.Ref}(...$argss)" if argss.nonEmpty =>
24-
fun.symbolOpt
25-
.collect {
26-
case Symbol.Global(_, Signature.Method(_, jvmSignature)) =>
27-
val argListSignatures =
28-
jvmSignature.stripPrefix("(").takeWhile(_ != ')').split(';')
29-
argListSignatures
30-
.zip(argss)
31-
.foldLeft(Patch.empty) {
32-
case (patches, (argListSignature, args)) =>
33-
if (!fixed(args) && singleTuplePattern
34-
.matcher(argListSignature)
35-
.matches && args.length > 1) {
36-
fixed += args // dirty hack, see explanation above
37-
patches + addWrappingParens(ctx, args)
38-
} else {
39-
patches
40-
}
41-
}
42-
}
43-
.getOrElse(Patch.empty)
71+
fun.symbolOpt.collect {
72+
case s @ Symbol.Global(_, Signature.Method(_, jvmSignature)) =>
73+
fixMethods(ctx, jvmSignature, argss, fixed) +
74+
fixFunctions(ctx, s, argss, fixed, mirror)
75+
76+
case s @ Symbol.Global(_, Signature.Term(x))
77+
if mirror.database.denotations.get(s).isDefined =>
78+
fixFunctions(ctx, s, argss, fixed, mirror)
79+
}.asPatch
4480
}.asPatch
4581
}
4682
}

scalafix-tests/input/src/main/scala/test/NoAutoTupling.scala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,16 @@ class NoAutoTupling {
4242
def sum(a: Int, b: (Int, String)): Int = ???
4343
sum(1, (2, "foo"))
4444
}
45-
// <<< SKIP auto-tupling with lambdas
46-
// object tup6 {
47-
// val foo = (a: (Int, Boolean)) => a
48-
// foo(2, true)
49-
// }
50-
// <<< SKIP auto-tupling with curried methods
51-
// object tup7 {
52-
// def foo: (((Int, String)) => ((String, List[Int])) => Int) = a => b => a._1
53-
// foo(1 + 2, "foo")("bar", 1 :: 2 :: Nil)
54-
// }
45+
// <<< auto-tupling with lambdas
46+
object tup6 {
47+
val foo = (a: (Int, Boolean)) => a
48+
foo(2, true)
49+
}
50+
// <<< auto-tupling with curried methods
51+
object tup7 {
52+
def foo: (((Int, String)) => ((String, List[Int])) => Int) = a => b => a._1
53+
foo(1 + 2, "foo")("bar", 1 :: 2 :: Nil)
54+
}
5555
// <<< auto-tupling with class constructors
5656
object tup8 {
5757
case class Foo(t: (Int, String))(s: (Boolean, List[Int]))

scalafix-tests/output/src/main/scala/test/NoAutoTupling.scala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,16 @@ class NoAutoTupling {
3939
def sum(a: Int, b: (Int, String)): Int = ???
4040
sum(1, (2, "foo"))
4141
}
42-
// <<< SKIP auto-tupling with lambdas
43-
// object tup6 {
44-
// val foo = (a: (Int, Boolean)) => a
45-
// foo(2, true)
46-
// }
47-
// <<< SKIP auto-tupling with curried methods
48-
// object tup7 {
49-
// def foo: (((Int, String)) => ((String, List[Int])) => Int) = a => b => a._1
50-
// foo(1 + 2, "foo")("bar", 1 :: 2 :: Nil)
51-
// }
42+
// <<< auto-tupling with lambdas
43+
object tup6 {
44+
val foo = (a: (Int, Boolean)) => a
45+
foo((2, true))
46+
}
47+
// <<< auto-tupling with curried methods
48+
object tup7 {
49+
def foo: (((Int, String)) => ((String, List[Int])) => Int) = a => b => a._1
50+
foo((1 + 2, "foo"))(("bar", 1 :: 2 :: Nil))
51+
}
5252
// <<< auto-tupling with class constructors
5353
object tup8 {
5454
case class Foo(t: (Int, String))(s: (Boolean, List[Int]))

0 commit comments

Comments
 (0)