@@ -137,10 +137,38 @@ class StringInterpolatorOpt extends MiniPhase:
137
137
case _ => false
138
138
// Perform format checking and normalization, then make it StringOps(fmt).format(args1) with tweaked args
139
139
def transformF (fun : Tree , args : Tree ): Tree =
140
- val (fmt, args1) = FormatInterpolatorTransform .checked(fun, args)
140
+ // For f"${arg}%xpart", check format conversions and return (format, args) for String.format(format, args).
141
+ def checked (args0 : Tree )(using Context ): (Tree , Tree ) =
142
+ val (partsExpr, parts) = fun match
143
+ case TypeApply (Select (Apply (_, (parts : SeqLiteral ) :: Nil ), _), _) =>
144
+ (parts.elems, parts.elems.map { case Literal (Constant (s : String )) => s })
145
+ case _ =>
146
+ report.error(" Expected statically known StringContext" , fun.srcPos)
147
+ (Nil , Nil )
148
+ val (args, elemtpt) = args0 match
149
+ case seqlit : SeqLiteral => (seqlit.elems, seqlit.elemtpt)
150
+ case _ =>
151
+ report.error(" Expected statically known argument list" , args0.srcPos)
152
+ (Nil , EmptyTree )
153
+
154
+ def literally (s : String ) = Literal (Constant (s))
155
+ if parts.lengthIs != args.length + 1 then
156
+ val badParts =
157
+ if parts.isEmpty then " there are no parts"
158
+ else s " too ${if parts.lengthIs > args.length + 1 then " few" else " many" } arguments for interpolated string "
159
+ report.error(badParts, fun.srcPos)
160
+ (literally(" " ), args0)
161
+ else
162
+ val checker = TypedFormatChecker (partsExpr, parts, args)
163
+ val (format, formatArgs) = checker.checked
164
+ if format.isEmpty then (literally(parts.mkString), args0) // on error just use unchecked inputs
165
+ else (literally(format.mkString), SeqLiteral (formatArgs.toList, elemtpt))
166
+ end checked
167
+ val (fmt, args1) = checked(args)
141
168
resolveConstructor(defn.StringOps .typeRef, List (fmt))
142
169
.select(nme.format)
143
170
.appliedTo(args1)
171
+ end transformF
144
172
// Starting with Scala 2.13, s and raw are macros in the standard
145
173
// library, so we need to expand them manually.
146
174
// sc.s(args) --> standardInterpolator(processEscapes, args, sc.parts)
0 commit comments