From cf5f10067e74fe688c0c2a47e50c17c66b68a1c3 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 20 Jul 2024 09:28:31 +0200 Subject: [PATCH] CallBuilder: Extract handling of interpolated string pattern into separate method. --- ICSharpCode.Decompiler/CSharp/CallBuilder.cs | 135 ++++++++++--------- 1 file changed, 73 insertions(+), 62 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs index 40778477e8..3ceeeaf60d 100644 --- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs @@ -345,69 +345,11 @@ public ExpressionWithResolveResult Build(OpCode callOpCode, IMethod method, argumentList.GetArgumentResolveResults(), isExpandedForm: argumentList.IsExpandedForm, isDelegateInvocation: true)); } - if (settings.StringInterpolation && IsInterpolatedStringCreation(method, argumentList) && - TryGetStringInterpolationTokens(argumentList, out string format, out var tokens)) + if (settings.StringInterpolation && IsInterpolatedStringCreation(method, argumentList)) { - var arguments = argumentList.Arguments; - var content = new List(); - - bool unpackSingleElementArray = !argumentList.IsExpandedForm && argumentList.Length == 2 - && argumentList.Arguments[1].Expression is ArrayCreateExpression ace - && ace.Initializer?.Elements.Count == 1; - - void UnpackSingleElementArray(ref TranslatedExpression argument) - { - if (!unpackSingleElementArray) - return; - var arrayCreation = (ArrayCreateExpression)argumentList.Arguments[1].Expression; - var arrayCreationRR = (ArrayCreateResolveResult)argumentList.Arguments[1].ResolveResult; - var element = arrayCreation.Initializer.Elements.First().Detach(); - argument = new TranslatedExpression(element, arrayCreationRR.InitializerElements.First()); - } - - if (tokens.Count > 0) - { - foreach (var (kind, index, alignment, text) in tokens) - { - TranslatedExpression argument; - switch (kind) - { - case TokenKind.String: - content.Add(new InterpolatedStringText(text)); - break; - case TokenKind.Argument: - argument = arguments[index + 1]; - UnpackSingleElementArray(ref argument); - content.Add(new Interpolation(argument)); - break; - case TokenKind.ArgumentWithFormat: - argument = arguments[index + 1]; - UnpackSingleElementArray(ref argument); - content.Add(new Interpolation(argument, suffix: text)); - break; - case TokenKind.ArgumentWithAlignment: - argument = arguments[index + 1]; - UnpackSingleElementArray(ref argument); - content.Add(new Interpolation(argument, alignment)); - break; - case TokenKind.ArgumentWithAlignmentAndFormat: - argument = arguments[index + 1]; - UnpackSingleElementArray(ref argument); - content.Add(new Interpolation(argument, alignment, text)); - break; - } - } - var formattableStringType = expressionBuilder.compilation.FindType(KnownTypeCode.FormattableString); - var isrr = new InterpolatedStringResolveResult(expressionBuilder.compilation.FindType(KnownTypeCode.String), - format, argumentList.GetArgumentResolveResults(1).ToArray()); - var expr = new InterpolatedStringExpression(); - expr.Content.AddRange(content); - if (method.Name == "Format") - return expr.WithRR(isrr); - return new CastExpression(expressionBuilder.ConvertType(formattableStringType), - expr.WithRR(isrr)) - .WithRR(new ConversionResolveResult(formattableStringType, isrr, Conversion.ImplicitInterpolatedStringConversion)); - } + var result = HandleStringInterpolation(method, argumentList); + if (result.Expression != null) + return result; } int allowedParamCount = (method.ReturnType.IsKnownType(KnownTypeCode.Void) ? 1 : 0); @@ -482,6 +424,75 @@ void UnpackSingleElementArray(ref TranslatedExpression argument) argumentList.GetArgumentResolveResultsDirect(), isExpandedForm: argumentList.IsExpandedForm)); } + private ExpressionWithResolveResult HandleStringInterpolation(IMethod method, ArgumentList argumentList) + { + if (!TryGetStringInterpolationTokens(argumentList, out string format, out var tokens)) + return default; + + var arguments = argumentList.Arguments; + var content = new List(); + + bool unpackSingleElementArray = !argumentList.IsExpandedForm && argumentList.Length == 2 + && argumentList.Arguments[1].Expression is ArrayCreateExpression ace + && ace.Initializer?.Elements.Count == 1; + + void UnpackSingleElementArray(ref TranslatedExpression argument) + { + if (!unpackSingleElementArray) + return; + var arrayCreation = (ArrayCreateExpression)argumentList.Arguments[1].Expression; + var arrayCreationRR = (ArrayCreateResolveResult)argumentList.Arguments[1].ResolveResult; + var element = arrayCreation.Initializer.Elements.First().Detach(); + argument = new TranslatedExpression(element, arrayCreationRR.InitializerElements.First()); + } + + if (tokens.Count == 0) + { + return default; + } + + foreach (var (kind, index, alignment, text) in tokens) + { + TranslatedExpression argument; + switch (kind) + { + case TokenKind.String: + content.Add(new InterpolatedStringText(text)); + break; + case TokenKind.Argument: + argument = arguments[index + 1]; + UnpackSingleElementArray(ref argument); + content.Add(new Interpolation(argument)); + break; + case TokenKind.ArgumentWithFormat: + argument = arguments[index + 1]; + UnpackSingleElementArray(ref argument); + content.Add(new Interpolation(argument, suffix: text)); + break; + case TokenKind.ArgumentWithAlignment: + argument = arguments[index + 1]; + UnpackSingleElementArray(ref argument); + content.Add(new Interpolation(argument, alignment)); + break; + case TokenKind.ArgumentWithAlignmentAndFormat: + argument = arguments[index + 1]; + UnpackSingleElementArray(ref argument); + content.Add(new Interpolation(argument, alignment, text)); + break; + } + } + var formattableStringType = expressionBuilder.compilation.FindType(KnownTypeCode.FormattableString); + var isrr = new InterpolatedStringResolveResult(expressionBuilder.compilation.FindType(KnownTypeCode.String), + format, argumentList.GetArgumentResolveResults(1).ToArray()); + var expr = new InterpolatedStringExpression(); + expr.Content.AddRange(content); + if (method.Name == "Format") + return expr.WithRR(isrr); + return new CastExpression(expressionBuilder.ConvertType(formattableStringType), + expr.WithRR(isrr)) + .WithRR(new ConversionResolveResult(formattableStringType, isrr, Conversion.ImplicitInterpolatedStringConversion)); + } + /// /// Converts a call to an Add method to a collection initializer expression. ///