From ed02b2eb9e7a63454784dffd87b2481dc8f6f7d8 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 2 Oct 2022 22:46:37 +0200 Subject: [PATCH] Add MemberNotNullWhenAttribute to IMethod, IProperty and IEvent. Make sure that it's guaranteed that AccessorOwner is non-null, when IsAccessor is true. --- .../ICSharpCode.Decompiler.csproj | 1 + ICSharpCode.Decompiler/NRTAttributes.cs | 25 +++++++++++++++++++ ICSharpCode.Decompiler/TypeSystem/IEvent.cs | 5 ++++ ICSharpCode.Decompiler/TypeSystem/IMethod.cs | 2 ++ .../TypeSystem/IProperty.cs | 4 +++ .../Implementation/MetadataMethod.cs | 4 +-- .../TypeSystem/NormalizeTypeVisitor.cs | 22 +++++++++++++--- .../TypeSystem/Nullability.cs | 20 ++++++++++++--- .../TypeSystem/TypeVisitor.cs | 2 ++ 9 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 ICSharpCode.Decompiler/NRTAttributes.cs diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 0efd42831..b3b5cc7a6 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -90,6 +90,7 @@ + diff --git a/ICSharpCode.Decompiler/NRTAttributes.cs b/ICSharpCode.Decompiler/NRTAttributes.cs new file mode 100644 index 000000000..bdcaab026 --- /dev/null +++ b/ICSharpCode.Decompiler/NRTAttributes.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Diagnostics.CodeAnalysis +{ + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] + internal sealed class MemberNotNullWhenAttribute : Attribute + { + public bool ReturnValue { get; } + + public string[] Members { get; } + + public MemberNotNullWhenAttribute(bool returnValue, string member) + { + ReturnValue = returnValue; + Members = new string[1] { member }; + } + + public MemberNotNullWhenAttribute(bool returnValue, params string[] members) + { + ReturnValue = returnValue; + Members = members; + } + } +} diff --git a/ICSharpCode.Decompiler/TypeSystem/IEvent.cs b/ICSharpCode.Decompiler/TypeSystem/IEvent.cs index 732840c62..635b031da 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IEvent.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IEvent.cs @@ -18,12 +18,17 @@ #nullable enable +using System.Diagnostics.CodeAnalysis; + namespace ICSharpCode.Decompiler.TypeSystem { public interface IEvent : IMember { + [MemberNotNullWhen(true, nameof(AddAccessor))] bool CanAdd { get; } + [MemberNotNullWhen(true, nameof(RemoveAccessor))] bool CanRemove { get; } + [MemberNotNullWhen(true, nameof(InvokeAccessor))] bool CanInvoke { get; } IMethod? AddAccessor { get; } diff --git a/ICSharpCode.Decompiler/TypeSystem/IMethod.cs b/ICSharpCode.Decompiler/TypeSystem/IMethod.cs index 26e4626c8..6438a1315 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IMethod.cs @@ -19,6 +19,7 @@ #nullable enable using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace ICSharpCode.Decompiler.TypeSystem @@ -81,6 +82,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// Gets whether the method is a property/event accessor. /// + [MemberNotNullWhen(true, nameof(AccessorOwner))] bool IsAccessor { get; } /// diff --git a/ICSharpCode.Decompiler/TypeSystem/IProperty.cs b/ICSharpCode.Decompiler/TypeSystem/IProperty.cs index f8b6203d1..cad688dbe 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IProperty.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IProperty.cs @@ -18,6 +18,8 @@ #nullable enable +using System.Diagnostics.CodeAnalysis; + namespace ICSharpCode.Decompiler.TypeSystem { /// @@ -25,7 +27,9 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public interface IProperty : IParameterizedMember { + [MemberNotNullWhen(true, nameof(Getter))] bool CanGet { get; } + [MemberNotNullWhen(true, nameof(Setter))] bool CanSet { get; } IMethod? Getter { get; } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs index abc4252ea..c3760e42e 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs @@ -67,7 +67,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation var (accessorOwner, semanticsAttribute) = module.PEFile.MethodSemanticsLookup.GetSemantics(handle); const MethodAttributes finalizerAttributes = (MethodAttributes.Virtual | MethodAttributes.Family | MethodAttributes.HideBySig); this.typeParameters = MetadataTypeParameter.Create(module, this, def.GetGenericParameters()); - if (semanticsAttribute != 0) + if (semanticsAttribute != 0 && !accessorOwner.IsNil + && accessorOwner.Kind is HandleKind.PropertyDefinition or HandleKind.EventDefinition) { this.symbolKind = SymbolKind.Accessor; this.accessorOwner = accessorOwner; @@ -129,7 +130,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public bool HasBody => module.metadata.GetMethodDefinition(handle).HasBody(); - public IMember AccessorOwner { get { if (accessorOwner.IsNil) diff --git a/ICSharpCode.Decompiler/TypeSystem/NormalizeTypeVisitor.cs b/ICSharpCode.Decompiler/TypeSystem/NormalizeTypeVisitor.cs index 505a06359..8f097f683 100644 --- a/ICSharpCode.Decompiler/TypeSystem/NormalizeTypeVisitor.cs +++ b/ICSharpCode.Decompiler/TypeSystem/NormalizeTypeVisitor.cs @@ -1,6 +1,22 @@ -using System; -using System.Collections.Generic; -using System.Text; +// Copyright (c) 2019 Daniel Grunwald +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#nullable enable using ICSharpCode.Decompiler.TypeSystem.Implementation; diff --git a/ICSharpCode.Decompiler/TypeSystem/Nullability.cs b/ICSharpCode.Decompiler/TypeSystem/Nullability.cs index 17ce52520..fc934ebea 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Nullability.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Nullability.cs @@ -1,6 +1,20 @@ -using System; -using System.Collections.Generic; -using System.Text; +// Copyright (c) 2019 Daniel Grunwald +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. namespace ICSharpCode.Decompiler.TypeSystem { diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeVisitor.cs b/ICSharpCode.Decompiler/TypeSystem/TypeVisitor.cs index da76087c7..d5636fe24 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeVisitor.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeVisitor.cs @@ -16,6 +16,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +#nullable enable + using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.TypeSystem