Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CodeConverter/CSharp/LiteralConversions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ internal static string EscapeQuotes(string unquotedTextForUser, string valueText
return EscapeVerbatimQuotes(valueTextForCompiler);
}

return unquotedTextForUser.Replace("\"\"", "\\\"");
return SymbolDisplay.FormatLiteral(valueTextForCompiler, false).Replace("\"", "\\\"");
}

public static string EscapeVerbatimQuotes(string valueTextForCompiler)
Expand Down
59 changes: 59 additions & 0 deletions Tests/CSharp/ExpressionTests/StringExpressionTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,70 @@
using System.Threading.Tasks;
using ICSharpCode.CodeConverter.Common;
using ICSharpCode.CodeConverter.CSharp;
using ICSharpCode.CodeConverter.Tests.Compilation;
using ICSharpCode.CodeConverter.Tests.TestRunners;
using Xunit;

namespace ICSharpCode.CodeConverter.Tests.CSharp.ExpressionTests;

public class StringExpressionTests : ConverterTestBase
{
[Fact]
public async Task NewlineOnlyStringAsync()
{
await TestConversionVisualBasicToCSharpAsync(
"Class TestClass\r\n Private Sub TestMethod()\r\n" +
" Dim tmp = \"\r\n\"\r\n End Sub\r\nEnd Class", @"
internal partial class TestClass
{
private void TestMethod()
{
string tmp = ""\r\n"";
}
}");
}

[Theory]
[InlineData("\r\n")]
[InlineData("\n")]
[InlineData("\r")]
[InlineData("\r\n\r\n")]
[InlineData("first\nsecond")]
[InlineData("first\rsecond")]
[InlineData("quote \" and backslash \\\nend")]
[InlineData("quote \" and backslash \\\r\nend")]
[InlineData("")]
[InlineData("plain \"quoted\" text")]
[InlineData(@"C:\new\folder")]
public async Task StringLiteralPreservesValueAsync(string value)
{
var source = "Public Class C\r\n Public Const Value As String = \"" +
value.Replace("\"", "\"\"") + "\"\r\nEnd Class";
var converted = await ConvertAsync<VBToCSConversion>(source);
var compiler = new CSharpCompiler();
var assembly = compiler.AssemblyFromCode(compiler.CreateTree(converted));
Assert.Equal(value, assembly.GetType("C").GetField("Value").GetRawConstantValue());
}

[Theory]
[InlineData("\r\n")]
[InlineData("\n")]
[InlineData("\r")]
[InlineData("\r\n\r\n")]
[InlineData("\"{braces}\\\n")]
public async Task InterpolatedMultilineStringPreservesValueAsync(string value)
{
var source = "Public Class C\r\n Public Shared Function GetValue() As String\r\n" +
" Dim v1 = 1\r\n Dim v2 = 2\r\n" +
" Return $\"What's up with {v1}" +
value.Replace("\"", "\"\"").Replace("{", "{{").Replace("}", "}}") +
"{v2}\"\r\n End Function\r\nEnd Class";
var converted = await ConvertAsync<VBToCSConversion>(source);
var compiler = new CSharpCompiler();
var assembly = compiler.AssemblyFromCode(compiler.CreateTree(converted));
Assert.Equal("What's up with 1" + value + "2", assembly.GetType("C").GetMethod("GetValue").Invoke(null, null));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In future I'd say for a new type of test, put it in its own file

}

[Fact]
public async Task MultilineStringAsync()
{
Expand Down
Loading