Skip to content

Commit

Permalink
New nullable reference annotation parsing code (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
Shane32 authored Nov 1, 2021
1 parent c3bb6ee commit 5fa69ac
Show file tree
Hide file tree
Showing 8 changed files with 800 additions and 272 deletions.
271 changes: 167 additions & 104 deletions src/GraphQL.DI/DIObjectGraphType.cs

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions src/GraphQL.DI/Nullability.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace GraphQL.DI
{
public enum Nullability : byte
{
Unknown = 0,
NonNullable = 1,
Nullable = 2,
}
}
12 changes: 12 additions & 0 deletions src/GraphQL.DI/NullabilityInformation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace GraphQL.DI
{
internal struct NullabilityInformation
{
public Nullability DefaultNullability;
public Nullability[] Nullability;
}
}
14 changes: 14 additions & 0 deletions src/GraphQL.DI/OptionalListAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace GraphQL.DI
{
/// <summary>
/// Marks a method's (field's) return value as nullable, or
/// marks a parameter's (query argument's) input value to be optional.
/// </summary>
//perhaps this should apply to ReturnValue instead of Method
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class OptionalListAttribute : Attribute
{
}
}
14 changes: 14 additions & 0 deletions src/GraphQL.DI/RequiredListAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace GraphQL.DI
{
/// <summary>
/// Marks a method's (field's) return value as always non-null, or
/// marks a parameter's (query argument's) input value to be required.
/// </summary>
//perhaps this should apply to ReturnValue instead of Method
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class RequiredListAttribute : Attribute
{
}
}
70 changes: 70 additions & 0 deletions src/GraphQL.DI/TypeInformation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace GraphQL.DI
{
/// <summary>
/// Contains type and nullability information for a method return type or argument type.
/// </summary>
public struct TypeInformation
{
/// <summary>
/// The argument or return parameter of the method being inspected.
/// </summary>
public ParameterInfo ParameterInfo;

/// <summary>
/// Indicates that this is an input type (an argument); false for output types.
/// </summary>
public bool IsInputType;

/// <summary>
/// The underlying type represented. This might be the underlying type of a <see cref="Nullable{T}"/>
/// or the underlying type of a <see cref="IEnumerable{T}"/>.
/// </summary>
public Type Type;

/// <summary>
/// Indicates if the underlying type is nullable.
/// </summary>
public bool IsNullable;

/// <summary>
/// Indicates that this represents a list of elements.
/// </summary>
public bool IsList;

/// <summary>
/// Indicates if the list is nullable.
/// </summary>
public bool ListIsNullable;

/// <summary>
/// The graph type of the underlying CLR type.
/// </summary>
public Type? GraphType;

/// <summary>
/// Initializes an instance with the specified properties.
/// </summary>
/// <param name="parameterInfo">The argument or return parameter of the method being inspected.</param>
/// <param name="isInputType">Indicates that this is an input type (an argument); false for output types.</param>
/// <param name="type">The underlying type.</param>
/// <param name="isNullable">Indicates that the underlying type is nullable.</param>
/// <param name="isList">Indicates that this represents a list of elements.</param>
/// <param name="listIsNullable">Indicates that the list is nullable.</param>
/// <param name="graphType">The graph type of the underlying CLR type; null if not specified.</param>
public TypeInformation(ParameterInfo parameterInfo, bool isInputType, Type type, bool isNullable, bool isList, bool listIsNullable, Type? graphType)
{
ParameterInfo = parameterInfo;
IsInputType = isInputType;
Type = type;
IsNullable = isNullable;
IsList = isList;
ListIsNullable = listIsNullable;
GraphType = graphType;
}
}
}
621 changes: 453 additions & 168 deletions src/Tests/DIObjectGraphTypeTests/Nullable.cs

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions src/Tests/NullabilityTestClasses.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#nullable enable
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using GraphQL.DataLoader;
Expand All @@ -20,6 +22,10 @@ public class NullableClass1
public static string Field7() => "field1";
[Optional]
public static string Field8() => "field2";
[Id]
public static string Field9() => "field9";
[OptionalList]
public static List<string> Field10() => null!;
}

public class NullableClass2
Expand All @@ -38,6 +44,8 @@ public class NullableClass2
public static string Field9() => "field1";
[Optional]
public static string Field10() => "field2";
[RequiredList]
public static List<string?>? Field11() => null!;
}

public class NullableClass5
Expand Down Expand Up @@ -130,4 +138,53 @@ public class NullableClass17
public static Task<string> Field2() => null!;
public static Task<string?> Field3() => null!;
}

public class NullableClass18<T>
{
//reference type
public static Tuple<string, string?> Field1() => null!;
//check ordering of nested types
public static Tuple<Tuple<string?, string?>, string> Field2() => null!;
//nullable value type
public static Tuple<int?, string?> Field3() => null!;
//non-generic value type
public static Tuple<Guid, string?> Field4() => null!;
//array
public static Tuple<string[], string?> Field5() => null!;
public static Tuple<int[], string?> Field6() => null!;
//value tuple
public static Tuple<(int, string), string?> Field7() => null!;
public static Tuple<ValueTuple<int, string>, string?> Field8() => null!;
//generic value type
public static Tuple<TestStruct<Guid>, string?> Field9() => null!;
//type reference
public static Tuple<T, string?> Field10() => null!;
}

public struct TestStruct<T>
{
public T Value;
}

public class NullableClass19
{
public static string Field1() => null!;
public static Task<string> Field2() => null!;
public static string[] Field3() => null!;
public static IEnumerable<string> Field4() => null!;
public static IList<string> Field5() => null!;
public static List<string> Field6() => null!;
public static ICollection<string> Field7() => null!;
public static IReadOnlyCollection<string> Field8() => null!;
public static IReadOnlyList<string> Field9() => null!;
public static HashSet<string> Field10() => null!;
public static ISet<string> Field11() => null!;
public static ICollection Field12() => null!;
public static IEnumerable Field13() => null!;
public static IDataLoaderResult<string> Field14() => null!;
public static IDataLoaderResult Field15() => null!;
public static Task<IDataLoaderResult<string[]>> Field16() => null!;
public static object Field17() => null!;
public static string Field18(string arg1 = "test", List<string> arg2 = null!, object arg3 = null!, object[] arg4 = null!) => null!;
}
}

0 comments on commit 5fa69ac

Please sign in to comment.