Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ When adding entries, please treat them as if they could end up in a release any

Thank you!

# 0.19.10

- Fix codegen bug where string literals containing both `$` and `"` generated code that failed to compile on Scala 2.12

# 0.19.9

- Support `@structurePattern` targeting unions using `{label}` and `{value}` magic identifiers in [#1978](https://github.com/disneystreaming/smithy4s/pull/1978)
Expand Down
13 changes: 10 additions & 3 deletions modules/codegen/src/smithy4s/codegen/internals/Renderer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import software.amazon.smithy.model.node.Node
import software.amazon.smithy.model.node._
import software.amazon.smithy.model.shapes.ShapeId

import scala.annotation.nowarn
import scala.jdk.CollectionConverters._

import Line._
Expand Down Expand Up @@ -1968,7 +1969,7 @@ private[internals] class Renderer(compilationUnit: CompilationUnit) { self =>
}

private def escapeForStringLiteral(raw: String): String = {
val sb = new StringBuilder("\"")
val sb = new StringBuilder("")
raw.foreach {
case '\b' => sb.append("\\b")
case '\t' => sb.append("\\t")
Expand All @@ -1980,7 +1981,6 @@ private[internals] class Renderer(compilationUnit: CompilationUnit) { self =>
case c if c >= ' ' && c <= '~' => sb.append(c)
case c => sb.append("\\u%04x".format(c.toInt))
}
sb.append('"')
sb.toString()
}

Expand All @@ -1995,7 +1995,14 @@ private[internals] class Renderer(compilationUnit: CompilationUnit) { self =>
// render any such strings as interpolated strings (even though that would
// otherwise be unecessary) so that we can render "$" as "$$", which get
// converted back to "$" during interpolation.
val escaped = if (str.contains('$')) s"s${str.replace("$", "$$")}" else str

// However when using interpolated strings, we cannot use normal escaping
// for double quotes as it is not supported by scala 2.12.
val escaped = if (str.contains('$')) {
@nowarn("msg=possible missing interpolator")
val replaced = str.replace("$", "$$").replace("\\\"", "${'\\\"'}")
s"""s"$replaced""""
} else s""""$str""""

line"$escaped"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import software.amazon.smithy.model.Model
import software.amazon.smithy.model.shapes.EnumShape
import software.amazon.smithy.model.shapes.StructureShape

import scala.annotation.nowarn

final class RendererSpec extends munit.ScalaCheckSuite {
import TestUtils._

Expand Down Expand Up @@ -456,6 +458,33 @@ final class RendererSpec extends munit.ScalaCheckSuite {
)
}

test(
"string literal containing $ and \" is rendered correctly"
) {
val smithy = """
|$version: "2.0"
|
|namespace smithy4s
|
|/// foo $ "
|string MyString
|""".stripMargin

val contents = generateScalaCode(smithy).values

@nowarn("msg=possible missing interpolator")
val expected =
"""Hints.dynamic(ShapeId("smithy.api", "documentation"), smithy4s.Document.fromString(s"foo $$ ${'\"'}"))"""
assert(
contents.exists(
_.contains(
expected
)
)
)
assert(s"foo $$ ${'\"'}" == "foo $ \"")
}

test(
"string literal containing /* is rendered as a string with * escaped as &ast;"
) {
Expand Down
Loading