Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8215499

String::indent inconsistency with blank lines

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P3 P3
    • 12
    • core-libs
    • None
    • behavioral
    • minimal
    • The method does not exist in a released version of the JDK, so there can be no external dependency on this behaviour.
    • SE

      Summary

      There is inconsistency with regards to blank lines and indentation. Adding indent space ignores blank lines, where subtraction indentation white space does not ignore blank lines.

      Problem

      The original specification states

          /**
           * Adjusts the indentation of each line of this string based on the value of
           * {@code n}, and normalizes line termination characters.
           * <p>
           * This string is conceptually separated into lines using
           * {@link String#lines()}. Each line is then adjusted as described below
           * and then suffixed with a line feed {@code "\n"} (U+000A). The resulting
           * lines are then concatenated and returned.
           * <p>
           * If {@code n > 0} then {@code n} spaces (U+0020) are inserted at the
           * beginning of each line. {@link String#isBlank() Blank lines} are
           * unaffected.
           * <p>
           * If {@code n < 0} then up to {@code n}
           * {@link Character#isWhitespace(int) white space characters} are removed
           * from the beginning of each line. If a given line does not contain
           * sufficient white space then all leading
           * {@link Character#isWhitespace(int) white space characters} are removed.
           * Each white space character is treated as a single character. In
           * particular, the tab character {@code "\t"} (U+0009) is considered a
           * single character; it is not expanded.
           * <p>
           * If {@code n == 0} then the line remains unchanged. However, line
           * terminators are still normalized.
           *
           * @param n  number of leading
           *           {@link Character#isWhitespace(int) white space characters}
           *           to add or remove
           *
           * @return string with indentation adjusted and line endings normalized
           *
           * @see String#lines()
           * @see String#isBlank()
           * @see Character#isWhitespace(int)
           *
           * @since 12
           */

      Noting that when adding spaces Blank lines are unaffected. This creates an asymmetry between adding and subtracting indentation that can be demonstrated with the following example.

              String input = ( "....abcd\n" +
                               "........\n" +
                               "....efgh\n").replace('.', ' ');
      
              String minus = input.indent(-4)
                                  .lines().map(s -> s + "|")
                                  .collect(Collectors.joining("\n"))
                                  .replace(' ', '.');
      
              String plus  = input.indent(4)
                                  .lines().map(s -> s + "|")
                                  .collect(Collectors.joining("\n"))
                                  .replace(' ', '.');

      Result:

      minus:
      abcd|
      ....|
      efgh|
      
      
      plus:
      ........abcd|
      ........|
      ........efgh|
      

      Solution

      The solution is to remove the condition "Blank lines are unaffected" from the specification with appropriate changes to the implementation.

      Specification

          /**
           * Adjusts the indentation of each line of this string based on the value of
           * {@code n}, and normalizes line termination characters.
           * <p>
           * This string is conceptually separated into lines using
           * {@link String#lines()}. Each line is then adjusted as described below
           * and then suffixed with a line feed {@code "\n"} (U+000A). The resulting
           * lines are then concatenated and returned.
           * <p>
           * If {@code n > 0} then {@code n} spaces (U+0020) are inserted at the
           * beginning of each line.
           * <p>
           * If {@code n < 0} then up to {@code n}
           * {@link Character#isWhitespace(int) white space characters} are removed
           * from the beginning of each line. If a given line does not contain
           * sufficient white space then all leading
           * {@link Character#isWhitespace(int) white space characters} are removed.
           * Each white space character is treated as a single character. In
           * particular, the tab character {@code "\t"} (U+0009) is considered a
           * single character; it is not expanded.
           * <p>
           * If {@code n == 0} then the line remains unchanged. However, line
           * terminators are still normalized.
           *
           * @param n  number of leading
           *           {@link Character#isWhitespace(int) white space characters}
           *           to add or remove
           *
           * @return string with indentation adjusted and line endings normalized
           *
           * @see String#lines()
           * @see String#isBlank()
           * @see Character#isWhitespace(int)
           *
           * @since 12
           */
          public String indent(int n) {
      
      
      --- a/src/java.base/share/classes/java/lang/String.java Sat Dec 08 09:56:55 2018 -0400
      +++ b/src/java.base/share/classes/java/lang/String.java Mon Dec 17 14:32:58 2018 -0400
      @@ -2808,8 +2808,7 @@
            * lines are then concatenated and returned.
            * <p>
            * If {@code n > 0} then {@code n} spaces (U+0020) are inserted at the
      -     * beginning of each line. {@link String#isBlank() Blank lines} are
      -     * unaffected.
      +     * beginning of each line.
            * <p>
            * If {@code n < 0} then up to {@code n}
            * {@link Character#isWhitespace(int) white space characters} are removed

            jlaskey Jim Laskey
            jlaskey Jim Laskey
            Roger Riggs, Stuart Marks
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: