diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.cs index 104417efd..6cd3964b2 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.cs @@ -11,9 +11,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine($"{args.Length:x}"); Console.WriteLine($"\ta{args.Length}b"); Console.WriteLine($"\ta{args.Length}ba{args[0]}a{args[args.Length]}a{args.Length}"); + Console.WriteLine($"\ta{((args.Length != 0) ? 5 : 0)}"); + Console.WriteLine($"\ta{(object)(args ?? args)}"); + Console.WriteLine($"\ta{args[0][0] == 'a'}"); + // This is legal, but we cannot create a pretty test for it, as it would require us + // to convert string literals to string interpolation literals even without a string.Format call. + // I do not think, this is worth the effort. + //Console.WriteLine($"\ta{$"a" == args[0]}"); } - public static void Invalid(string[] args) + public static void InvalidFormatString(string[] args) { Console.WriteLine(string.Format("", args.Length)); Console.WriteLine(string.Format("a", args.Length)); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.opt.roslyn.il index 34f13e90b..1da7e6a41 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.opt.roslyn.il @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module CS6_StringInterpolation.dll -// MVID: {F5FD4CCF-66AB-4E03-8E45-96F42947A65D} +// MVID: {E5F8B296-2C38-455C-B3AC-4CF5B5014FFB} .custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) .imagebase 0x10000000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x03070000 +// Image base: 0x01330000 // =============== CLASS MEMBERS DECLARATION =================== @@ -42,7 +42,7 @@ { .method public hidebysig static void General(string[] args) cil managed { - // Code size 150 (0x96) + // Code size 232 (0xe8) .maxstack 6 IL_0000: ldstr "{0}" IL_0005: ldarg.0 @@ -110,10 +110,45 @@ IL_008b: call string [mscorlib]System.String::Format(string, object[]) IL_0090: call void [mscorlib]System.Console::WriteLine(string) - IL_0095: ret + IL_0095: ldstr "\ta{0}" + IL_009a: ldarg.0 + IL_009b: ldlen + IL_009c: brtrue.s IL_00a1 + + IL_009e: ldc.i4.0 + IL_009f: br.s IL_00a2 + + IL_00a1: ldc.i4.5 + IL_00a2: box [mscorlib]System.Int32 + IL_00a7: call string [mscorlib]System.String::Format(string, + object) + IL_00ac: call void [mscorlib]System.Console::WriteLine(string) + IL_00b1: ldstr "\ta{0}" + IL_00b6: ldarg.0 + IL_00b7: dup + IL_00b8: brtrue.s IL_00bc + + IL_00ba: pop + IL_00bb: ldarg.0 + IL_00bc: call string [mscorlib]System.String::Format(string, + object) + IL_00c1: call void [mscorlib]System.Console::WriteLine(string) + IL_00c6: ldstr "\ta{0}" + IL_00cb: ldarg.0 + IL_00cc: ldc.i4.0 + IL_00cd: ldelem.ref + IL_00ce: ldc.i4.0 + IL_00cf: callvirt instance char [mscorlib]System.String::get_Chars(int32) + IL_00d4: ldc.i4.s 97 + IL_00d6: ceq + IL_00d8: box [mscorlib]System.Boolean + IL_00dd: call string [mscorlib]System.String::Format(string, + object) + IL_00e2: call void [mscorlib]System.Console::WriteLine(string) + IL_00e7: ret } // end of method CS6_StringInterpolation::General - .method public hidebysig static void Invalid(string[] args) cil managed + .method public hidebysig static void InvalidFormatString(string[] args) cil managed { // Code size 556 (0x22c) .maxstack 3 @@ -310,7 +345,7 @@ object) IL_0226: call void [mscorlib]System.Console::WriteLine(string) IL_022b: ret - } // end of method CS6_StringInterpolation::Invalid + } // end of method CS6_StringInterpolation::InvalidFormatString .method public hidebysig specialname rtspecialname instance void .ctor() cil managed diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.roslyn.il index e355bdd8d..c2f5192db 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS6_StringInterpolation.roslyn.il @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module CS6_StringInterpolation.dll -// MVID: {FE9286DD-8C20-4FC8-8786-543E572641EA} +// MVID: {13226DB1-4F60-403F-8874-DA41699044FA} .custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) .imagebase 0x10000000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x03840000 +// Image base: 0x00DD0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -42,7 +42,7 @@ { .method public hidebysig static void General(string[] args) cil managed { - // Code size 156 (0x9c) + // Code size 241 (0xf1) .maxstack 6 IL_0000: nop IL_0001: ldstr "{0}" @@ -116,10 +116,48 @@ object[]) IL_0095: call void [mscorlib]System.Console::WriteLine(string) IL_009a: nop - IL_009b: ret + IL_009b: ldstr "\ta{0}" + IL_00a0: ldarg.0 + IL_00a1: ldlen + IL_00a2: brtrue.s IL_00a7 + + IL_00a4: ldc.i4.0 + IL_00a5: br.s IL_00a8 + + IL_00a7: ldc.i4.5 + IL_00a8: box [mscorlib]System.Int32 + IL_00ad: call string [mscorlib]System.String::Format(string, + object) + IL_00b2: call void [mscorlib]System.Console::WriteLine(string) + IL_00b7: nop + IL_00b8: ldstr "\ta{0}" + IL_00bd: ldarg.0 + IL_00be: dup + IL_00bf: brtrue.s IL_00c3 + + IL_00c1: pop + IL_00c2: ldarg.0 + IL_00c3: call string [mscorlib]System.String::Format(string, + object) + IL_00c8: call void [mscorlib]System.Console::WriteLine(string) + IL_00cd: nop + IL_00ce: ldstr "\ta{0}" + IL_00d3: ldarg.0 + IL_00d4: ldc.i4.0 + IL_00d5: ldelem.ref + IL_00d6: ldc.i4.0 + IL_00d7: callvirt instance char [mscorlib]System.String::get_Chars(int32) + IL_00dc: ldc.i4.s 97 + IL_00de: ceq + IL_00e0: box [mscorlib]System.Boolean + IL_00e5: call string [mscorlib]System.String::Format(string, + object) + IL_00ea: call void [mscorlib]System.Console::WriteLine(string) + IL_00ef: nop + IL_00f0: ret } // end of method CS6_StringInterpolation::General - .method public hidebysig static void Invalid(string[] args) cil managed + .method public hidebysig static void InvalidFormatString(string[] args) cil managed { // Code size 581 (0x245) .maxstack 3 @@ -341,7 +379,7 @@ IL_023e: call void [mscorlib]System.Console::WriteLine(string) IL_0243: nop IL_0244: ret - } // end of method CS6_StringInterpolation::Invalid + } // end of method CS6_StringInterpolation::InvalidFormatString .method public hidebysig specialname rtspecialname instance void .ctor() cil managed diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs b/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs index aaede07e4..622394ca0 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs @@ -152,10 +152,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms content.Add(new InterpolatedStringText(text)); break; case TokenKind.Argument: - content.Add(new Interpolation(arguments[index + 1].Detach())); + content.Add(new Interpolation(WrapInParens(arguments[index + 1].Detach()))); break; case TokenKind.ArgumentWithFormat: - content.Add(new Interpolation(arguments[index + 1].Detach(), text)); + content.Add(new Interpolation(WrapInParens(arguments[index + 1].Detach()), text)); break; } } @@ -201,6 +201,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return; } + Expression WrapInParens(Expression expression) + { + if (expression is ConditionalExpression) + return new ParenthesizedExpression(expression); + return expression; + } + enum TokenKind { Error,