Skip to content

Commit

Permalink
Fix #66 Convert Func<int, Task> into Action<int>
Browse files Browse the repository at this point in the history
  • Loading branch information
virzak committed Mar 20, 2024
1 parent fa72a97 commit 20da318
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 5 deletions.
4 changes: 2 additions & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="N.SourceGenerators.UnionTypes" Version="0.27.0-rc.57" />
<PackageVersion Include="N.SourceGenerators.UnionTypes" Version="0.27.0" />
<PackageVersion Include="Nerdbank.GitVersioning" Version="3.6.133" />
<PackageVersion Include="PolySharp" Version="1.14.1" />
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
Expand All @@ -19,4 +19,4 @@
<PackageVersion Include="xunit" Version="2.7.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.7" />
</ItemGroup>
</Project>
</Project>
61 changes: 58 additions & 3 deletions src/Zomp.SyncMethodGenerator/AsyncToSyncRewriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,22 @@ List<SyntaxTrivia> RemoveFirstEndIf(SyntaxTriviaList list)
public override SyntaxNode? VisitParameter(ParameterSyntax node)
{
var @base = (ParameterSyntax)base.VisitParameter(node)!;

if (node.Type is not null && @base.Type is not null)
{
var originalType = node.Type;
var variableType = GetSymbol(originalType);

if (variableType is INamedTypeSymbol { IsGenericType: true } namedTypeSymbol
&& GetNameWithoutTypeParams(namedTypeSymbol) is SystemFunc)
{
if (ConvertFuncToAction(@base.Type, namedTypeSymbol) is { } newTypeSyntax)
{
return @base.WithType(newTypeSyntax.WithTriviaFrom(originalType));
}
}
}

if (node.Type is null || TypeAlreadyQualified(node.Type))
{
return @base;
Expand Down Expand Up @@ -1056,8 +1072,8 @@ bool ShouldRemoveArgumentLocal(ArgumentSyntax arg, int index)
TypeSyntax? newTypeSyntax = null;

SeparatedSyntaxList<VariableDeclaratorSyntax>? separatedVariableNames = null;
if (variableType is INamedTypeSymbol { IsGenericType: true } n
&& GetNameWithoutTypeParams(n) is SystemFunc)
if (variableType is INamedTypeSymbol { IsGenericType: true } namedTypeSymbol
&& GetNameWithoutTypeParams(namedTypeSymbol) is SystemFunc)
{
var newVariableNames = new List<VariableDeclaratorSyntax>();
foreach (var variable in @base.Declaration.Variables)
Expand All @@ -1066,7 +1082,12 @@ bool ShouldRemoveArgumentLocal(ArgumentSyntax arg, int index)
.WithTrailingTrivia(variable.Identifier.TrailingTrivia).WithInitializer(variable.Initializer));
}

var typeArgs = n.TypeArguments;
var typeArgs = namedTypeSymbol.TypeArguments;

if (ConvertFuncToAction(@base.Declaration.Type, namedTypeSymbol) is { } newTypeSyntax2)
{
newTypeSyntax = newTypeSyntax2;
}

if (typeArgs[^1].ToString() is TaskType or ValueTaskType
&& @base.Declaration.Type is GenericNameSyntax gns)
Expand Down Expand Up @@ -1605,6 +1626,40 @@ private static string GetNewName(IMethodSymbol methodSymbol)
return replacement;
}

private static TypeSyntax? ConvertFuncToAction(TypeSyntax originalType, INamedTypeSymbol namedTypeSymbol)
{
var typeArgs = namedTypeSymbol.TypeArguments;

if (typeArgs[^1].ToString() is not TaskType and not ValueTaskType
|| originalType is not GenericNameSyntax gns)
{
return null;
}

TypeSyntax newTypeSyntax;
var newType = Global("System.Action");

var list = new List<TypeSyntax>();
if (typeArgs.Length > 1)
{
for (var i = 0; i < typeArgs.Length - 1; i++)
{
list.Add(ProcessSymbol(typeArgs[i]));
}

var originalSeparators = gns.TypeArgumentList.Arguments.GetSeparators();

var separatedList = SeparatedList(list, originalSeparators);
newTypeSyntax = GenericName(Identifier(newType), TypeArgumentList(separatedList));
}
else
{
newTypeSyntax = IdentifierName(newType);
}

return newTypeSyntax;
}

private bool PreProcess(
SyntaxList<StatementSyntax> statements,
Dictionary<int, ExtraNodeInfo> extraNodeInfoList,
Expand Down
9 changes: 9 additions & 0 deletions tests/Generator.Tests/DelegateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ public Task AsyncDelegate() => """
await delAsync();
""".Verify(sourceType: SourceType.MethodBody);

[Fact]
public Task FuncToActionInParameter() => """
[CreateSyncVersion]
async Task MethodAsync(Func<int, Task> bar)
{
await bar(5);
}
""".Verify();

[Theory]
[InlineData(true)]
[InlineData(false)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//HintName: Test.Class.MethodAsync.g.cs
void Method(global::System.Action<int> bar)
{
bar(5);
}

0 comments on commit 20da318

Please sign in to comment.