diff --git a/src/main/java/spoon/reflect/visitor/LiteralHelper.java b/src/main/java/spoon/reflect/visitor/LiteralHelper.java index 103893c2d45..02021b02512 100644 --- a/src/main/java/spoon/reflect/visitor/LiteralHelper.java +++ b/src/main/java/spoon/reflect/visitor/LiteralHelper.java @@ -92,7 +92,7 @@ public static String getLiteralToken(CtLiteral literal) { } StringBuilder sb = new StringBuilder(10); sb.append('\''); - appendCharLiteral(sb, (Character) literal.getValue(), mayContainsSpecialCharacter); + appendCharLiteral(sb, (Character) literal.getValue(), mayContainsSpecialCharacter, false); sb.append('\''); return sb.toString(); } else if (literal.getValue() instanceof String) { @@ -113,7 +113,7 @@ public static String getLiteralToken(CtLiteral literal) { } } - static void appendCharLiteral(StringBuilder sb, Character c, boolean mayContainsSpecialCharacter) { + static void appendCharLiteral(StringBuilder sb, Character c, boolean mayContainsSpecialCharacter, boolean isInsideString) { if (!mayContainsSpecialCharacter) { sb.append(c); } else { @@ -137,7 +137,11 @@ static void appendCharLiteral(StringBuilder sb, Character c, boolean mayContains sb.append("\\\""); //$NON-NLS-1$ break; case '\'': - sb.append("\\'"); //$NON-NLS-1$ + if (isInsideString) { + sb.append("'"); //$NON-NLS-1$ + } else { + sb.append("\\'"); //$NON-NLS-1$ + } break; case '\\': // take care not to display the escape as a potential // real char @@ -152,12 +156,11 @@ static void appendCharLiteral(StringBuilder sb, Character c, boolean mayContains static String getStringLiteral(String value, boolean mayContainsSpecialCharacter) { if (!mayContainsSpecialCharacter) { return value; - } else { - StringBuilder sb = new StringBuilder(value.length() * 2); - for (int i = 0; i < value.length(); i++) { - appendCharLiteral(sb, value.charAt(i), mayContainsSpecialCharacter); - } - return sb.toString(); } + StringBuilder sb = new StringBuilder(value.length() * 2); + for (int i = 0; i < value.length(); i++) { + appendCharLiteral(sb, value.charAt(i), true, true); + } + return sb.toString(); } } diff --git a/src/test/java/spoon/test/literal/LiteralTest.java b/src/test/java/spoon/test/literal/LiteralTest.java index 4f39387898e..1047234a16a 100644 --- a/src/test/java/spoon/test/literal/LiteralTest.java +++ b/src/test/java/spoon/test/literal/LiteralTest.java @@ -22,14 +22,16 @@ import spoon.reflect.declaration.CtType; import spoon.reflect.code.CtLiteral; import spoon.reflect.factory.CodeFactory; +import spoon.test.GitHubIssue; import spoon.test.literal.testclasses.Tacos; import spoon.Launcher; import spoon.reflect.code.LiteralBase; +import spoon.reflect.cu.SourcePosition; import spoon.reflect.factory.TypeFactory; import spoon.reflect.declaration.CtClass; import org.junit.jupiter.api.Test; import spoon.testing.utils.ModelTest; - +import java.util.List; import java.util.TreeSet; import static spoon.testing.utils.ModelUtils.buildClass; @@ -257,4 +259,27 @@ public void testLiteralBasePrinter(Factory factory) { assertEquals("'c'", ctClass.getField("c1").getDefaultExpression().toString()); assertEquals("\"hello\"", ctClass.getField("s1").getDefaultExpression().toString()); } + + @GitHubIssue(issueNumber = 5070, fixed = true) + void tooStrictEscaping() { + // contract: inside a string without a position ' are not escaped. + List> literals = Launcher.parseClass("class Foo { String s = \"'\"; }") + .getElements(new TypeFilter<>(CtLiteral.class)); + CtLiteral ctLiteral = literals.get(0); + ctLiteral.setPosition(SourcePosition.NOPOSITION); + String literal = (String) ctLiteral.getValue(); + assertEquals("'", literal); + assertEquals("\"'\"", ctLiteral.toString()); + } + + @GitHubIssue(issueNumber = 5070, fixed = true) + void tooStrictEscapingCharTest() { + // contract: inside a string with a position ' are escaped. + List> literals = Launcher.parseClass("class Foo { char c = \'\\'\'; }") + .getElements(new TypeFilter<>(CtLiteral.class)); + CtLiteral ctLiteral = literals.get(0); + char literal = (char) ctLiteral.getValue(); + assertEquals('\'', literal); + assertEquals("\'\\'\'", ctLiteral.toString()); + } }