From 2a3c703e0990326f894316eebc569eee716a89bb Mon Sep 17 00:00:00 2001 From: Victor Irzak Date: Fri, 26 Apr 2024 10:56:12 -0400 Subject: [PATCH] Fix #74 Prevent a crash when there's a complex expression to the left of the dot in an extension method --- .../AsyncToSyncRewriter.cs | 2 +- tests/Generator.Tests/ExtensionMethodTests.cs | 73 +++++++++++++++++++ ...Test#Tests.Class.MethodAsync.g.verified.cs | 11 +++ ...s.HasGeneric2ExtensionAsync.g.verified.cs} | 0 ...ns.HasGenericExtensionAsync.g.verified.cs} | 0 tests/Generator.Tests/UnitTests.cs | 45 ------------ 6 files changed, 85 insertions(+), 46 deletions(-) create mode 100644 tests/Generator.Tests/ExtensionMethodTests.cs create mode 100644 tests/Generator.Tests/Snapshots/ExtensionMethodTests.LeftOfTheDotTest#Tests.Class.MethodAsync.g.verified.cs rename tests/Generator.Tests/Snapshots/{UnitTests.UnwrapGenericExtensionMethod#Zomp.SyncMethodGenerator.IntegrationTests.Extensions.HasGeneric2ExtensionAsync.g.verified.cs => ExtensionMethodTests.UnwrapGenericExtensionMethod#Zomp.SyncMethodGenerator.IntegrationTests.Extensions.HasGeneric2ExtensionAsync.g.verified.cs} (100%) rename tests/Generator.Tests/Snapshots/{UnitTests.UnwrapGenericExtensionMethod#Zomp.SyncMethodGenerator.IntegrationTests.Extensions.HasGenericExtensionAsync.g.verified.cs => ExtensionMethodTests.UnwrapGenericExtensionMethod#Zomp.SyncMethodGenerator.IntegrationTests.Extensions.HasGenericExtensionAsync.g.verified.cs} (100%) diff --git a/src/Zomp.SyncMethodGenerator/AsyncToSyncRewriter.cs b/src/Zomp.SyncMethodGenerator/AsyncToSyncRewriter.cs index 9e0b083..e92c3ab 100644 --- a/src/Zomp.SyncMethodGenerator/AsyncToSyncRewriter.cs +++ b/src/Zomp.SyncMethodGenerator/AsyncToSyncRewriter.cs @@ -133,7 +133,7 @@ static BinaryExpressionSyntax CheckNull(ExpressionSyntax expr) => BinaryExpressi CastExpression(NullableType(IdentifierName(SystemObject)), expr).AppendSpace(), LiteralExpression(SyntaxKind.NullLiteralExpression).PrependSpace()); - var argumentType = GetSymbol(leftOfTheDot) ?? throw new InvalidOperationException("Can't process"); + var argumentType = GetSymbol(node.Expression) ?? throw new InvalidOperationException("Can't process"); var funcArgumentType = GetReturnType(argumentType); IdentifierNameSyntax toCheckForNullExpr; diff --git a/tests/Generator.Tests/ExtensionMethodTests.cs b/tests/Generator.Tests/ExtensionMethodTests.cs new file mode 100644 index 0000000..2a43890 --- /dev/null +++ b/tests/Generator.Tests/ExtensionMethodTests.cs @@ -0,0 +1,73 @@ +namespace Generator.Tests; + +public class ExtensionMethodTests +{ + [Fact] + public Task UnwrapGenericExtensionMethod() => """ +using System.Drawing; +using System.Threading; +using System.Threading.Tasks; + +namespace Zomp.SyncMethodGenerator.IntegrationTests +{ + using Extensi.ons123; + partial class Extensions + { + [CreateSyncVersion] + public static async Task HasGenericExtensionAsync(object o, CancellationToken ct) + { + var z = o.TryGetValue(out var item); + } + + [CreateSyncVersion] + public static async Task HasGeneric2ExtensionAsync(object o, CancellationToken ct) + { + var z = o.TryGetValue(out var _, out var _1); + } + } +} + +namespace Extensi.ons123 +{ + internal static class MyExtensionClass + { + public static bool TryGetValue(this object _, out T? item) + { + item = default; + return false; + } + + public static bool TryGetValue(this object _, out T1? item1, out T2? item2) + { + item1 = default; + item2 = default; + return false; + } + } +} +""".Verify(sourceType: SourceType.Full); + + [Fact] + public Task LeftOfTheDotTest() => """ +namespace Tests; + +internal class Bar +{ + public static Bar Create() => new Bar(); +} + +partial class Class +{ + [Zomp.SyncMethodGenerator.CreateSyncVersion] + public async Task MethodAsync() + { + _ = Bar.Create()?.DoSomething(); + } +} + +internal static class BarExtension +{ + public static Bar DoSomething(this Bar bar) => bar; +} +""".Verify(sourceType: SourceType.Full); +} diff --git a/tests/Generator.Tests/Snapshots/ExtensionMethodTests.LeftOfTheDotTest#Tests.Class.MethodAsync.g.verified.cs b/tests/Generator.Tests/Snapshots/ExtensionMethodTests.LeftOfTheDotTest#Tests.Class.MethodAsync.g.verified.cs new file mode 100644 index 0000000..70609de --- /dev/null +++ b/tests/Generator.Tests/Snapshots/ExtensionMethodTests.LeftOfTheDotTest#Tests.Class.MethodAsync.g.verified.cs @@ -0,0 +1,11 @@ +//HintName: Tests.Class.MethodAsync.g.cs +// +#nullable enable +namespace Tests; +partial class Class +{ + public void Method() + { + _ = ((global::System.Func)((param)=>(object?)param == null?(global::Tests.Bar?)null: global::Tests.BarExtension.DoSomething(param)))(global::Tests.Bar.Create()); + } +} diff --git a/tests/Generator.Tests/Snapshots/UnitTests.UnwrapGenericExtensionMethod#Zomp.SyncMethodGenerator.IntegrationTests.Extensions.HasGeneric2ExtensionAsync.g.verified.cs b/tests/Generator.Tests/Snapshots/ExtensionMethodTests.UnwrapGenericExtensionMethod#Zomp.SyncMethodGenerator.IntegrationTests.Extensions.HasGeneric2ExtensionAsync.g.verified.cs similarity index 100% rename from tests/Generator.Tests/Snapshots/UnitTests.UnwrapGenericExtensionMethod#Zomp.SyncMethodGenerator.IntegrationTests.Extensions.HasGeneric2ExtensionAsync.g.verified.cs rename to tests/Generator.Tests/Snapshots/ExtensionMethodTests.UnwrapGenericExtensionMethod#Zomp.SyncMethodGenerator.IntegrationTests.Extensions.HasGeneric2ExtensionAsync.g.verified.cs diff --git a/tests/Generator.Tests/Snapshots/UnitTests.UnwrapGenericExtensionMethod#Zomp.SyncMethodGenerator.IntegrationTests.Extensions.HasGenericExtensionAsync.g.verified.cs b/tests/Generator.Tests/Snapshots/ExtensionMethodTests.UnwrapGenericExtensionMethod#Zomp.SyncMethodGenerator.IntegrationTests.Extensions.HasGenericExtensionAsync.g.verified.cs similarity index 100% rename from tests/Generator.Tests/Snapshots/UnitTests.UnwrapGenericExtensionMethod#Zomp.SyncMethodGenerator.IntegrationTests.Extensions.HasGenericExtensionAsync.g.verified.cs rename to tests/Generator.Tests/Snapshots/ExtensionMethodTests.UnwrapGenericExtensionMethod#Zomp.SyncMethodGenerator.IntegrationTests.Extensions.HasGenericExtensionAsync.g.verified.cs diff --git a/tests/Generator.Tests/UnitTests.cs b/tests/Generator.Tests/UnitTests.cs index b50aa69..94f3561 100644 --- a/tests/Generator.Tests/UnitTests.cs +++ b/tests/Generator.Tests/UnitTests.cs @@ -643,51 +643,6 @@ These comments shouldn't show #endregion } -""".Verify(sourceType: SourceType.Full); - - [Fact] - public Task UnwrapGenericExtensionMethod() => """ -using System.Drawing; -using System.Threading; -using System.Threading.Tasks; - -namespace Zomp.SyncMethodGenerator.IntegrationTests -{ - using Extensi.ons123; - partial class Extensions - { - [CreateSyncVersion] - public static async Task HasGenericExtensionAsync(object o, CancellationToken ct) - { - var z = o.TryGetValue(out var item); - } - - [CreateSyncVersion] - public static async Task HasGeneric2ExtensionAsync(object o, CancellationToken ct) - { - var z = o.TryGetValue(out var _, out var _1); - } - } -} - -namespace Extensi.ons123 -{ - internal static class MyExtensionClass - { - public static bool TryGetValue(this object _, out T? item) - { - item = default; - return false; - } - - public static bool TryGetValue(this object _, out T1? item1, out T2? item2) - { - item1 = default; - item2 = default; - return false; - } - } -} """.Verify(sourceType: SourceType.Full); #if NETCOREAPP1_0_OR_GREATER