diff --git a/JavaToCSharp.Tests/IntegrationTests.cs b/JavaToCSharp.Tests/IntegrationTests.cs index ec753c8..8d121e1 100644 --- a/JavaToCSharp.Tests/IntegrationTests.cs +++ b/JavaToCSharp.Tests/IntegrationTests.cs @@ -67,6 +67,7 @@ public void GeneralUnsuccessfulConversionTest(string filePath) [InlineData("Resources/Java9PrivateInterfaceMethods.java")] [InlineData("Resources/Java10TypeInference.java")] [InlineData("Resources/Java14SwitchExpressions.java")] + [InlineData("Resources/Java15TextBlocks.java")] [InlineData("Resources/NewArrayLiteralBug.java")] [InlineData("Resources/OctalLiteralBug.java")] [InlineData("Resources/DeprecatedAnnotation.java")] diff --git a/JavaToCSharp.Tests/Resources/Java15TextBlocks.java b/JavaToCSharp.Tests/Resources/Java15TextBlocks.java new file mode 100644 index 0000000..1273cc4 --- /dev/null +++ b/JavaToCSharp.Tests/Resources/Java15TextBlocks.java @@ -0,0 +1,33 @@ +/// Expect: +/// - output: "\n
hi\n\n|he said \"\"quoted\"\" ok\n|a b\tc\n" +package example; + +// https://docs.oracle.com/en/java/javase/15/language/text-blocks.html + +public class Program { + public static void main(String[] args) { + String html = """ + + hi + + """; + + // Two adjacent quotes are legal inside a text block, and require a longer + // delimiter when converted to a C# raw string literal. + String quotes = """ + he said ""quoted"" ok + """; + + // \s keeps a trailing space, a trailing backslash joins lines, and \t is a tab. + String escapes = """ + a\s\ + b\tc + """; + + System.out.print(html); + System.out.print("|"); + System.out.print(quotes); + System.out.print("|"); + System.out.print(escapes); + } +} diff --git a/JavaToCSharp.Tests/VisitLiteralExpressionTests.cs b/JavaToCSharp.Tests/VisitLiteralExpressionTests.cs index cf5aaa6..6785419 100644 --- a/JavaToCSharp.Tests/VisitLiteralExpressionTests.cs +++ b/JavaToCSharp.Tests/VisitLiteralExpressionTests.cs @@ -19,6 +19,23 @@ public void VisitLiteralExpression_String() Assert.Equal("\\r", expr?.GetFirstToken().ValueText); } + [Theory] + // The value is written as it appears in Java source, indented under the opening """. + [InlineData(" a\n b\n ", "a\nb\n")] + [InlineData(" \n hi\n \n ", "\n hi\n\n")] + // Escapes are resolved once: \t stays a tab and \\ collapses to a single backslash. + [InlineData(" tab\there \\\\ backslash\n ", "tab\there \\ backslash\n")] + // Two adjacent quotes need a four-quote delimiter in the generated C#. + [InlineData(" he said \"\"quoted\"\" ok\n ", "he said \"\"quoted\"\" ok\n")] + public void VisitLiteralExpression_TextBlock(string javaValue, string expected) + { + var expr = ExpressionVisitor.VisitExpression( + new ConversionContext(new JavaConversionOptions()), + new TextBlockLiteralExpr(javaValue)); + + Assert.Equal(expected, expr?.GetFirstToken().ValueText); + } + [Theory] [InlineData("0b10", 2)] [InlineData("0b100", 4)] diff --git a/JavaToCSharp/Expressions/ExpressionVisitor.cs b/JavaToCSharp/Expressions/ExpressionVisitor.cs index 0f26be1..9b5ab0e 100644 --- a/JavaToCSharp/Expressions/ExpressionVisitor.cs +++ b/JavaToCSharp/Expressions/ExpressionVisitor.cs @@ -48,6 +48,7 @@ static ExpressionVisitor() { typeof(MethodReferenceExpr), new MethodReferenceExpressionVisitor() }, { typeof(TypeExpr), new TypeExpressionVisitor() }, { typeof(SwitchExpr), new SwitchExpressionVisitor() }, + { typeof(TextBlockLiteralExpr), new TextBlockLiteralExpressionVisitor() }, }; } diff --git a/JavaToCSharp/Expressions/TextBlockLiteralExpressionVisitor.cs b/JavaToCSharp/Expressions/TextBlockLiteralExpressionVisitor.cs new file mode 100644 index 0000000..8e2c0fd --- /dev/null +++ b/JavaToCSharp/Expressions/TextBlockLiteralExpressionVisitor.cs @@ -0,0 +1,57 @@ +using com.github.javaparser.ast.expr; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace JavaToCSharp.Expressions; + +public class TextBlockLiteralExpressionVisitor : ExpressionVisitor