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
- csr of
-
JDK-8215493 String::indent inconsistency with blank lines
- Resolved