diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs index 46cbd3930..3f3c5cf59 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs @@ -221,12 +221,21 @@ namespace ICSharpCode.Decompiler.Tests.Pretty { } +#if CS72 + public static void Do(this ref DateTime test) + { + + } +#endif - public static void Do2(this int test) + public static void Do2(this int test, DateTime date) { test.Do(); ((IEnumerable)null).Any(); ((object)null).Do(); +#if CS72 + date.Do(); +#endif } } } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs index 3b11cd87f..7c64e687d 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs @@ -137,7 +137,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } if (!CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args, argNames)) return; - if (firstArgument is NullReferenceExpression) { + if (firstArgument is DirectionExpression dirExpr) { + if (dirExpr.FieldDirection != FieldDirection.Ref) + return; + if (!context.Settings.RefExtensionMethods) + return; + firstArgument = dirExpr.Expression; + target = firstArgument.GetResolveResult(); + dirExpr.Detach(); + } else if (firstArgument is NullReferenceExpression) { Debug.Assert(context.RequiredNamespacesSuperset.Contains(method.Parameters[0].Type.Namespace)); firstArgument = firstArgument.ReplaceWith(expr => new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.Parameters[0].Type), expr.Detach())); } diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs index 163d58346..8e130da03 100644 --- a/ICSharpCode.Decompiler/DecompilerSettings.cs +++ b/ICSharpCode.Decompiler/DecompilerSettings.cs @@ -97,6 +97,7 @@ namespace ICSharpCode.Decompiler introduceReadonlyAndInModifiers = false; introduceRefModifiersOnStructs = false; nonTrailingNamedArguments = false; + refExtensionMethods = false; } if (languageVersion < CSharp.LanguageVersion.CSharp7_3) { introduceUnmanagedConstraint = false; @@ -114,7 +115,7 @@ namespace ICSharpCode.Decompiler return CSharp.LanguageVersion.CSharp8_0; if (introduceUnmanagedConstraint || tupleComparisons || stackAllocInitializers) return CSharp.LanguageVersion.CSharp7_3; - if (introduceRefModifiersOnStructs || introduceReadonlyAndInModifiers || nonTrailingNamedArguments) + if (introduceRefModifiersOnStructs || introduceReadonlyAndInModifiers || nonTrailingNamedArguments || refExtensionMethods) return CSharp.LanguageVersion.CSharp7_2; // C# 7.1 missing if (outVariables || tupleTypes || tupleConversions || discards || localFunctions) @@ -626,6 +627,23 @@ namespace ICSharpCode.Decompiler } } + bool refExtensionMethods = true; + + /// + /// Gets/Sets whether to use C# 7.2 'ref' extension methods. + /// + [Category("C# 7.2 / VS 2017.4")] + [Description("DecompilerSettings.AllowExtensionMethodSyntaxOnRef")] + public bool RefExtensionMethods { + get { return refExtensionMethods; } + set { + if (refExtensionMethods != value) { + refExtensionMethods = value; + OnPropertyChanged(); + } + } + } + bool stringInterpolation = true; /// diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs index 5c86e06e2..60474f712 100644 --- a/ILSpy/Properties/Resources.Designer.cs +++ b/ILSpy/Properties/Resources.Designer.cs @@ -474,6 +474,15 @@ namespace ICSharpCode.ILSpy.Properties { } } + /// + /// Looks up a localized string similar to Use 'ref' extension methods. + /// + public static string DecompilerSettings_AllowExtensionMethodSyntaxOnRef { + get { + return ResourceManager.GetString("DecompilerSettings.AllowExtensionMethodSyntaxOnRef", resourceCulture); + } + } + /// /// Looks up a localized string similar to Always cast targets of explicit interface implementation calls. /// diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx index 0128389d9..ac22077ae 100644 --- a/ILSpy/Properties/Resources.resx +++ b/ILSpy/Properties/Resources.resx @@ -729,4 +729,7 @@ Entity could not be resolved. Cannot analyze entities from missing assembly references. Add the missing reference and try again. + + Use 'ref' extension methods + \ No newline at end of file