@@ -115,55 +115,57 @@ class StringInterpolatorOpt extends MiniPhase {
115115 }
116116
117117 override def transformApply (tree : Apply )(using Context ): Tree = {
118+ def mkConcat (strs : List [Literal ], elems : List [Tree ]): Tree =
119+ val stri = strs.iterator
120+ val elemi = elems.iterator
121+ var result : Tree = stri.next
122+ def concat (tree : Tree ): Unit =
123+ result = result.select(defn.String_+ ).appliedTo(tree).withSpan(tree.span)
124+ while elemi.hasNext
125+ do
126+ concat(elemi.next)
127+ val str = stri.next
128+ if ! str.const.stringValue.isEmpty then concat(str)
129+ result
130+ end mkConcat
118131 val sym = tree.symbol
119- val isInterpolatedMethod = // Test names first to avoid loading scala.StringContext if not used
120- (sym.name == nme.raw_ && sym.eq(defn.StringContext_raw )) ||
121- (sym.name == nme.f && sym.eq(defn.StringContext_f )) ||
122- (sym.name == nme.s && sym.eq(defn.StringContext_s ))
132+ // Test names first to avoid loading scala.StringContext if not used, and common names first
133+ val isInterpolatedMethod =
134+ sym.name match
135+ case nme.s => sym eq defn.StringContext_s
136+ case nme.raw_ => sym eq defn.StringContext_raw
137+ case nme.f => sym eq defn.StringContext_f
138+ case _ => false
123139 def transformF (fun : Tree , args : Tree ): Tree =
124140 val (parts1, args1) = FormatInterpolatorTransform .checked(fun, args)
125141 resolveConstructor(defn.StringOps .typeRef, List (parts1))
126142 .select(nme.format)
127143 .appliedTo(args1)
128- if (isInterpolatedMethod)
129- (tree : @ unchecked) match {
144+ // Starting with Scala 2.13, s and raw are macros in the standard
145+ // library, so we need to expand them manually.
146+ // sc.s(args) --> standardInterpolator(processEscapes, args, sc.parts)
147+ // sc.raw(args) --> standardInterpolator(x => x, args, sc.parts)
148+ def transformS (fun : Tree , args : Tree , isRaw : Boolean ): Tree =
149+ val pre = fun match
150+ case Select (pre, _) => pre
151+ case intp : Ident => tpd.desugarIdentPrefix(intp)
152+ val stringToString = defn.StringContextModule_processEscapes .info.asInstanceOf [MethodType ]
153+ val process = tpd.Lambda (stringToString, args =>
154+ if isRaw then args.head else ref(defn.StringContextModule_processEscapes ).appliedToTermArgs(args)
155+ )
156+ evalOnce(pre) { sc =>
157+ val parts = sc.select(defn.StringContext_parts )
158+ ref(defn.StringContextModule_standardInterpolator )
159+ .appliedToTermArgs(List (process, args, parts))
160+ }
161+ end transformS
162+ if isInterpolatedMethod then
163+ (tree : @ unchecked) match
130164 case StringContextIntrinsic (strs : List [Literal ], elems : List [Tree ]) =>
131- val stri = strs.iterator
132- val elemi = elems.iterator
133- var result : Tree = stri.next
134- def concat (tree : Tree ): Unit = {
135- result = result.select(defn.String_+ ).appliedTo(tree).withSpan(tree.span)
136- }
137- while (elemi.hasNext) {
138- concat(elemi.next)
139- val str = stri.next
140- if (! str.const.stringValue.isEmpty) concat(str)
141- }
142- result
143- case Apply (intp, args :: Nil ) if sym.eq(defn.StringContext_f ) =>
144- transformF(intp, args)
145- // Starting with Scala 2.13, s and raw are macros in the standard
146- // library, so we need to expand them manually.
147- // sc.s(args) --> standardInterpolator(processEscapes, args, sc.parts)
148- // sc.raw(args) --> standardInterpolator(x => x, args, sc.parts)
165+ mkConcat(strs, elems)
149166 case Apply (intp, args :: Nil ) =>
150- val pre = intp match {
151- case Select (pre, _) => pre
152- case intp : Ident => tpd.desugarIdentPrefix(intp)
153- }
154- val isRaw = sym eq defn.StringContext_raw
155- val stringToString = defn.StringContextModule_processEscapes .info.asInstanceOf [MethodType ]
156-
157- val process = tpd.Lambda (stringToString, args =>
158- if (isRaw) args.head else ref(defn.StringContextModule_processEscapes ).appliedToTermArgs(args))
159-
160- evalOnce(pre) { sc =>
161- val parts = sc.select(defn.StringContext_parts )
162-
163- ref(defn.StringContextModule_standardInterpolator )
164- .appliedToTermArgs(List (process, args, parts))
165- }
166- }
167+ if sym eq defn.StringContext_f then transformF(intp, args)
168+ else transformS(intp, args, isRaw = sym eq defn.StringContext_raw )
167169 else
168170 tree.tpe match
169171 case _ : ConstantType => tree
0 commit comments