Skip to content

Commit ac15b02

Browse files
authored
Fix nullability context for typedefs generator (#158)
1 parent 0e23327 commit ac15b02

2 files changed

Lines changed: 35 additions & 3 deletions

File tree

src/NodeApi.Generator/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ private static void ResolveSystemAssemblies(string? targetFramework)
224224
}
225225
string dotnetRootDirectory = Path.GetDirectoryName(Path.GetDirectoryName(
226226
Path.GetDirectoryName(runtimeDirectory)!)!)!;
227+
227228
string refAssemblyDirectory = Path.Combine(
228229
dotnetRootDirectory,
229230
"packs",

src/NodeApi.Generator/TypeDefinitionsGenerator.cs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,9 @@ private string GetTSType(PropertyInfo property)
933933
propertyType = propertyType.GetElementType()!;
934934
}
935935

936-
string tsType = GetTSType(propertyType, _nullabilityContext.Create(property));
936+
string tsType = GetTSType(
937+
propertyType,
938+
FixNullability(_nullabilityContext.Create(property)));
937939

938940
if (tsType == "unknown" || tsType.Contains("unknown"))
939941
{
@@ -1001,7 +1003,8 @@ private string GetTSType(ParameterInfo parameter)
10011003
}
10021004

10031005
tsType = GetTSType(
1004-
parameter.ParameterType, _nullabilityContext.Create(parameter));
1006+
parameter.ParameterType,
1007+
FixNullability(_nullabilityContext.Create(parameter)));
10051008
return $"{{ {resultName}: {tsType}, {outProperties} }}";
10061009
}
10071010
}
@@ -1013,7 +1016,7 @@ private string GetTSType(ParameterInfo parameter)
10131016
parameterType = parameterType.GetElementType()!;
10141017
}
10151018

1016-
tsType = GetTSType(parameterType, _nullabilityContext.Create(parameter));
1019+
tsType = GetTSType(parameterType, FixNullability(_nullabilityContext.Create(parameter)));
10171020
if (tsType == "unknown" || tsType.Contains("unknown"))
10181021
{
10191022
string className = parameter.Member.DeclaringType!.Name;
@@ -1043,6 +1046,34 @@ private string GetTSType(ParameterInfo parameter)
10431046
return tsType;
10441047
}
10451048

1049+
/// <summary>
1050+
/// The generator loads all referenced types in a separate MetadataLoadContext,
1051+
/// which causes a problem with NullabilityInfoContext when it tries to detect
1052+
/// whether a type is a value type, because the referenced ValueType type is not
1053+
/// the same as the system ValueType type. This method overrides the nullability
1054+
/// state for value types, which can never be nullable. (Note Nullable<T> is itself
1055+
/// a non-nullable value type; it is handled by the generator as a special case.)
1056+
/// </summary>
1057+
private static NullabilityInfo FixNullability(NullabilityInfo nullability)
1058+
{
1059+
if (nullability.Type.BaseType?.FullName == typeof(ValueType).FullName)
1060+
{
1061+
// Use reflection to override these properties which have internal setters.
1062+
// There is no public constructor and no other way to set these properties.
1063+
typeof(NullabilityInfo).GetProperty(nameof(NullabilityInfo.ReadState))!
1064+
.SetValue(nullability, NullabilityState.NotNull);
1065+
typeof(NullabilityInfo).GetProperty(nameof(NullabilityInfo.WriteState))!
1066+
.SetValue(nullability, NullabilityState.NotNull);
1067+
}
1068+
1069+
for (int i = 0; i < nullability.GenericTypeArguments.Length; i++)
1070+
{
1071+
FixNullability(nullability.GenericTypeArguments[i]);
1072+
}
1073+
1074+
return nullability;
1075+
}
1076+
10461077
private string GetTSType(Type type, NullabilityInfo? nullability)
10471078
{
10481079
string tsType = "unknown";

0 commit comments

Comments
 (0)