Skip to content

Commit 1a6afc2

Browse files
committed
add support for formatting Nullable<GenericValueType<...>> with nullability annotations
1 parent ff51b15 commit 1a6afc2

File tree

3 files changed

+34
-8
lines changed

3 files changed

+34
-8
lines changed

src/Smdn.Reflection.ReverseGenerating/Smdn.Reflection.ReverseGenerating/CSharpTypeFormatter.FormatTypeNameWithNullabilityAnnotation.cs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,16 @@ FormatTypeNameOptions options
7777
nullabilityAnnotationForByRefParameter = NullableAnnotationSyntaxString;
7878

7979
// nullable value types (Nullable<>)
80-
if (IsValueTupleType(nullableUnderlyingType))
80+
if (IsValueTupleType(nullableUnderlyingType)) {
8181
// special case for nullable value tuples (Nullable<ValueTuple<>>)
8282
return FormatValueTuple(target, builder, options).Append(nullabilityAnnotationForByRefParameter);
83-
else if (isGenericTypeClosedOrDefinition)
83+
}
84+
else if (nullableUnderlyingType.IsGenericType) {
8485
// case for nullable generic value types (Nullable<GenericValueType<>>)
85-
// TODO: cannot get NullabilityInfo of generic type argument from Nullable<GenericValueType<>> (ex: KeyValuePair<int?, string?>?)
86-
return builder.Append(FormatTypeNameCore(targetType, options));
86+
return FormatNullableGenericValueType(target, builder, options)
87+
.Append(GetNullabilityAnnotation(target))
88+
.Append(nullabilityAnnotationForByRefParameter);
89+
}
8790

8891
targetType = nullableUnderlyingType;
8992
}
@@ -202,5 +205,28 @@ FormatTypeNameOptions options
202205

203206
return builder.Append(')').Append(GetNullabilityAnnotation(target));
204207
}
208+
209+
private static StringBuilder FormatNullableGenericValueType(
210+
NullabilityInfo target,
211+
StringBuilder builder,
212+
FormatTypeNameOptions options
213+
)
214+
{
215+
if (options.TypeWithNamespace && !target.Type.IsNested)
216+
builder.Append(target.Type.Namespace).Append('.');
217+
218+
builder
219+
.Append(target.Type.GenericTypeArguments[0].GetGenericTypeName()) // the name of GenericValueType of Nullable<GenericValueType<>>
220+
.Append('<');
221+
222+
for (var i = 0; i < target.GenericTypeArguments.Length; i++) {
223+
if (0 < i)
224+
builder.Append(", ");
225+
226+
FormatTypeNameWithNullabilityAnnotation(target.GenericTypeArguments[i], builder, options);
227+
}
228+
229+
return builder.Append('>');
230+
}
205231
}
206232
#endif // SYSTEM_REFLECTION_NULLABILITYINFO

tests/Smdn.Reflection.ReverseGenerating/Smdn.Reflection.ReverseGenerating/Generator.MemberDeclaration.Parameters.NullabilityAnnotations.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ public void NullableNonLanguagePrimitiveRefType(Uri? p) { }
7474
[MemberDeclarationTestCase($"public void {nameof(ListOfKeyValuePairOfRefTypeValue)}(List<KeyValuePair<string, string>> p) {{}}", ParameterWithNamespace = false)] public void ListOfKeyValuePairOfRefTypeValue(List<KeyValuePair<string, string>> p) { }
7575
[MemberDeclarationTestCase($"public void {nameof(ListOfKeyValuePairOfNullableRefTypeValue)}(List<KeyValuePair<string, string?>> p) {{}}", ParameterWithNamespace = false)] public void ListOfKeyValuePairOfNullableRefTypeValue(List<KeyValuePair<string, string?>> p) { }
7676
[MemberDeclarationTestCase($"public void {nameof(ListOfNullableKeyValuePairOfRefTypeValue)}(List<KeyValuePair<string, string>?> p) {{}}", ParameterWithNamespace = false)] public void ListOfNullableKeyValuePairOfRefTypeValue(List<KeyValuePair<string, string>?> p) { }
77-
[SkipTestCase("cannot get NullabilityInfo of generic type argument from Nullable<GenericValueType<>>")] [MemberDeclarationTestCase($"public void {nameof(ListOfNullableKeyValuePairOfNullableRefTypeValue)}(List<KeyValuePair<string, string?>?> p) {{}}", ParameterWithNamespace = false)] public void ListOfNullableKeyValuePairOfNullableRefTypeValue(List<KeyValuePair<string, string?>?> p) { }
77+
[MemberDeclarationTestCase($"public void {nameof(ListOfNullableKeyValuePairOfNullableRefTypeValue)}(List<KeyValuePair<string, string?>?> p) {{}}", ParameterWithNamespace = false)] public void ListOfNullableKeyValuePairOfNullableRefTypeValue(List<KeyValuePair<string, string?>?> p) { }
7878
[MemberDeclarationTestCase($"public void {nameof(NullableListOfKeyValuePairOfRefTypeValue)}(List<KeyValuePair<string, string>>? p) {{}}", ParameterWithNamespace = false)] public void NullableListOfKeyValuePairOfRefTypeValue(List<KeyValuePair<string, string>>? p) { }
7979
[MemberDeclarationTestCase($"public void {nameof(NullableListOfKeyValuePairOfNullableRefTypeValue)}(List<KeyValuePair<string, string?>>? p) {{}}", ParameterWithNamespace = false)] public void NullableListOfKeyValuePairOfNullableRefTypeValue(List<KeyValuePair<string, string?>>? p) { }
80-
[SkipTestCase("cannot get NullabilityInfo of generic type argument from Nullable<GenericValueType<>>")] [MemberDeclarationTestCase($"public void {nameof(NullableListOfNullableKeyValuePairOfNullableRefTypeValue)}(List<KeyValuePair<string, string?>?>? p) {{}}", ParameterWithNamespace = false)] public void NullableListOfNullableKeyValuePairOfNullableRefTypeValue(List<KeyValuePair<string, string?>?>? p) { }
80+
[MemberDeclarationTestCase($"public void {nameof(NullableListOfNullableKeyValuePairOfNullableRefTypeValue)}(List<KeyValuePair<string, string?>?>? p) {{}}", ParameterWithNamespace = false)] public void NullableListOfNullableKeyValuePairOfNullableRefTypeValue(List<KeyValuePair<string, string?>?>? p) { }
8181

