Skip to content

Commit de01dc2

Browse files
Merge pull request #1231 from icsharpcode/fix-gettype-unbound-generics-1958760587701317988
Fix gettype unbound generics #1165
2 parents 2c2b64e + 2bdaa9f commit de01dc2

File tree

3 files changed

+37
-2
lines changed

3 files changed

+37
-2
lines changed

CodeConverter/CSharp/ExpressionNodeVisitor.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -578,8 +578,13 @@ public override async Task<CSharpSyntaxNode> VisitArrayRankSpecifier(VBasic.Synt
578578

579579
public override async Task<CSharpSyntaxNode> VisitTypeArgumentList(VBasic.Syntax.TypeArgumentListSyntax node)
580580
{
581-
var args = await node.Arguments.SelectAsync(async a => await a.AcceptAsync<TypeSyntax>(TriviaConvertingExpressionVisitor));
582-
return CS.SyntaxFactory.TypeArgumentList(CS.SyntaxFactory.SeparatedList(args));
581+
var args = await node.Arguments.SelectAsync(async a => {
582+
if (a is VBasic.Syntax.IdentifierNameSyntax id && id.Identifier.IsMissing) {
583+
return CS.SyntaxFactory.OmittedTypeArgument();
584+
}
585+
return await a.AcceptAsync<TypeSyntax>(TriviaConvertingExpressionVisitor);
586+
});
587+
return CS.SyntaxFactory.TypeArgumentList(CS.SyntaxFactory.SeparatedList<TypeSyntax>(args));
583588
}
584589

585590
private async Task<CSharpSyntaxNode> ConvertCastExpressionAsync(VBSyntax.CastExpressionSyntax node,

CodeConverter/CSharp/VbNameExpander.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ private static bool NameCanBeExpanded(SyntaxNode node)
110110
if (node.Parent is NameColonEqualsSyntax || node.Parent is NamedFieldInitializerSyntax) return false;
111111
// Workaround roslyn bug where it duplicates the inferred name
112112
if (node.Parent is InferredFieldInitializerSyntax) return false;
113+
// Roslyn's Simplifier.Expand corrupts open generic type arguments (e.g. Nullable(Of) in GetType(Nullable(Of)))
114+
// by replacing them with the error type fallback (Object). Prevent expansion so the missing type arg is preserved.
115+
if (node is GenericNameSyntax gns && gns.TypeArgumentList.Arguments.Any(a => a is IdentifierNameSyntax id && id.Identifier.IsMissing)) return false;
113116
return true;
114117
}
115118

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using ICSharpCode.CodeConverter.Tests.TestRunners;
4+
using Xunit;
5+
6+
namespace ICSharpCode.CodeConverter.Tests.CSharp.ExpressionTests;
7+
8+
public class OmittedTypeArgumentTest : ConverterTestBase
9+
{
10+
[Fact]
11+
public async Task TestGetTypeOmittedArgument()
12+
{
13+
await TestConversionVisualBasicToCSharpAsync(@"Public Class Test
14+
Public Function IsNullable(ByVal type As Type) As Boolean
15+
Return type.IsGenericType AndAlso type.GetGenericTypeDefinition() Is GetType(Nullable(Of))
16+
End Function
17+
End Class", @"using System;
18+
19+
public partial class Test
20+
{
21+
public bool IsNullable(Type @type)
22+
{
23+
return type.IsGenericType && ReferenceEquals(type.GetGenericTypeDefinition(), typeof(Nullable<>));
24+
}
25+
}");
26+
}
27+
}

0 commit comments

Comments
 (0)