diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/NullableAttributes.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/NullableAttributes.cs index 1a3656e..edc1e55 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/NullableAttributes.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/NullableAttributes.cs @@ -84,4 +84,61 @@ internal sealed class DoesNotReturnIfAttribute : Attribute /// Gets the condition parameter value. public bool ParameterValue { get; } } + + /// Specifies that the method or property will ensure that the listed field and property members have not-null values. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] + internal class MemberNotNullAttribute : Attribute + { + /// Initializes the attribute with a field or property member. + /// + /// The field or property member that is promised to be not-null. + /// + public MemberNotNullAttribute(string member) => Members = new[] { member }; + + /// Initializes the attribute with the list of field and property members. + /// + /// The list of field and property members that are promised to be not-null. + /// + public MemberNotNullAttribute(params string[] members) => Members = members; + + /// Gets field or property member names. + public string[] Members { get; } + } + + /// Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] + internal sealed class MemberNotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition and a field or property member. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + /// + /// The field or property member that is promised to be not-null. + /// + public MemberNotNullWhenAttribute(bool returnValue, string member) + { + ReturnValue = returnValue; + Members = new[] { member }; + } + + /// Initializes the attribute with the specified return value condition and list of field and property members. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + /// + /// The list of field and property members that are promised to be not-null. + /// + public MemberNotNullWhenAttribute(bool returnValue, params string[] members) + { + ReturnValue = returnValue; + Members = members; + } + + /// Gets the return value condition. + public bool ReturnValue { get; } + + /// Gets field or property member names. + public string[] Members { get; } + } } diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/NullableAttributes.vb b/TunnelVisionLabs.ReferenceAssemblyAnnotator/NullableAttributes.vb index ab87809..cde2dd2 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/NullableAttributes.vb +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/NullableAttributes.vb @@ -94,7 +94,7 @@ Namespace Global.System.Diagnostics.CodeAnalysis ''' Specifies that the method will not return if the associated Boolean parameter is passed the specified value. - Friend NotInheritable Class DoesNotReturnAttribute + Friend NotInheritable Class DoesNotReturnIfAttribute Inherits Attribute ''' Initializes the attribute with the specified parameter value. @@ -110,4 +110,65 @@ Namespace Global.System.Diagnostics.CodeAnalysis Public ReadOnly Property ParameterValue As Boolean End Class + ''' Specifies that the method or property will ensure that the listed field and property members have not-null values. + + Friend NotInheritable Class MemberNotNullAttribute + Inherits Attribute + + ''' Initializes the attribute with a field or property member. + ''' + ''' The field or property member that is promised to be not-null. + ''' + Public Sub New(member As String) + Me.Members = {member} + End Sub + + ''' Initializes the attribute with the list of field and property members. + ''' + ''' The list of field and property members that are promised to be not-null. + ''' + Public Sub New(ParamArray members As String()) + Me.Members = members + End Sub + + ''' Gets field or property member names. + Public ReadOnly Property Members As String() + End Class + + ''' Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition. + + Friend NotInheritable Class MemberNotNullWhenAttribute + Inherits Attribute + + ''' Initializes the attribute with the specified return value condition and a field or property member. + ''' + ''' The return value condition. If the method returns this value, the associated parameter will not be null. + ''' + ''' + ''' The field or property member that is promised to be not-null. + ''' + Public Sub New(returnValue As Boolean, member As String) + Me.ReturnValue = returnValue + Me.Members = {member} + End Sub + + ''' Initializes the attribute with the specified return value condition and list of field and property members. + ''' + ''' The return value condition. If the method returns this value, the associated parameter will not be null. + ''' + ''' + ''' The list of field and property members that are promised to be not-null. + ''' + Public Sub New(ReturnValue As Boolean, ParamArray members As String()) + Me.ReturnValue = ReturnValue + Me.Members = members + End Sub + + ''' Gets the return value condition. + Public ReadOnly Property ReturnValue As Boolean + + ''' Gets field or property member names. + Public ReadOnly Property Members As String() + End Class + End Namespace diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes+MemberNotNullAttributeProvidedType.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes+MemberNotNullAttributeProvidedType.cs new file mode 100644 index 0000000..9688a39 --- /dev/null +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes+MemberNotNullAttributeProvidedType.cs @@ -0,0 +1,33 @@ +// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +namespace TunnelVisionLabs.ReferenceAssemblyAnnotator +{ + using System; + using Mono.Cecil; + using Mono.Cecil.Rocks; + + internal partial class WellKnownTypes + { + private sealed class MemberNotNullAttributeProvidedType : ProvidedAttributeType + { + public MemberNotNullAttributeProvidedType() + : base("System.Diagnostics.CodeAnalysis", "MemberNotNullAttribute") + { + } + + protected override void ImplementAttribute(ModuleDefinition module, TypeDefinition attribute, WellKnownTypes wellKnownTypes, CustomAttributeFactory attributeFactory) + { + var constructor1 = MethodFactory.Constructor(wellKnownTypes.TypeSystem); + constructor1.Parameters.Add(new ParameterDefinition("member", ParameterAttributes.None, wellKnownTypes.TypeSystem.String)); + attribute.Methods.Add(constructor1); + + var constructor2 = MethodFactory.Constructor(wellKnownTypes.TypeSystem); + constructor2.Parameters.Add(new ParameterDefinition("members", ParameterAttributes.None, wellKnownTypes.TypeSystem.String.MakeArrayType())); + attribute.Methods.Add(constructor2); + + attribute.CustomAttributes.Add(attributeFactory.AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, inherited: false, allowMultiple: true)); + } + } + } +} diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes+MemberNotNullWhenAttributeProvidedType.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes+MemberNotNullWhenAttributeProvidedType.cs new file mode 100644 index 0000000..18c364a --- /dev/null +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes+MemberNotNullWhenAttributeProvidedType.cs @@ -0,0 +1,35 @@ +// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +namespace TunnelVisionLabs.ReferenceAssemblyAnnotator +{ + using System; + using Mono.Cecil; + using Mono.Cecil.Rocks; + + internal partial class WellKnownTypes + { + private sealed class MemberNotNullWhenAttributeProvidedType : ProvidedAttributeType + { + public MemberNotNullWhenAttributeProvidedType() + : base("System.Diagnostics.CodeAnalysis", "MemberNotNullWhenAttribute") + { + } + + protected override void ImplementAttribute(ModuleDefinition module, TypeDefinition attribute, WellKnownTypes wellKnownTypes, CustomAttributeFactory attributeFactory) + { + var constructor1 = MethodFactory.Constructor(wellKnownTypes.TypeSystem); + constructor1.Parameters.Add(new ParameterDefinition("parameterValue", ParameterAttributes.None, wellKnownTypes.TypeSystem.Boolean)); + constructor1.Parameters.Add(new ParameterDefinition("member", ParameterAttributes.None, wellKnownTypes.TypeSystem.String)); + attribute.Methods.Add(constructor1); + + var constructor2 = MethodFactory.Constructor(wellKnownTypes.TypeSystem); + constructor1.Parameters.Add(new ParameterDefinition("parameterValue", ParameterAttributes.None, wellKnownTypes.TypeSystem.Boolean)); + constructor2.Parameters.Add(new ParameterDefinition("members", ParameterAttributes.None, wellKnownTypes.TypeSystem.String.MakeArrayType())); + attribute.Methods.Add(constructor2); + + attribute.CustomAttributes.Add(attributeFactory.AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, inherited: false, allowMultiple: true)); + } + } + } +} diff --git a/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs b/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs index 58162e0..bbafac1 100644 --- a/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs +++ b/TunnelVisionLabs.ReferenceAssemblyAnnotator/WellKnownTypes.cs @@ -27,6 +27,8 @@ internal partial class WellKnownTypes private readonly WellKnownType _systemDiagnosticsCodeAnalysisDoesNotReturnIfAttribute = new DoesNotReturnIfAttributeProvidedType(); private readonly WellKnownType _systemDiagnosticsCodeAnalysisMaybeNullAttribute = new MaybeNullAttributeProvidedType(); private readonly WellKnownType _systemDiagnosticsCodeAnalysisMaybeNullWhenAttribute = new MaybeNullWhenAttributeProvidedType(); + private readonly WellKnownType _systemDiagnosticsCodeAnalysisMemberNotNullAttribute = new MemberNotNullAttributeProvidedType(); + private readonly WellKnownType _systemDiagnosticsCodeAnalysisMemberNotNullWhenAttribute = new MemberNotNullWhenAttributeProvidedType(); private readonly WellKnownType _systemDiagnosticsCodeAnalysisNotNullAttribute = new NotNullAttributeProvidedType(); private readonly WellKnownType _systemDiagnosticsCodeAnalysisNotNullIfNotNullAttribute = new NotNullIfNotNullAttributeProvidedType(); private readonly WellKnownType _systemDiagnosticsCodeAnalysisNotNullWhenAttribute = new NotNullWhenAttributeProvidedType(); @@ -70,6 +72,12 @@ public WellKnownTypes(AssemblyDefinition assemblyDefinition) SystemDiagnosticsCodeAnalysisMaybeNullWhenAttribute = new Lazy( () => _systemDiagnosticsCodeAnalysisMaybeNullWhenAttribute.GetOrCreateTypeReference(Module, this), LazyThreadSafetyMode.ExecutionAndPublication); + SystemDiagnosticsCodeAnalysisMemberNotNullAttribute = new Lazy( + () => _systemDiagnosticsCodeAnalysisMemberNotNullAttribute.GetOrCreateTypeReference(Module, this), + LazyThreadSafetyMode.ExecutionAndPublication); + SystemDiagnosticsCodeAnalysisMemberNotNullWhenAttribute = new Lazy( + () => _systemDiagnosticsCodeAnalysisMemberNotNullWhenAttribute.GetOrCreateTypeReference(Module, this), + LazyThreadSafetyMode.ExecutionAndPublication); SystemDiagnosticsCodeAnalysisNotNullAttribute = new Lazy( () => _systemDiagnosticsCodeAnalysisNotNullAttribute.GetOrCreateTypeReference(Module, this), LazyThreadSafetyMode.ExecutionAndPublication); @@ -115,6 +123,10 @@ public WellKnownTypes(AssemblyDefinition assemblyDefinition) public Lazy SystemDiagnosticsCodeAnalysisMaybeNullWhenAttribute { get; } + public Lazy SystemDiagnosticsCodeAnalysisMemberNotNullAttribute { get; } + + public Lazy SystemDiagnosticsCodeAnalysisMemberNotNullWhenAttribute { get; } + public Lazy SystemDiagnosticsCodeAnalysisNotNullAttribute { get; } public Lazy SystemDiagnosticsCodeAnalysisNotNullIfNotNullAttribute { get; }