Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions CodeConverter/CSharp/ExpressionNodeVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -578,8 +578,13 @@ public override async Task<CSharpSyntaxNode> VisitArrayRankSpecifier(VBasic.Synt

public override async Task<CSharpSyntaxNode> VisitTypeArgumentList(VBasic.Syntax.TypeArgumentListSyntax node)
{
var args = await node.Arguments.SelectAsync(async a => await a.AcceptAsync<TypeSyntax>(TriviaConvertingExpressionVisitor));
return CS.SyntaxFactory.TypeArgumentList(CS.SyntaxFactory.SeparatedList(args));
var args = await node.Arguments.SelectAsync(async a => {
if (a is VBasic.Syntax.IdentifierNameSyntax id && id.Identifier.IsMissing) {
return CS.SyntaxFactory.OmittedTypeArgument();
}
return await a.AcceptAsync<TypeSyntax>(TriviaConvertingExpressionVisitor);
});
return CS.SyntaxFactory.TypeArgumentList(CS.SyntaxFactory.SeparatedList<TypeSyntax>(args));
}

private async Task<CSharpSyntaxNode> ConvertCastExpressionAsync(VBSyntax.CastExpressionSyntax node,
Expand Down
3 changes: 3 additions & 0 deletions CodeConverter/CSharp/VbNameExpander.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ private static bool NameCanBeExpanded(SyntaxNode node)
if (node.Parent is NameColonEqualsSyntax || node.Parent is NamedFieldInitializerSyntax) return false;
// Workaround roslyn bug where it duplicates the inferred name
if (node.Parent is InferredFieldInitializerSyntax) return false;
// Roslyn's Simplifier.Expand corrupts open generic type arguments (e.g. Nullable(Of) in GetType(Nullable(Of)))
// by replacing them with the error type fallback (Object). Prevent expansion so the missing type arg is preserved.
if (node is GenericNameSyntax gns && gns.TypeArgumentList.Arguments.Any(a => a is IdentifierNameSyntax id && id.Identifier.IsMissing)) return false;
return true;
}

Expand Down
27 changes: 27 additions & 0 deletions Tests/CSharp/ExpressionTests/OmittedTypeArgumentTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using System.Threading.Tasks;
using ICSharpCode.CodeConverter.Tests.TestRunners;
using Xunit;

namespace ICSharpCode.CodeConverter.Tests.CSharp.ExpressionTests;

public class OmittedTypeArgumentTest : ConverterTestBase
{
[Fact]
public async Task TestGetTypeOmittedArgument()
{
await TestConversionVisualBasicToCSharpAsync(@"Public Class Test
Public Function IsNullable(ByVal type As Type) As Boolean
Return type.IsGenericType AndAlso type.GetGenericTypeDefinition() Is GetType(Nullable(Of))
End Function
End Class", @"using System;

public partial class Test
{
public bool IsNullable(Type @type)
{
return type.IsGenericType && ReferenceEquals(type.GetGenericTypeDefinition(), typeof(Nullable<>));
}
}");
}
}
Loading