I am trying to analyze with roslyn if a type declaration is a "Nullable Reference" type (C#8)
I was planing on looking if the TypeSyntex
was a NullableTypeSyntax
and if the ITypeSymbol.IsReferenceType
is true
.
The following code works for the most part, but is fails when the declared type is generic i.e. List<T>?
void Main()
{
string text = @"
#nullable enable
public class MyClass
{
public string? Get() => null;
public List<string>? GetGeneric() => null;
}";
SyntaxTree tree = CSharpSyntaxTree.ParseText(text);
PortableExecutableReference mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
CSharpCompilation compilation = CSharpCompilation.Create("RefitCompilation", syntaxTrees: new[] { tree }, references: new[] { mscorlib });
SemanticModel semanticModel = compilation.GetSemanticModel(tree);
MethodDeclarationSyntax nonGenericMethodSyntax = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First();
ITypeSymbol nonGenericReturnType = semanticModel.GetTypeInfo(nonGenericMethodSyntax.ReturnType).Type;
bool isNullableTypeReference = nonGenericMethodSyntax.ReturnType is NullableTypeSyntax && nonGenericReturnType.IsReferenceType;
Console.WriteLine($@"NonGeneric Nullalbe Reference: `{nonGenericMethodSyntax}`
Is Nullable Type Reference: {isNullableTypeReference}
Original Definition: {nonGenericReturnType.OriginalDefinition},
IsNullableTypeSyntax: {nonGenericMethodSyntax.ReturnType is NullableTypeSyntax}
Is Reference Type: {nonGenericReturnType.IsReferenceType}");
Console.WriteLine();
MethodDeclarationSyntax genericMethodSyntax = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().Last();
ITypeSymbol genericReturnType = semanticModel.GetTypeInfo(genericMethodSyntax.ReturnType).Type;
isNullableTypeReference = genericMethodSyntax.ReturnType is NullableTypeSyntax && genericReturnType.IsReferenceType;
Console.WriteLine($@"Generic Nullalbe Reference: `{genericMethodSyntax}`
Is Nullable Type Reference: {isNullableTypeReference}
Original Definition: {genericReturnType.OriginalDefinition},
IsNullableTypeSyntax: {genericMethodSyntax.ReturnType is NullableTypeSyntax}
Is Reference Type: {genericReturnType.IsReferenceType}");
}
which outputs
NonGeneric Nullalbe Reference: `public string? Get() => null;`
Is Nullable Type Reference: True
Original Definition: string,
IsNullableTypeSyntax: True
Is Reference Type: True
Generic Nullalbe Reference: `public List<string>? GetGeneric() => null;`
Is Nullable Type Reference: False
Original Definition: System.Nullable<T>,
IsNullableTypeSyntax: True
Is Reference Type: False
Why is List<T>?
Original Definition System.Nullable<T>
? and how can I determine if a type is a Nullable Reference type?
semanticModel.GetTypeInfo(nonGenericMethodSyntax.ReturnType).Nullability.Annotation
? – BorrerisemanticModel.GetTypeInfo(nonGenericMethodSyntax.ReturnType).Nullability.Annotation
is None.Nullability.FlowState
is None as well – ValloIsReferenceType = true
– Further