diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/GloballyQualifiedTypeInStringInterpolation.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/GloballyQualifiedTypeInStringInterpolation.cs index d15031502..c4d1acb50 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/GloballyQualifiedTypeInStringInterpolation.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/GloballyQualifiedTypeInStringInterpolation.cs @@ -2,6 +2,20 @@ { public static class GloballyQualifiedTypeInStringInterpolation { - public static string CurrentDateTime => $"Time: {(global::System.DateTime.Now)}"; + public static string Root => $"Prefix {(global::System.DateTime.Now)} suffix"; + public static string Cast => $"Prefix {((int)global::System.DateTime.Now.Ticks)} suffix"; + public static string Lambda1 => $"Prefix {(global::System.Func)(() => global::System.DateTime.Now)} suffix"; + public static string Lambda2 => $"Prefix {((global::System.Func)(() => global::System.DateTime.Now))()} suffix"; + public static string Method1 => $"Prefix {M(global::System.DateTime.Now)} suffix"; + public static string Method2 => $"Prefix {(global::System.DateTime.Now.Ticks)} suffix"; + public static string Method3 => $"Prefix {(global::System.DateTime.Equals(global::System.DateTime.Now, global::System.DateTime.Now))} suffix"; + public static string ConditionalExpression1 => $"Prefix {(Boolean ? global::System.DateTime.Now : global::System.DateTime.UtcNow)} suffix"; + public static string ConditionalExpression2 => $"Prefix {(Boolean ? global::System.DateTime.Now : global::System.DateTime.UtcNow).Ticks} suffix"; + + private static bool Boolean => false; + private static long M(global::System.DateTime time) + { + return time.Ticks; + } } } diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs index 4d3f2143d..ac20204c4 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs @@ -393,9 +393,31 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public override void VisitInterpolation(Interpolation interpolation) { // If an interpolation contains global::, we need to parenthesize the expression. - if (interpolation.Descendants.Any(n => n is MemberType { IsDoubleColon: true })) + if (InterpolationNeedsParenthesized(interpolation)) Parenthesize(interpolation.Expression); base.VisitInterpolation(interpolation); + + static bool InterpolationNeedsParenthesized(AstNode node) + { + if (node is MemberType { IsDoubleColon: true }) + return true; + + if (node is ConditionalExpression) + return false; // Conditional expressions are parenthesized in their own visit method. + if (node is AnonymousMethodExpression or LambdaExpression) + return false; + if (node is InvocationExpression invocation) + return InterpolationNeedsParenthesized(invocation.Target); + if (node is CastExpression cast) + return InterpolationNeedsParenthesized(cast.Expression); + + foreach (var child in node.Children) + { + if (InterpolationNeedsParenthesized(child)) + return true; + } + return false; + } } // Conditional operator