Skip to content

Escape string literals that contain line breaks#908

Open
adityasingh2400 wants to merge 1 commit into
apple:mainfrom
adityasingh2400:fix-string-literal-newline
Open

Escape string literals that contain line breaks#908
adityasingh2400 wants to merge 1 commit into
apple:mainfrom
adityasingh2400:fix-string-literal-newline

Conversation

@adityasingh2400
Copy link
Copy Markdown

When the renderer emits a string literal, it currently picks between a raw literal and a plain literal based only on whether the content contains a quote or a backslash. But neither a raw nor a plain single-line literal can contain a line break, so any string value with a newline or carriage return is rendered across multiple lines and produces an unterminated string literal that does not compile.

Motivation

A string enum whose value contains a newline triggers this. For example:

components:
  schemas:
    Mode:
      type: string
      enum:
        - "first line\nsecond line"
        - normal

generates:

@frozen public enum Mode: String, Codable, Hashable, Sendable, CaseIterable {
    case first_space_line_xA_second_space_line = "first line
second line"
    case normal = "normal"
}

which fails to compile with error: unterminated string literal. The same applies anywhere a .string literal carries a line break, including a string with both a quote and a newline, where the existing raw-literal path is chosen but still cannot span lines.

Modifications

renderLiteral now checks for a line feed or carriage return first. When the content has one, it emits an escaped regular literal that represents the break with \n or \r (also escaping backslashes and quotes so the value round-trips). Every other string keeps the existing raw-literal behavior, so no current output changes.

The example above now renders as a single valid line:

case first_space_line_xA_second_space_line = "first line\nsecond line"

Result

Specs with line breaks in string values, such as enum cases, now generate compiling Swift whose values match the input byte for byte.

Test Plan

Added unit tests in Test_TextBasedRenderer covering a newline, a newline combined with a quote, a carriage return, and a backslash followed by a newline. They fail before the change and pass after. The existing reference and Petstore suites are unchanged.

The text renderer emitted string literals on a single line, choosing
between a raw literal and a plain literal based only on whether the
content had a quote or backslash. Neither a raw nor a plain single-line
literal can contain a line break, so any string value with a newline or
carriage return produced an unterminated string literal that does not
compile.

This happens, for example, when a string enum case value in the OpenAPI
document contains a newline: the generated `rawValue` spanned two lines
and the file failed to build.

Detect line breaks first and, in that case, emit an escaped regular
literal that represents the break with `\n` or `\r` (also escaping
backslashes and quotes). All other strings keep the existing raw-literal
behavior, so no current output changes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant