From 7afa86d90c6662039353cde8e1a3be3d8437ddf6 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 10 Aug 2019 15:08:48 +0200 Subject: [PATCH] Add support for "where T : notnull" constraint. --- .../TestCases/Pretty/NullableRefTypes.cs | 4 ++++ .../CSharp/Syntax/TypeSystemAstBuilder.cs | 4 +++- .../TypeSystem/Implementation/MetadataTypeParameter.cs | 8 +++++++- ILSpy/Languages/CSharpHighlightingTokenWriter.cs | 5 ++++- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullableRefTypes.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullableRefTypes.cs index 1bc660bd4..de00697f1 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullableRefTypes.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NullableRefTypes.cs @@ -48,6 +48,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty ByRef(ref a).ToString(); ByRef(ref b)!.ToString(); } + + public void Constraints() where C : class where CN : class? where NN : notnull where S : struct where D : IDisposable where DN : IDisposable? where NND : notnull, IDisposable + { + } } public class T02_EverythingIsNullableInHere diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index 2e3009fa3..53836a230 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -1785,7 +1785,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax Constraint ConvertTypeParameterConstraint(ITypeParameter tp) { - if (!tp.HasDefaultConstructorConstraint && !tp.HasReferenceTypeConstraint && !tp.HasValueTypeConstraint && tp.DirectBaseTypes.All(IsObjectOrValueType)) { + if (!tp.HasDefaultConstructorConstraint && !tp.HasReferenceTypeConstraint && !tp.HasValueTypeConstraint && tp.NullabilityConstraint != Nullability.NotNullable && tp.DirectBaseTypes.All(IsObjectOrValueType)) { return null; } Constraint c = new Constraint(); @@ -1802,6 +1802,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } else { c.BaseTypes.Add(new PrimitiveType("struct")); } + } else if (tp.NullabilityConstraint == Nullability.NotNullable) { + c.BaseTypes.Add(new PrimitiveType("notnull")); } foreach (IType t in tp.DirectBaseTypes) { if (!IsObjectOrValueType(t)) diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs index 862fc4482..b7549e6ac 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs @@ -161,7 +161,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } } } - return Nullability.Oblivious; + if (Owner is MetadataMethod method) { + return method.NullableContext; + } else if (Owner is ITypeDefinition td) { + return td.NullableContext; + } else { + return Nullability.Oblivious; + } } public override IEnumerable DirectBaseTypes { diff --git a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs index cf0464067..ddd989831 100644 --- a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs +++ b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs @@ -272,7 +272,9 @@ namespace ICSharpCode.ILSpy HighlightingColor color = null; switch (type) { case "new": - color = typeKeywordsColor; + case "notnull": + // Not sure if reference type or value type + color = referenceTypeKeywordsColor; break; case "bool": case "byte": @@ -289,6 +291,7 @@ namespace ICSharpCode.ILSpy case "uint": case "ushort": case "ulong": + case "unmanaged": color = valueTypeKeywordsColor; break; case "class":