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