@@ -8,19 +8,21 @@ import scala.collection.mutable
88
99object CanBuildFrom {
1010 def apply (paramss : List [List [Term .Param ]],
11- body : Term ,
11+ stats : List [ Tree ] ,
1212 ctx : RuleCtx ,
1313 collectionCanBuildFrom : SymbolMatcher ,
1414 nothing : SymbolMatcher )(implicit index : SemanticdbIndex ): Patch = {
1515 // CanBuildFrom has def apply() but not CanBuild
1616 def emptyApply (param : Name ): Boolean = {
1717 import scala .meta .contrib ._
1818 val matchCbf = SymbolMatcher .exact(ctx.index.symbol(param).get)
19- body.exists {
20- case Term .Apply (Term .Select (matchCbf(_), _), Nil ) => true
21- case Term .Apply (matchCbf(_), Nil ) => true
22- case _ => false
23- }
19+ stats.exists(
20+ _.exists {
21+ case Term .Apply (Term .Select (matchCbf(_), _), Nil ) => true
22+ case Term .Apply (matchCbf(_), Nil ) => true
23+ case _ => false
24+ }
25+ )
2426 }
2527
2628 paramss.flatten
@@ -38,7 +40,7 @@ object CanBuildFrom {
3840 ) if ! nothing.matches(p1) && ! emptyApply(param) =>
3941 new CanBuildFrom (param, cbf)
4042 }
41- .map(_.toBuildFrom(body , ctx))
43+ .map(_.toBuildFrom(stats , ctx))
4244 .asPatch
4345 }
4446}
@@ -48,7 +50,7 @@ object CanBuildFrom {
4850// param: cbf
4951// cbf : collection.generic.CanBuildFrom
5052case class CanBuildFrom (param : Name , cbf : Type ) {
51- def toBuildFrom (body : Term , ctx : RuleCtx )(implicit index : SemanticdbIndex ): Patch = {
53+ def toBuildFrom (stats : List [ Tree ] , ctx : RuleCtx )(implicit index : SemanticdbIndex ): Patch = {
5254
5355 val matchCbf = SymbolMatcher .exact(ctx.index.symbol(param).get)
5456
@@ -60,15 +62,17 @@ case class CanBuildFrom(param: Name, cbf: Type) {
6062 )
6163
6264 val cbfCalls =
63- body.collect {
64- // cbf.apply(x)
65- case ap @ Term .Apply (sel @ Term .Select (cbf2 @ matchCbf(_), apply), List (x)) =>
66- replaceNewBuilder(ap, cbf2, x)
67-
68- // cbf(x)
69- case ap @ Term .Apply (cbf2 @ matchCbf(_), List (x)) =>
70- replaceNewBuilder(ap, cbf2, x)
71- }.asPatch
65+ stats
66+ .map(_.collect {
67+ // cbf.apply(x)
68+ case ap @ Term .Apply (sel @ Term .Select (cbf2 @ matchCbf(_), apply), List (x)) =>
69+ replaceNewBuilder(ap, cbf2, x)
70+
71+ // cbf(x)
72+ case ap @ Term .Apply (cbf2 @ matchCbf(_), List (x)) =>
73+ replaceNewBuilder(ap, cbf2, x)
74+ }.asPatch)
75+ .asPatch
7276
7377 val parameterType =
7478 ctx.replaceTree(cbf, " BuildFrom" )
@@ -79,12 +83,13 @@ case class CanBuildFrom(param: Name, cbf: Type) {
7983
8084object CanBuildFromNothing {
8185 def apply (paramss : List [List [Term .Param ]],
82- body : Term ,
86+ stats : List [ Tree ] ,
8387 ctx : RuleCtx ,
8488 collectionCanBuildFrom : SymbolMatcher ,
8589 nothing : SymbolMatcher ,
8690 toTpe : SymbolMatcher ,
8791 handledTo : mutable.Set [Tree ])(implicit index : SemanticdbIndex ): Patch = {
92+
8893 paramss.flatten
8994 .collect {
9095 case Term .Param (
@@ -96,16 +101,13 @@ object CanBuildFromNothing {
96101 List (
97102 nothing(_),
98103 t,
99- cct @ Type .Apply (
100- cc,
101- _
102- )
104+ toT
103105 )
104106 )
105107 ),
106108 _
107109 ) =>
108- new CanBuildFromNothing (param, tpe, t, cct, cc, body , ctx, toTpe, handledTo)
110+ new CanBuildFromNothing (param, tpe, t, toT, stats , ctx, toTpe, handledTo)
109111 }
110112 .map(_.toFactory)
111113 .asPatch
@@ -119,14 +121,12 @@ object CanBuildFromNothing {
119121// tpe : collection.generic.CanBuildFrom[Nothing, Int, CC[Int]]
120122// cbf : CanBuildFrom
121123// v : Int
122- // cct : CC[Int]
123- // cc : CC
124+ // toT : CC[Int]
124125case class CanBuildFromNothing (param : Name ,
125126 tpe : Type .Apply ,
126127 t : Type ,
127- cct : Type .Apply ,
128- cc : Type ,
129- body : Term ,
128+ toT : Type ,
129+ stats : List [Tree ],
130130 ctx : RuleCtx ,
131131 toTpe : SymbolMatcher ,
132132 handledTo : mutable.Set [Tree ]) {
@@ -141,53 +141,61 @@ case class CanBuildFromNothing(param: Name,
141141 val visitedCbfCalls = mutable.Set [Tree ]()
142142
143143 val cbfCalls =
144- body.collect {
145- // cbf.apply()
146- case ap @ Term . Apply (sel @ Term . Select (cbf2 @ matchCbf(_), apply), Nil ) =>
147- visitedCbfCalls += sel
148- replaceNewBuilder(ap, cbf2)
149-
150- // cbf.apply
151- case sel @ Term . Select (cbf2 @ matchCbf(_), ap) if ( ! visitedCbfCalls.contains(sel)) =>
152- replaceNewBuilder( sel, cbf2)
153-
154- // cbf()
155- case ap @ Term . Apply (cbf2 @ matchCbf(_), Nil ) =>
156- replaceNewBuilder(ap, cbf2)
157- }.asPatch
158-
159- val matchCC = SymbolMatcher .exact(ctx.index.symbol(cc).get)
144+ stats
145+ .map(_.collect {
146+ // cbf.apply()
147+ case ap @ Term . Apply ( sel @ Term . Select (cbf2 @ matchCbf(_), apply), Nil ) =>
148+ visitedCbfCalls += sel
149+ replaceNewBuilder(ap, cbf2)
150+
151+ // cbf.apply
152+ case sel @ Term . Select ( cbf2 @ matchCbf(_), ap) if ( ! visitedCbfCalls.contains(sel)) =>
153+ replaceNewBuilder(sel, cbf2)
154+
155+ // cbf()
156+ case ap @ Term . Apply ( cbf2 @ matchCbf(_), Nil ) =>
157+ replaceNewBuilder(ap, cbf2)
158+ }.asPatch)
159+ .asPatch
160160
161161 // e.to[CC] => cbf.fromSpecific(e)
162- val toCalls =
163- body.collect {
164- case ap @ Term .ApplyType (Term .Select (e, to @ toTpe(_)), List (cc2 @ matchCC(_))) =>
165- handledTo += to
162+ val toCalls = toT match {
163+ case cct @ Type .Apply (cc, _) => {
164+ val matchCC = SymbolMatcher .exact(ctx.index.symbol(cc).get)
165+
166+ stats
167+ .map(_.collect {
168+ case ap @ Term .ApplyType (Term .Select (e, to @ toTpe(_)), List (cc2 @ matchCC(_))) =>
169+ handledTo += to
166170
167- // e.to[CC](*cbf*) extract implicit parameter
168- val synth = ctx.index.synthetics.find(_.position.end == ap.pos.end).get
169- val Term .Apply (_, List (implicitCbf)) = synth.text.parse[Term ].get
171+ // e.to[CC](*cbf*) extract implicit parameter
172+ val synth = ctx.index.synthetics.find(_.position.end == ap.pos.end).get
173+ val Term .Apply (_, List (implicitCbf)) = synth.text.parse[Term ].get
170174
171- // This is a bit unsafe
172- // https://github.com/scalameta/scalameta/issues/1636
173- if (implicitCbf.syntax == param.syntax) {
175+ // This is a bit unsafe
176+ // https://github.com/scalameta/scalameta/issues/1636
177+ if (implicitCbf.syntax == param.syntax) {
174178
175- // .to[CC]
176- val apToRemove = ap.tokens.slice(e.tokens.end - ap.tokens.start, ap.tokens.size)
179+ // .to[CC]
180+ val apToRemove = ap.tokens.slice(e.tokens.end - ap.tokens.start, ap.tokens.size)
177181
178- ctx.removeTokens(apToRemove) +
179- ctx.addLeft(e, implicitCbf.syntax + " .fromSpecific(" ) +
180- ctx.addRight(e, " )" )
181- } else Patch .empty
182+ ctx.removeTokens(apToRemove) +
183+ ctx.addLeft(e, implicitCbf.syntax + " .fromSpecific(" ) +
184+ ctx.addRight(e, " )" )
185+ } else Patch .empty
182186
183- }.asPatch
187+ }.asPatch)
188+ .asPatch
189+ }
190+ case _ => Patch .empty
191+ }
184192
185193 // implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, CC[Int]] =>
186194 // implicit cbf: Factory[Int, CC[Int]]
187195 val parameterType =
188196 ctx.replaceTree(
189197 tpe,
190- Type .Apply (Type .Name (" Factory" ), List (t, cct )).syntax
198+ Type .Apply (Type .Name (" Factory" ), List (t, toT )).syntax
191199 )
192200
193201 parameterType + cbfCalls + toCalls
0 commit comments