8282434: Leading combining diacritic character in string renders incorrectly

Reviewed-by: vromero
This commit is contained in:
Jan Lahoda 2022-09-06 08:42:45 +00:00
parent ef20ffe4d2
commit 4955835249
2 changed files with 55 additions and 19 deletions

View File

@ -24,6 +24,7 @@
*/
package jdk.jshell.execution;
import java.lang.Character.UnicodeBlock;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
@ -222,26 +223,32 @@ public class DirectExecutionControl implements ExecutionControl {
if (value == null) {
return "null";
} else if (value instanceof String) {
return "\"" + ((String) value).codePoints()
.flatMap(cp ->
(cp == '"')
? "\\\"".codePoints()
: (cp < 256)
? charRep[cp].codePoints()
: IntStream.of(cp))
.collect(
StringBuilder::new,
StringBuilder::appendCodePoint,
StringBuilder::append)
.toString() + "\"";
StringBuilder result = new StringBuilder();
result.append("\"");
var cpIt = ((String) value).codePoints().iterator();
int idx = 0;
while (cpIt.hasNext()) {
int cp = cpIt.nextInt();
if (cp == '"') {
result.append("\\\"");
} else {
appendEscapedChar(idx, cp, result);
}
idx++;
}
result.append("\"");
return result.toString();
} else if (value instanceof Character) {
char cp = (char) (Character) value;
return "'" + (
(cp == '\'')
? "\\\'"
: (cp < 256)
? charRep[cp]
: String.valueOf(cp)) + "'";
StringBuilder result = new StringBuilder();
result.append("'");
if (cp == '\'') {
result.append("\\\'");
} else {
appendEscapedChar(0, cp, result);
}
result.append("'");
return result.toString();
} else if (value.getClass().isArray()) {
int dims = 0;
Class<?> t = value.getClass();
@ -277,6 +284,29 @@ public class DirectExecutionControl implements ExecutionControl {
}
}
private static void appendEscapedChar(int idx, int cp, StringBuilder target) {
if (cp < 256) {
target.append(charRep[cp]);
} else if (needsEscape(idx, cp)) {
target.append(String.format("\\u%04X", cp));
} else {
target.appendCodePoint(cp);
}
}
private static boolean needsEscape(int idx, int cp) {
UnicodeBlock block = UnicodeBlock.of(cp);
if (block == UnicodeBlock.COMBINING_DIACRITICAL_MARKS ||
block == UnicodeBlock.COMBINING_DIACRITICAL_MARKS_EXTENDED ||
block == UnicodeBlock.COMBINING_DIACRITICAL_MARKS_SUPPLEMENT) {
//escape leading combining diacritical marks,
//as those might be confusingly merged into the leading quotes:
return idx == 0;
} else {
return false;
}
}
/**
* Converts incoming exceptions in user code into instances of subtypes of
* {@link ExecutionControl.ExecutionControlException} and throws the

View File

@ -22,7 +22,7 @@
*/
/*
* @test 8130450 8158906 8154374 8166400 8171892 8173807 8173848
* @test 8130450 8158906 8154374 8166400 8171892 8173807 8173848 8282434
* @summary simple regression test
* @build KullaTesting TestingInputStream
* @run testng SimpleRegressionTest
@ -207,6 +207,10 @@ public class SimpleRegressionTest extends KullaTesting {
"\"\"");
assertEval("(String)null",
"null");
assertEval("\"\\u032Ea\"",
"\"\\u032Ea\"");
assertEval("\"a\\u032Ea\"",
"\"a\u032Ea\"");
}
public void testCharRepresentation() {
@ -222,5 +226,7 @@ public class SimpleRegressionTest extends KullaTesting {
"'\\035'");
assertEval("\"a\\bb\\tc\\nd\\fe\\rf\\\"g'\\\\h\".charAt(1)",
"'\\b'");
assertEval("\"\\u032E\".charAt(0)",
"'\\u032E'");
}
}