8282
class Params {
8383
[MemberDeclarationTestCase($"public void {nameof(ArrayOfValueType)}(params int[] p) {{}}")] public void ArrayOfValueType(params int[] p) { }

tests/Smdn.Reflection.ReverseGenerating/Smdn.Reflection.ReverseGenerating/Generator.MemberDeclaration.ReturnParameters.NullabilityAnnotations.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ public class NullabilityAnnotations {
5959
[MemberDeclarationTestCase($"public List<KeyValuePair<string, string>> {nameof(ListOfKeyValuePairOfRefTypeValue)}() {{}}", MemberWithNamespace = false)] public List<KeyValuePair<string, string>> ListOfKeyValuePairOfRefTypeValue() => throw null;
6060
[MemberDeclarationTestCase($"public List<KeyValuePair<string, string?>> {nameof(ListOfKeyValuePairOfNullableRefTypeValue)}() {{}}", MemberWithNamespace = false)] public List<KeyValuePair<string, string?>> ListOfKeyValuePairOfNullableRefTypeValue() => throw null;
6161
[MemberDeclarationTestCase($"public List<KeyValuePair<string, string>?> {nameof(ListOfNullableKeyValuePairOfRefTypeValue)}() {{}}", MemberWithNamespace = false)] public List<KeyValuePair<string, string>?> ListOfNullableKeyValuePairOfRefTypeValue() => throw null;
62-
[SkipTestCase("cannot get NullabilityInfo of generic type argument from Nullable<GenericValueType<>>")] [MemberDeclarationTestCase($"public List<KeyValuePair<string, string?>?> {nameof(ListOfNullableKeyValuePairOfNullableRefTypeValue)}() {{}}", MemberWithNamespace = false)] public List<KeyValuePair<string, string?>?> ListOfNullableKeyValuePairOfNullableRefTypeValue() => throw null;
62+
[MemberDeclarationTestCase($"public List<KeyValuePair<string, string?>?> {nameof(ListOfNullableKeyValuePairOfNullableRefTypeValue)}() {{}}", MemberWithNamespace = false)] public List<KeyValuePair<string, string?>?> ListOfNullableKeyValuePairOfNullableRefTypeValue() => throw null;
6363
[MemberDeclarationTestCase($"public List<KeyValuePair<string, string>>? {nameof(NullableListOfKeyValuePairOfRefTypeValue)}() {{}}", MemberWithNamespace = false)] public List<KeyValuePair<string, string>>? NullableListOfKeyValuePairOfRefTypeValue() => throw null;
6464
[MemberDeclarationTestCase($"public List<KeyValuePair<string, string?>>? {nameof(NullableListOfKeyValuePairOfNullableRefTypeValue)}() {{}}", MemberWithNamespace = false)] public List<KeyValuePair<string, string?>>? NullableListOfKeyValuePairOfNullableRefTypeValue() => throw null;
65-
[SkipTestCase("cannot get NullabilityInfo of generic type argument from Nullable<GenericValueType<>>")] [MemberDeclarationTestCase($"public List<KeyValuePair<string, string?>?>? {nameof(NullableListOfNullableKeyValuePairOfNullableRefTypeValue)}() {{}}", MemberWithNamespace = false)] public List<KeyValuePair<string, string?>?>? NullableListOfNullableKeyValuePairOfNullableRefTypeValue() => throw null;
65+
[MemberDeclarationTestCase($"public List<KeyValuePair<string, string?>?>? {nameof(NullableListOfNullableKeyValuePairOfNullableRefTypeValue)}() {{}}", MemberWithNamespace = false)] public List<KeyValuePair<string, string?>?>? NullableListOfNullableKeyValuePairOfNullableRefTypeValue() => throw null;
6666

6767
class Modifiers {
6868
class Ref {

0 commit comments

Comments
 (0)