diff --git a/src/TypeNameInterpretation/FrameworkExtensions/ArgumentNullExceptionShims.cs b/src/TypeNameInterpretation/FrameworkExtensions/ArgumentNullExceptionShims.cs new file mode 100644 index 0000000..0193def --- /dev/null +++ b/src/TypeNameInterpretation/FrameworkExtensions/ArgumentNullExceptionShims.cs @@ -0,0 +1,26 @@ +// Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See LICENSE in the project root for license information. + +#if !NET +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +namespace System +{ + static class ArgumentNullExceptionShims + { + extension(ArgumentNullException) + { + public static void ThrowIfNull([NotNull] object? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null) + { + if (argument is null) + { + ThrowNullReferenceException(paramName); + } + } + } + + [DoesNotReturn] + static void ThrowNullReferenceException(string? paramName) => throw new ArgumentNullException(paramName); + } +} +#endif diff --git a/src/TypeNameInterpretation/FrameworkExtensions/Attributes/CallerArgumentExpressionAttribute.cs b/src/TypeNameInterpretation/FrameworkExtensions/Attributes/CallerArgumentExpressionAttribute.cs new file mode 100644 index 0000000..d29c22c --- /dev/null +++ b/src/TypeNameInterpretation/FrameworkExtensions/Attributes/CallerArgumentExpressionAttribute.cs @@ -0,0 +1,12 @@ +// Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See LICENSE in the project root for license information. + +#if !NET +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Parameter)] + sealed class CallerArgumentExpressionAttribute(string parameterName) : Attribute + { + public string ParameterName { get; } = parameterName; + } +} +#endif diff --git a/src/TypeNameInterpretation/InsAssemblyExtensions.cs b/src/TypeNameInterpretation/InsAssemblyExtensions.cs index b57bc30..829755f 100644 --- a/src/TypeNameInterpretation/InsAssemblyExtensions.cs +++ b/src/TypeNameInterpretation/InsAssemblyExtensions.cs @@ -10,6 +10,8 @@ public static class InsAssemblyExtensions { public static bool TryGetVersion(this InsAssembly assembly, [NotNullWhen(true)] out Version? version) { + ArgumentNullException.ThrowIfNull(assembly); + if (!assembly.TryGetQualification(WellKnownQualificationNames.Version, out var value)) { version = null; @@ -26,6 +28,8 @@ public static bool TryGetVersion(this InsAssembly assembly, [NotNullWhen(true)] public static bool TryGetPublicKey(this InsAssembly assembly, out byte[]? publicKey) { + ArgumentNullException.ThrowIfNull(assembly); + if (!assembly.TryGetQualification(WellKnownQualificationNames.PublicKey, out var value)) { publicKey = null; @@ -42,6 +46,8 @@ public static bool TryGetPublicKey(this InsAssembly assembly, out byte[]? public public static bool TryGetPublicKeyToken(this InsAssembly assembly, out byte[]? publicKeyToken) { + ArgumentNullException.ThrowIfNull(assembly); + if (!assembly.TryGetQualification(WellKnownQualificationNames.PublicKeyToken, out var value)) { publicKeyToken = null; @@ -58,6 +64,8 @@ public static bool TryGetPublicKeyToken(this InsAssembly assembly, out byte[]? p public static bool TryGetProcessorArchitecture(this InsAssembly assembly, out ProcessorArchitecture processorArchitecture) { + ArgumentNullException.ThrowIfNull(assembly); + if (!assembly.TryGetQualification(WellKnownQualificationNames.ProcessorArchitecture, out var value)) { processorArchitecture = default; @@ -74,6 +82,9 @@ public static bool TryGetProcessorArchitecture(this InsAssembly assembly, out Pr public static bool TryGetQualification(this InsAssembly assembly, string name, [NotNullWhen(true)] out string? value) { + ArgumentNullException.ThrowIfNull(assembly); + ArgumentNullException.ThrowIfNull(name); + foreach (var qualification in assembly.Qualifications) { if (qualification.Name == name) @@ -88,13 +99,22 @@ public static bool TryGetQualification(this InsAssembly assembly, string name, [ } public static InsAssembly WithVersion(this InsAssembly assembly, Version version) - => assembly.WithQualification(WellKnownQualificationNames.Version, version.ToString()); + { + ArgumentNullException.ThrowIfNull(assembly); + ArgumentNullException.ThrowIfNull(version); + return assembly.WithQualification(WellKnownQualificationNames.Version, version.ToString()); + } public static InsAssembly WithPublicKey(this InsAssembly assembly, ReadOnlySpan publicKey) - => assembly.WithQualification(WellKnownQualificationNames.PublicKey, FormatBlob(publicKey)); + { + ArgumentNullException.ThrowIfNull(assembly); + return assembly.WithQualification(WellKnownQualificationNames.PublicKey, FormatBlob(publicKey)); + } public static InsAssembly WithPublicKey(this InsAssembly assembly, byte[]? publicKey) { + ArgumentNullException.ThrowIfNull(assembly); + if (publicKey == null) { return assembly.WithQualification(WellKnownQualificationNames.PublicKey, NullBlob); @@ -106,10 +126,15 @@ public static InsAssembly WithPublicKey(this InsAssembly assembly, byte[]? publi } public static InsAssembly WithPublicKeyToken(this InsAssembly assembly, ReadOnlySpan publicKeyToken) - => assembly.WithQualification(WellKnownQualificationNames.PublicKeyToken, FormatBlob(publicKeyToken)); + { + ArgumentNullException.ThrowIfNull(assembly); + return assembly.WithQualification(WellKnownQualificationNames.PublicKeyToken, FormatBlob(publicKeyToken)); + } public static InsAssembly WithPublicKeyToken(this InsAssembly assembly, byte[]? publicKeyToken) { + ArgumentNullException.ThrowIfNull(assembly); + if (publicKeyToken == null) { return assembly.WithQualification(WellKnownQualificationNames.PublicKeyToken, NullBlob); @@ -121,13 +146,24 @@ public static InsAssembly WithPublicKeyToken(this InsAssembly assembly, byte[]? } public static InsAssembly WithProcessorArchitecture(this InsAssembly assembly, ProcessorArchitecture processorArchitecture) - => assembly.WithQualification(WellKnownQualificationNames.ProcessorArchitecture, processorArchitecture.ToString()); + { + ArgumentNullException.ThrowIfNull(assembly); + return assembly.WithQualification(WellKnownQualificationNames.ProcessorArchitecture, processorArchitecture.ToString()); + } public static InsAssembly WithQualification(this InsAssembly assembly, string name, string value) - => assembly.WithQualifications(assembly.Qualifications.WithQualification(name, value)); + { + ArgumentNullException.ThrowIfNull(assembly); + ArgumentNullException.ThrowIfNull(name); + return assembly.WithQualifications(assembly.Qualifications.WithQualification(name, value)); + } public static InsAssembly WithoutQualification(this InsAssembly assembly, string name) - => assembly.WithQualifications(assembly.Qualifications.WithoutQualification(name)); + { + ArgumentNullException.ThrowIfNull(assembly); + ArgumentNullException.ThrowIfNull(name); + return assembly.WithQualifications(assembly.Qualifications.WithoutQualification(name)); + } static InsAssembly WithQualifications(this InsAssembly assembly, ImmutableArray newQualifications) { diff --git a/src/TypeNameInterpretation/InsFormatter.cs b/src/TypeNameInterpretation/InsFormatter.cs index f9a6504..ae61018 100644 --- a/src/TypeNameInterpretation/InsFormatter.cs +++ b/src/TypeNameInterpretation/InsFormatter.cs @@ -9,38 +9,28 @@ public static class InsFormatter { public static StringBuilder Write(StringBuilder builder, InsType type) { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - if (type == null) - { - throw new ArgumentNullException(nameof(type)); - } - + ArgumentNullException.ThrowIfNull(builder); + ArgumentNullException.ThrowIfNull(type); return Writer.Instance.WriteComplexType(type, builder); } public static StringBuilder Write(StringBuilder builder, InsAssembly assembly) { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - if (assembly == null) - { - throw new ArgumentNullException(nameof(assembly)); - } - + ArgumentNullException.ThrowIfNull(builder); + ArgumentNullException.ThrowIfNull(assembly); return Writer.WriteAssembly(assembly, builder); } - public static string Format(InsType type) => Write(BuilderPool.Rent(), type).ToStringAndReturn(); + public static string Format(InsType type) + { + ArgumentNullException.ThrowIfNull(type); + return Write(BuilderPool.Rent(), type).ToStringAndReturn(); + } public static string Format(InsAssembly assembly) { + ArgumentNullException.ThrowIfNull(assembly); + if (assembly.Qualifications.Length == 0 && assembly.Name.AsSpan().IndexOfAny(Delimiters.All) < 0) { return assembly.Name; diff --git a/src/TypeNameInterpretation/InsRewriter.cs b/src/TypeNameInterpretation/InsRewriter.cs index 2f66b9d..fd19f80 100644 --- a/src/TypeNameInterpretation/InsRewriter.cs +++ b/src/TypeNameInterpretation/InsRewriter.cs @@ -8,11 +8,7 @@ public abstract class InsRewriter : IInsTypeVisitor VisitTypes(ImmutableArray typeAr public virtual InsAssembly VisitAssembly(InsAssembly assembly, TArgument argument) { - if (assembly == null) - { - throw new ArgumentNullException(nameof(assembly)); - } - + ArgumentNullException.ThrowIfNull(assembly); var qualifications = VisitAssemblyQualifications(assembly.Qualifications, argument); if (qualifications == assembly.Qualifications) diff --git a/src/TypeNameInterpretation/Tree/InsArrayType.cs b/src/TypeNameInterpretation/Tree/InsArrayType.cs index b8c71d8..86c63fa 100644 --- a/src/TypeNameInterpretation/Tree/InsArrayType.cs +++ b/src/TypeNameInterpretation/Tree/InsArrayType.cs @@ -16,11 +16,7 @@ internal InsArrayType(InsType elementType, int rank) public override TReturn Apply(IInsTypeVisitor visitor, TArgument argument) { - if (visitor == null) - { - throw new ArgumentNullException(nameof(visitor)); - } - + ArgumentNullException.ThrowIfNull(visitor); return visitor.VisitArray(this, argument); } } diff --git a/src/TypeNameInterpretation/Tree/InsAssembly.cs b/src/TypeNameInterpretation/Tree/InsAssembly.cs index e87ed88..6ff37cb 100644 --- a/src/TypeNameInterpretation/Tree/InsAssembly.cs +++ b/src/TypeNameInterpretation/Tree/InsAssembly.cs @@ -8,7 +8,8 @@ public sealed class InsAssembly { internal InsAssembly(string name, ImmutableArray qualifications) { - Name = name ?? throw new ArgumentNullException(nameof(name)); + ArgumentNullException.ThrowIfNull(name); + Name = name; Qualifications = qualifications; } diff --git a/src/TypeNameInterpretation/Tree/InsAssemblyQualification.cs b/src/TypeNameInterpretation/Tree/InsAssemblyQualification.cs index 4a0d4f2..37a0b13 100644 --- a/src/TypeNameInterpretation/Tree/InsAssemblyQualification.cs +++ b/src/TypeNameInterpretation/Tree/InsAssemblyQualification.cs @@ -7,8 +7,10 @@ public sealed class InsAssemblyQualification { internal InsAssemblyQualification(string name, string value) { - Name = name ?? throw new ArgumentNullException(nameof(name)); - Value = value ?? throw new ArgumentNullException(nameof(value)); + ArgumentNullException.ThrowIfNull(name); + ArgumentNullException.ThrowIfNull(value); + Name = name; + Value = value; } public string Name { get; } diff --git a/src/TypeNameInterpretation/Tree/InsByRefType.cs b/src/TypeNameInterpretation/Tree/InsByRefType.cs index 4e1a2ef..e684898 100644 --- a/src/TypeNameInterpretation/Tree/InsByRefType.cs +++ b/src/TypeNameInterpretation/Tree/InsByRefType.cs @@ -14,11 +14,7 @@ internal InsByRefType(InsType elementType) public override TReturn Apply(IInsTypeVisitor visitor, TArgument argument) { - if (visitor == null) - { - throw new ArgumentNullException(nameof(visitor)); - } - + ArgumentNullException.ThrowIfNull(visitor); return visitor.VisitByRef(this, argument); } } diff --git a/src/TypeNameInterpretation/Tree/InsElementedType.cs b/src/TypeNameInterpretation/Tree/InsElementedType.cs index c153c23..6d089c4 100644 --- a/src/TypeNameInterpretation/Tree/InsElementedType.cs +++ b/src/TypeNameInterpretation/Tree/InsElementedType.cs @@ -7,7 +7,8 @@ public abstract class InsElementedType : InsType { private protected InsElementedType(InsType elementType) { - ElementType = elementType ?? throw new ArgumentNullException(nameof(elementType)); + ArgumentNullException.ThrowIfNull(elementType); + ElementType = elementType; } public InsType ElementType { get; } diff --git a/src/TypeNameInterpretation/Tree/InsGenericType.cs b/src/TypeNameInterpretation/Tree/InsGenericType.cs index 7ee2744..bad4396 100644 --- a/src/TypeNameInterpretation/Tree/InsGenericType.cs +++ b/src/TypeNameInterpretation/Tree/InsGenericType.cs @@ -8,7 +8,8 @@ public sealed class InsGenericType : InsType { internal InsGenericType(InsNamedType definition, ImmutableArray typeArguments) { - Definition = definition ?? throw new ArgumentNullException(nameof(definition)); + ArgumentNullException.ThrowIfNull(definition); + Definition = definition; TypeArguments = typeArguments; } @@ -18,11 +19,7 @@ internal InsGenericType(InsNamedType definition, ImmutableArray typeArg public override TReturn Apply(IInsTypeVisitor visitor, TArgument argument) { - if (visitor == null) - { - throw new ArgumentNullException(nameof(visitor)); - } - + ArgumentNullException.ThrowIfNull(visitor); return visitor.VisitGeneric(this, argument); } } diff --git a/src/TypeNameInterpretation/Tree/InsNamedType.cs b/src/TypeNameInterpretation/Tree/InsNamedType.cs index a1662a3..d92b9d3 100644 --- a/src/TypeNameInterpretation/Tree/InsNamedType.cs +++ b/src/TypeNameInterpretation/Tree/InsNamedType.cs @@ -9,7 +9,8 @@ internal InsNamedType( string name, InsAssembly? assembly) { - Name = name ?? throw new ArgumentNullException(nameof(name)); + ArgumentNullException.ThrowIfNull(name); + Name = name; Assembly = assembly; } @@ -17,8 +18,10 @@ internal InsNamedType( string name, InsNamedType? declaringType) { - Name = name ?? throw new ArgumentNullException(nameof(name)); - DeclaringType = declaringType ?? throw new ArgumentNullException(nameof(declaringType)); + ArgumentNullException.ThrowIfNull(name); + ArgumentNullException.ThrowIfNull(declaringType); + Name = name; + DeclaringType = declaringType; } public string Name { get; } @@ -28,11 +31,7 @@ internal InsNamedType( public override TReturn Apply(IInsTypeVisitor visitor, TArgument argument) { - if (visitor == null) - { - throw new ArgumentNullException(nameof(visitor)); - } - + ArgumentNullException.ThrowIfNull(visitor); return visitor.VisitNamed(this, argument); } } diff --git a/src/TypeNameInterpretation/Tree/InsPointerType.cs b/src/TypeNameInterpretation/Tree/InsPointerType.cs index 11693f9..ccd798f 100644 --- a/src/TypeNameInterpretation/Tree/InsPointerType.cs +++ b/src/TypeNameInterpretation/Tree/InsPointerType.cs @@ -14,11 +14,7 @@ internal InsPointerType(InsType elementType) public override TReturn Apply(IInsTypeVisitor visitor, TArgument argument) { - if (visitor == null) - { - throw new ArgumentNullException(nameof(visitor)); - } - + ArgumentNullException.ThrowIfNull(visitor); return visitor.VisitPointer(this, argument); } } diff --git a/src/TypeNameInterpretation/Tree/InsSZArrayType.cs b/src/TypeNameInterpretation/Tree/InsSZArrayType.cs index c26207e..9e8e1d7 100644 --- a/src/TypeNameInterpretation/Tree/InsSZArrayType.cs +++ b/src/TypeNameInterpretation/Tree/InsSZArrayType.cs @@ -14,11 +14,7 @@ internal InsSZArrayType(InsType elementType) public override TReturn Apply(IInsTypeVisitor visitor, TArgument argument) { - if (visitor == null) - { - throw new ArgumentNullException(nameof(visitor)); - } - + ArgumentNullException.ThrowIfNull(visitor); return visitor.VisitSZArray(this, argument); } }