String reboot - (1a) incidental whitespace

Liam Miller-Cushon cushon at google.com
Tue Apr 16 23:03:02 UTC 2019


On Wed, Apr 10, 2019 at 8:25 AM Jim Laskey <james.laskey at oracle.com> wrote:

> Don’t peek yet.  Stop and comment first.
>

Here's a variation on the narrative you provided. This is more thinking
aloud than a proposal I'm advocating for, but I think it's a potentially
interesting point in the design space.

Idea: multi-line strings should be formatted like other expressions, rather
than a block-like construct (this differs from the 'fat delimiter pattern'
in the original message), i.e.:

String a = """
        ...
        """; // +8 expression continuation indent

Policy: both delimiters must be on a separate line from the contents of
the string. This means we can't have 'multi-line' strings that do not span
multiple lines of source code.

Since the closing delimiter's indentation is independent of the position of
the opening delimiter, and cannot be on the same line as the string
contents, this opens the door to basing the relative indentation off the
closing delimiter. (It also avoids needing information from the scanner to
manage indentation.)

> What control knobs do we have, that we could assign meaning to, that
would let the user choose either way?

The position of the closing delimiter.

> Do we allow content on the same lines as the delimiters?

No

> How do we interpret auto-alignment on single-line strings? Strip?

Single-line strings cannot use `"""`, since we require the delimiters to be
on their own line.

> Should we always add a final newline?
> Should we strip blanks lines?  Only on the first and last?  All leading
and trailing?
> Should we right strip lines?

Maybe (read on for some discussion of trailing newlines). For the most part
the other choices don't affect the following examples.

Examples:

String a = """
           +--------+
           |  text  |
           +--------+
           """; // first characters in first column?

Actual:

+--------+\n
|  text  |\n
+--------+

String b = """
               +--------+
               |  text  |
               +--------+
           """; // first characters in first column or indented four spaces?

Actual: +4 indentation relative to closing delimiter:

    +--------+\n
    |  text  |\n
    +--------+

String c = """
               +--------+
               |  text  |
               +--------+
"""; // first characters in first column or indented several?

Actual: indented several, relative to closing delimiter:

               +--------+\n
               |  text  |\n
               +--------+

String d = """
    +--------+
    |  text  |
    +--------+
"""; // first characters in first column or indented four?

Actual: +4 indentation relative to closing delimiter:

    +--------+\n
    |  text  |\n
    +--------+

String e =
"""
+--------+
|  text  |
+--------+
"""; // heredoc?

Actual:

+--------+\n
|  text  |\n
+--------+

String f = """


               +--------+
               |  text  |
               +--------+


           """; // one or all leading or trailing blank lines stripped?

Actual:

           \n
           \n
           +--------+\n
           |  text  |\n
           +--------+\n
           \n


Examples g, h, and i are disallowed, since delimiters must be on their own
line.

For j, since delimiters must be on their own line, we'd need something like:

String j = """
           public static void
           """
           + " " + name
           + """
           (String... args) {
               System.out.println(String.join(args));
           }
           """;

Using a multi-line string for "public static void" is unnecessary, but I
kept that to illustrate what concatenation looks like with multi-line
strings. This example suggests we'd usually prefer `String.format` to
concatenating multi-line strings under this approach.

Conclusions:

Requiring delimiters to be on their own line rules out some
potentially surprising edge-cases, and allows indentation management to
work without special knowledge from the scanner. It also provides a
convenient opt-out mechanism if leading indentation is desired.

One disadvantage is the handling of the trailing newline. Requiring the
closing delimiter to be on its own line means there's always a trailing
newline in source. If we want to allow expressing multi-line strings that
don't have a trailing newline we could automatically trim one trailing
newline character, but then it would be necessary to leave an extra blank
line after multi-line strings in cases where a trailing newline is actually
desired. Example:

String message = """
        hello
        world

        """;

Actual:

hello\n
world\n
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20190416/4f3cb431/attachment-0001.html>


More information about the amber-spec-experts mailing list