Skip to content

Commit 5ae4166

Browse files
committed
add support for formatting 'class?' constraints
1 parent 1d302e3 commit 5ae4166

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

src/Smdn.Reflection.ReverseGenerating/Smdn.Reflection.ReverseGenerating/Generator.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,9 @@ bool typeWithNamespace
226226
yield return "struct";
227227
}
228228
else if (constraintAttrs.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint)) {
229-
yield return "class";
229+
yield return genericParameter.GetNullableAttributeMetadataValue() == NullableMetadataValue.Annotated
230+
? "class?"
231+
: "class";
230232
}
231233
else if (constraintAttrs.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint)) {
232234
if (HasUnmanagedConstraint(genericParameter))
@@ -236,7 +238,7 @@ bool typeWithNamespace
236238
}
237239

238240
var orderedConstraintTypeNames = constraintTypesExceptValueType
239-
.Select(i => i.FormatTypeName(typeWithNamespace: typeWithNamespace))
241+
.Select(constraintType => constraintType.FormatTypeName(typeWithNamespace: typeWithNamespace))
240242
.OrderBy(static name => name, StringComparer.Ordinal);
241243

242244
foreach (var ctn in orderedConstraintTypeNames)

tests/Smdn.Reflection.ReverseGenerating/Smdn.Reflection.ReverseGenerating/Generator.TypeDeclaration.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,44 @@ namespace Constraints1 {
307307
[TypeDeclarationTestCase("public class C0_NullableDisableContext<T>")] public class C0_NullableDisableContext<T> { }
308308
#nullable restore
309309

310+
#nullable enable annotations
311+
[TypeDeclarationTestCase("public class RefType<T> where T : class")]
312+
public class RefType<T> where T : class { }
313+
314+
[TypeDeclarationTestCase("public class NullableRefType<T> where T : class?")]
315+
public class NullableRefType<T> where T : class? { }
316+
317+
[TypeDeclarationTestCase("public class RefTypeAndNullableRefType<TRef, TNullableRef> where TRef : class where TNullableRef : class?")]
318+
public class RefTypeAndNullableRefType<TRef, TNullableRef> where TRef : class where TNullableRef : class? { }
319+
320+
[TypeDeclarationTestCase("public class NullableRefTypeAndRefType<TNullableRef, TRef> where TNullableRef : class? where TRef : class")]
321+
public class NullableRefTypeAndRefType<TNullableRef, TRef> where TNullableRef : class? where TRef : class { }
322+
323+
[TypeDeclarationTestCase("public class RefTypeWithDefaultConstructor<T> where T : class, new()")]
324+
public class RefTypeWithDefaultConstructor<T> where T : class, new() { }
325+
326+
[TypeDeclarationTestCase("public class NullableRefTypeWithDefaultConstructor<T> where T : class?, new()")]
327+
public class NullableRefTypeWithDefaultConstructor<T> where T : class?, new() { }
328+
329+
[TypeDeclarationTestCase("public class RefTypeWithIDisposable<T> where T : class, System.IDisposable")]
330+
public class RefTypeWithIDisposable<T> where T : class, IDisposable { }
331+
332+
[TypeDeclarationTestCase("public class NullableRefTypeWithIDisposable<T> where T : class?, System.IDisposable")]
333+
public class NullableRefTypeWithIDisposable<T> where T : class?, IDisposable { }
334+
335+
[TypeDeclarationTestCase("public class RefTypeWithNullableIDisposable<T> where T : class, System.IDisposable")]
336+
public class RefTypeWithNullableIDisposable<T> where T : class, IDisposable? { } // ? nullability annotation will be erased
337+
338+
[TypeDeclarationTestCase("public class NullableRefTypeWithNullableIDisposable<T> where T : class, System.IDisposable")]
339+
public class NullableRefTypeWithNullableIDisposable<T> where T : class?, IDisposable? { } // ? nullability annotation will be erased
340+
341+
[TypeDeclarationTestCase("public class IDisposable<T> where T : System.IDisposable")]
342+
public class IDisposable<T> where T : IDisposable { }
343+
344+
[TypeDeclarationTestCase("public class NullableIDisposable<T> where T : System.IDisposable")]
345+
public class NullableIDisposable<T> where T : IDisposable? { } // ? nullability annotation will be erased
346+
#nullable restore
347+
310348
[TypeDeclarationTestCase("public class C1<T> where T : new()")] public class C1<T> where T : new() { }
311349
[TypeDeclarationTestCase("public class C2_0<T> where T : struct")] public class C2_0<T> where T : struct { }
312350
[TypeDeclarationTestCase("public class C2_1<T> where T : struct, System.IDisposable")] public class C2_1<T> where T : struct, IDisposable { }
@@ -323,6 +361,11 @@ namespace Constraints1 {
323361
public class C10<T> where T : CBase { }
324362
public class CBase { }
325363

364+
#nullable enable annotations
365+
[TypeDeclarationTestCase("public class NullableConstraintType<T> where T : CBase", TypeWithNamespace = false)]
366+
public class NullableConstraintType<T> where T : CBase? { } // ? nullability annotation will be erased
367+
#nullable restore
368+
326369
[TypeDeclarationTestCase("public class C11<T> where T : System.Enum")] public class C11<T> where T : System.Enum { }
327370
[TypeDeclarationTestCase("public class C12<T> where T : System.Delegate")] public class C12<T> where T : System.Delegate { }
328371
[TypeDeclarationTestCase("public class C13<T> where T : System.MulticastDelegate")] public class C13<T> where T : System.MulticastDelegate { }
@@ -342,6 +385,9 @@ public class C15_2_NullableEnableContext<T0, T1> where T1 : notnull { }
342385

343386
[TypeDeclarationTestCase("public class C15_3_NullableEnableContext<T> where T : notnull, System.IDisposable")]
344387
public class C15_3_NullableEnableContext<T> where T : notnull, IDisposable { }
388+
389+
[TypeDeclarationTestCase("public class C15_4_NullableEnableContext<T> where T : notnull, System.IDisposable")]
390+
public class C15_4_NullableEnableContext<T> where T : notnull, IDisposable? { } // ? nullability annotation will be erased
345391
#nullable restore
346392
#nullable disable annotations
347393
[TypeDeclarationTestCase("public class C15_0_NullableDisableContext<T> where T : notnull")]

0 commit comments

Comments
 (0)