diff --git a/.github/workflows/update-dependencies.yml b/.github/workflows/update-dependencies.yml index 4d72867..4b0c48b 100644 --- a/.github/workflows/update-dependencies.yml +++ b/.github/workflows/update-dependencies.yml @@ -19,3 +19,4 @@ jobs: secrets: inherit with: solutionsToCheck: 'nanoFramework.TestFramework.sln' + exclusionList: 'NFUnit Test Demo,NFUnit Test DemoByReference' diff --git a/poc/TestOfTestFrameworkByReference/NFUnitTestByReference.nfproj b/poc/TestOfTestFrameworkByReference/NFUnitTestByReference.nfproj index 9e2ef89..ab8367f 100644 --- a/poc/TestOfTestFrameworkByReference/NFUnitTestByReference.nfproj +++ b/poc/TestOfTestFrameworkByReference/NFUnitTestByReference.nfproj @@ -25,6 +25,7 @@ $(MSBuildProjectDirectory)\nano.runsettings + latest @@ -49,6 +50,9 @@ ..\packages\nanoFramework.Runtime.Native.1.6.12\lib\nanoFramework.Runtime.Native.dll + + ..\packages\nanoFramework.System.Runtime.1.0.27\lib\nanoFramework.System.Runtime.dll + diff --git a/poc/TestOfTestFrameworkByReference/Test.cs b/poc/TestOfTestFrameworkByReference/Test.cs index 8927799..22d44ab 100644 --- a/poc/TestOfTestFrameworkByReference/Test.cs +++ b/poc/TestOfTestFrameworkByReference/Test.cs @@ -5,6 +5,7 @@ // using System; +using System.Runtime.CompilerServices; using System.Threading; using nanoFramework.TestFramework; using NFUnitTest.Mock; @@ -263,7 +264,7 @@ private static void ThrowsException() public class SomethingElse { - public void NothingReally() + public void NothingReally(object value, [CallerArgumentExpression(nameof(value))] string parameter = null) { Console.WriteLine("Only classes marked with [TestClass] will run tests."); } diff --git a/poc/TestOfTestFrameworkByReference/packages.config b/poc/TestOfTestFrameworkByReference/packages.config index 5acdbc7..93b3aa9 100644 --- a/poc/TestOfTestFrameworkByReference/packages.config +++ b/poc/TestOfTestFrameworkByReference/packages.config @@ -2,4 +2,5 @@ + \ No newline at end of file diff --git a/source/TestFramework/CallerArgumentExpressionAttribute.cs b/source/TestFramework/CallerArgumentExpressionAttribute.cs new file mode 100644 index 0000000..ec3fb98 --- /dev/null +++ b/source/TestFramework/CallerArgumentExpressionAttribute.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// ReSharper disable once CheckNamespace +namespace System.Runtime.CompilerServices +{ + /// + /// Indicates that a parameter captures the expression passed for another parameter as a string. + /// + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] + internal sealed class CallerArgumentExpressionAttribute : Attribute + { + /// + /// Initializes a new instance of the class. + /// + /// The name of the parameter whose expression should be captured as a string. + public CallerArgumentExpressionAttribute(string parameterName) + { + ParameterName = parameterName; + } + + /// + /// Gets the name of the parameter whose expression should be captured as a string. + /// + public string ParameterName { get; } + } +} \ No newline at end of file diff --git a/source/TestFramework/NullableAttributes.cs b/source/TestFramework/NullableAttributes.cs new file mode 100644 index 0000000..e36c7e6 --- /dev/null +++ b/source/TestFramework/NullableAttributes.cs @@ -0,0 +1,181 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// ReSharper disable once CheckNamespace +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Specifies that is allowed as an input even if the corresponding type disallows it. + /// + /// + /// To override a method that has a parameter annotated with this attribute, use the ? operator. For more information, see Nullable static analysis in the C# guide. + /// + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] + internal sealed class AllowNullAttribute : Attribute + { } + + /// + /// Specifies that null is disallowed as an input even if the corresponding type allows it. + /// + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] + internal sealed class DisallowNullAttribute : Attribute + { } + + /// + /// Specifies that an output may be null even if the corresponding type disallows it. + /// + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class MaybeNullAttribute : Attribute + { } + + /// + /// Specifies that an output will not be null even if the corresponding type allows it. Specifies that an input argument was not null when the call returns. + /// + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class NotNullAttribute : Attribute + { } + + /// + /// Specifies that when a method returns , the parameter may be null even if the corresponding type disallows it. + /// + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class MaybeNullWhenAttribute : Attribute + { + /// + /// Initializes the attribute with the specified return value condition. + /// + /// + /// The return value condition. If the method returns this value, the associated parameter may be null. + /// + internal MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// + /// Gets the return value condition. + /// + internal bool ReturnValue { get; } + } + + /// + /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. + /// + internal sealed class NotNullWhenAttribute : Attribute + { + /// Initializes the attribute with the specified return value condition. + /// + /// The return value condition. If the method returns this value, the associated parameter will not be null. + /// + internal NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; + + /// Gets the return value condition. + internal bool ReturnValue { get; } + } + + /// + /// Specifies that the output will be non-null if the named parameter is non-null. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] + internal sealed class NotNullIfNotNullAttribute : Attribute + { + /// Initializes the attribute with the associated parameter name. + /// + /// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null. + /// + internal NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName; + + /// Gets the associated parameter name. + internal string ParameterName { get; } + } + + /// + /// Applied to a method that will never return under any circumstance. + /// + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + internal sealed class DoesNotReturnAttribute : Attribute + { } + + /// + /// Specifies that the method will not return if the associated Boolean parameter is passed the specified value. + /// + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class DoesNotReturnIfAttribute : Attribute + { + /// Initializes the attribute with the specified parameter value. + /// + /// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to + /// the associated parameter matches this value. + /// + internal DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue; + + /// + /// Gets the condition parameter value. + /// + internal 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 sealed class MemberNotNullAttribute : Attribute + { + /// Initializes the attribute with a field or property member. + /// + /// The field or property member that is promised to be not-null. + /// + internal 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. + /// + internal MemberNotNullAttribute(params string[] members) => Members = members; + + /// + /// Gets field or property member names. + /// + internal 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. + /// + internal 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. + /// + internal MemberNotNullWhenAttribute(bool returnValue, params string[] members) + { + ReturnValue = returnValue; + Members = members; + } + + /// + /// Gets the return value condition. + /// + internal bool ReturnValue { get; } + + /// + /// Gets field or property member names. + /// + internal string[] Members { get; } + } +} diff --git a/source/TestFramework/nanoFramework.TestFramework.nfproj b/source/TestFramework/nanoFramework.TestFramework.nfproj index ed41c19..b81f2cb 100644 --- a/source/TestFramework/nanoFramework.TestFramework.nfproj +++ b/source/TestFramework/nanoFramework.TestFramework.nfproj @@ -41,7 +41,9 @@ Assert.cs + + @@ -57,9 +59,6 @@ ..\..\packages\nanoFramework.CoreLibrary.1.15.5\lib\mscorlib.dll True - - ..\..\packages\nanoFramework.System.Runtime.1.0.27\lib\nanoFramework.System.Runtime.dll - diff --git a/source/TestFramework/packages.config b/source/TestFramework/packages.config index 0b25966..b466781 100644 --- a/source/TestFramework/packages.config +++ b/source/TestFramework/packages.config @@ -1,6 +1,5 @@ - + - \ No newline at end of file diff --git a/source/TestFramework/packages.lock.json b/source/TestFramework/packages.lock.json index 11aa244..be631b7 100644 --- a/source/TestFramework/packages.lock.json +++ b/source/TestFramework/packages.lock.json @@ -8,12 +8,6 @@ "resolved": "1.15.5", "contentHash": "u2+GvAp1uxLrGdILACAZy+EVKOs28EQ52j8Lz7599egXZ3GBGejjnR2ofhjMQwzrJLlgtyrsx8nSLngDfJNsAg==" }, - "nanoFramework.System.Runtime": { - "type": "Direct", - "requested": "[1.0.27, 1.0.27]", - "resolved": "1.0.27", - "contentHash": "aMwvQV6AR+XlDc+dHR/fWWnTe5dc7LDaqZS0ccfmd31Y39dZnmX3iQB2wXWtZGvXLCC+obc3IF3Vc70FiG0raw==" - }, "Nerdbank.GitVersioning": { "type": "Direct", "requested": "[3.6.139, 3.6.139]",