├── Source
├── RuntimeNullables
│ ├── key.snk
│ ├── stylecop.json
│ ├── NullChecksAttribute.cs
│ └── RuntimeNullables.csproj
├── TestAssemblyNonPublic
│ ├── IPublicInterface.cs
│ ├── IInternalInterface.cs
│ ├── AssemblyAttributes.cs
│ ├── FodyWeavers.xml
│ ├── PublicContainingNestedNonPublic.cs
│ ├── stylecop.json
│ ├── InternalSubClass.cs
│ ├── PublicBaseClass.cs
│ ├── TestAssemblyNonPublic.csproj
│ └── FodyWeavers.xsd
├── TestAssembly
│ ├── NullableDisabled.cs
│ ├── Record.cs
│ ├── IsExternalInit.cs
│ ├── FodyWeavers.xml
│ ├── Combo.cs
│ ├── stylecop.json
│ ├── GeneratedCode.cs
│ ├── Properties.cs
│ ├── NestedContainer.cs
│ ├── TestAssembly.csproj
│ ├── Returns.cs
│ ├── InputParameters.cs
│ ├── Enumerables.cs
│ ├── Enumerators.cs
│ ├── OutputParameters.cs
│ ├── AsyncEnumerables.cs
│ ├── AsyncEnumerators.cs
│ ├── FodyWeavers.xsd
│ └── TaskResults.cs
├── RuntimeNullables.Fody
│ ├── NullableValue.cs
│ ├── Contexts
│ │ ├── AssemblyContext.cs
│ │ ├── GenericParameterInfo.cs
│ │ ├── PropertyContext.cs
│ │ ├── ModuleContext.cs
│ │ ├── WeavingContext.cs
│ │ ├── NullableContext.cs
│ │ ├── MethodContext.cs
│ │ └── TypeContext.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Extensions
│ │ ├── InstructionExtensions.cs
│ │ ├── InstructionCollectionExtensions.cs
│ │ ├── ParameterDefinitionExtensions.cs
│ │ ├── ReadOnlyListExtensions.cs
│ │ ├── NullableValueExtensions.cs
│ │ ├── MethodDefinitionExtensions.cs
│ │ ├── TypeReferenceExtensions.cs
│ │ └── AttributeProviderExtensions.cs
│ ├── RuntimeNullablesException.cs
│ ├── stylecop.json
│ ├── RuntimeNullables.Fody.csproj
│ ├── RuntimeNullables.Fody.xcf
│ ├── ModuleReferences.cs
│ ├── ReturnBlockInfo.cs
│ ├── ILHelpers.cs
│ ├── ModuleWeaver.cs
│ └── BclReferences.cs
├── TestAssemblyPointers
│ ├── Pointers.cs
│ ├── FodyWeavers.xml
│ ├── stylecop.json
│ ├── TestAssemblyPointers.csproj
│ └── FodyWeavers.xsd
├── TestAssemblyThrowHelpers
│ ├── FodyWeavers.xml
│ ├── stylecop.json
│ ├── UsesThrowHelpers.cs
│ ├── ThrowHelpers.cs
│ ├── TestAssemblyThrowHelpers.csproj
│ └── FodyWeavers.xsd
├── RuntimeNullables.Fody.Tests
│ ├── NullableDisabledTests.cs
│ ├── VerifyILTests.NullableDisabled.Debug.DotNet6_0.verified.txt
│ ├── VerifyILTests.NullableDisabled.Debug.DotNet7_0.verified.txt
│ ├── VerifyILTests.Pointers.Release.DotNet6_0.verified.txt
│ ├── VerifyILTests.Pointers.Release.DotNet7_0.verified.txt
│ ├── VerifyILTests.NullableDisabled.Release.DotNet6_0.verified.txt
│ ├── VerifyILTests.NullableDisabled.Release.DotNet7_0.verified.txt
│ ├── GeneratedCodeTests.cs
│ ├── CheckOutputsFalseTests.cs
│ ├── VerifyILTests.Pointers.Debug.DotNet6_0.verified.txt
│ ├── VerifyILTests.Pointers.Debug.DotNet7_0.verified.txt
│ ├── stylecop.json
│ ├── PointerTests.cs
│ ├── VerifyILTests.PublicContainingNestedNonPublic.Release.DotNet6_0.verified.txt
│ ├── VerifyILTests.PublicContainingNestedNonPublic.Release.DotNet7_0.verified.txt
│ ├── RecordTests.cs
│ ├── VerifyILTests.PublicContainingNestedNonPublic.Debug.DotNet6_0.verified.txt
│ ├── VerifyILTests.PublicContainingNestedNonPublic.Debug.DotNet7_0.verified.txt
│ ├── NestedTests.cs
│ ├── ThrowHelpersTests.cs
│ ├── VersioningTests.cs
│ ├── EnumerableTests.cs
│ ├── VerifyILTests.InjectedThrowHelpers.Debug.DotNet6_0.verified.txt
│ ├── VerifyILTests.InjectedThrowHelpers.Debug.DotNet7_0.verified.txt
│ ├── VerifyILTests.InjectedThrowHelpers.Release.DotNet6_0.verified.txt
│ ├── VerifyILTests.InjectedThrowHelpers.Release.DotNet7_0.verified.txt
│ ├── AssemblyTests.cs
│ ├── EnumeratorTests.cs
│ ├── PropertyTests.cs
│ ├── RuntimeNullables.Fody.Tests.csproj
│ ├── VerifyILTests.GeneratedCode.Release.DotNet6_0.verified.txt
│ ├── VerifyILTests.GeneratedCode.Release.DotNet7_0.verified.txt
│ ├── VerifyILTests.GeneratedCode.Debug.DotNet6_0.verified.txt
│ ├── VerifyILTests.GeneratedCode.Debug.DotNet7_0.verified.txt
│ ├── VerifyILTests.PublicBaseClass.Release.DotNet6_0.verified.txt
│ ├── VerifyILTests.PublicBaseClass.Release.DotNet7_0.verified.txt
│ ├── OutputParameterTests.cs
│ ├── ReturnTests.cs
│ ├── NonPublicTests.cs
│ ├── VerifyILTests.NestedContainer.Release.DotNet6_0.verified.txt
│ ├── VerifyILTests.NestedContainer.Release.DotNet7_0.verified.txt
│ ├── VerifyILTests.PublicBaseClass.Debug.DotNet6_0.verified.txt
│ ├── VerifyILTests.PublicBaseClass.Debug.DotNet7_0.verified.txt
│ ├── AsyncEnumerableTests.cs
│ ├── VerifyPETests.cs
│ ├── ComboAndMessageTests.cs
│ ├── VerifyILTests.NestedContainer.Debug.DotNet6_0.verified.txt
│ ├── VerifyILTests.NestedContainer.Debug.DotNet7_0.verified.txt
│ ├── AsyncEnumeratorTests.cs
│ ├── VerifyILTests.Combo.Release.DotNet6_0.verified.txt
│ ├── VerifyILTests.Combo.Release.DotNet7_0.verified.txt
│ ├── InputParametersTests.cs
│ ├── VerifyILTests.Combo.Debug.DotNet6_0.verified.txt
│ ├── VerifyILTests.Combo.Debug.DotNet7_0.verified.txt
│ ├── VerifyILTests.InternalSubClass.Release.DotNet6_0.verified.txt
│ ├── VerifyILTests.InternalSubClass.Release.DotNet7_0.verified.txt
│ ├── VerifyILTests.InternalSubClass.Debug.DotNet6_0.verified.txt
│ ├── VerifyILTests.InternalSubClass.Debug.DotNet7_0.verified.txt
│ ├── TaskResultTests.cs
│ ├── VerifyILTests.InputParameters.Release.DotNet6_0.verified.txt
│ ├── VerifyILTests.InputParameters.Release.DotNet7_0.verified.txt
│ ├── VerifyILTests.InputParameters.Debug.DotNet6_0.verified.txt
│ ├── VerifyILTests.InputParameters.Debug.DotNet7_0.verified.txt
│ ├── VerifyILTests.cs
│ ├── VerifyILTests.Returns.Debug.DotNet6_0.verified.txt
│ ├── VerifyILTests.Returns.Debug.DotNet7_0.verified.txt
│ ├── VerifyILTests.Returns.Release.DotNet6_0.verified.txt
│ └── VerifyILTests.Returns.Release.DotNet7_0.verified.txt
├── stylecop.json
└── Directory.Build.props
├── Resources
└── Singulink Icon 128x128.png
├── LICENSE
└── .github
└── workflows
└── build-and-test.yml
/Source/RuntimeNullables/key.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Singulink/RuntimeNullables/HEAD/Source/RuntimeNullables/key.snk
--------------------------------------------------------------------------------
/Resources/Singulink Icon 128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Singulink/RuntimeNullables/HEAD/Resources/Singulink Icon 128x128.png
--------------------------------------------------------------------------------
/Source/TestAssemblyNonPublic/IPublicInterface.cs:
--------------------------------------------------------------------------------
1 | namespace TestAssemblyNonPublic;
2 |
3 | public interface IPublicInterface
4 | {
5 | void InterfacePublicMethod(string value);
6 | }
--------------------------------------------------------------------------------
/Source/TestAssemblyNonPublic/IInternalInterface.cs:
--------------------------------------------------------------------------------
1 | namespace TestAssemblyNonPublic;
2 |
3 | internal interface IInternalInterface
4 | {
5 | void InterfaceInternalMethod(string value);
6 | }
--------------------------------------------------------------------------------
/Source/TestAssembly/NullableDisabled.cs:
--------------------------------------------------------------------------------
1 | namespace TestAssembly;
2 |
3 | #nullable disable
4 |
5 | public static class NullableDisabled
6 | {
7 | public static string NonNull(string x) => x;
8 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/NullableValue.cs:
--------------------------------------------------------------------------------
1 | namespace RuntimeNullables.Fody;
2 |
3 | internal enum NullableValue : byte
4 | {
5 | Oblivious = 0,
6 | NotAnnotated = 1,
7 | Annotated = 2,
8 | }
--------------------------------------------------------------------------------
/Source/TestAssembly/Record.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace TestAssembly;
6 |
7 | public record Record(string Name, int Value)
8 | {
9 | }
--------------------------------------------------------------------------------
/Source/TestAssemblyNonPublic/AssemblyAttributes.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 | using RuntimeNullables;
3 |
4 | [assembly: NullChecks(false)]
5 | [assembly: InternalsVisibleTo("RuntimeNullables.Fody.Tests")]
--------------------------------------------------------------------------------
/Source/TestAssemblyPointers/Pointers.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable CA1801 // Review unused parameters
2 | namespace TestAssemblyPointers;
3 |
4 | public static class Pointers
5 | {
6 | public static unsafe int* Ignored(int* value) { return value; }
7 | }
--------------------------------------------------------------------------------
/Source/TestAssembly/IsExternalInit.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 |
3 | #pragma warning disable CA1812
4 |
5 | namespace System.Runtime.CompilerServices;
6 |
7 | [EditorBrowsable(EditorBrowsableState.Never)]
8 | internal static class IsExternalInit { }
--------------------------------------------------------------------------------
/Source/TestAssemblyThrowHelpers/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Source/TestAssemblyNonPublic/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Source/TestAssembly/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Source/TestAssemblyPointers/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/Contexts/AssemblyContext.cs:
--------------------------------------------------------------------------------
1 | using Mono.Cecil;
2 |
3 | namespace RuntimeNullables.Fody.Contexts;
4 |
5 | internal class AssemblyContext : NullableContext
6 | {
7 | public AssemblyContext(AssemblyDefinition assembly, WeavingContext weavingContext) : base(assembly, weavingContext) { }
8 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/NullableDisabledTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 | using TestAssembly;
3 |
4 | namespace RuntimeNullables.Fody.Tests;
5 |
6 | [TestClass]
7 | public class NullableDisabledTests
8 | {
9 | [TestMethod]
10 | public void NonNull() => NullableDisabled.NonNull(null);
11 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/VerifyILTests.NullableDisabled.Debug.DotNet6_0.verified.txt:
--------------------------------------------------------------------------------
1 | .class public abstract auto ansi sealed beforefieldinit TestAssembly.NullableDisabled
2 | extends [System.Runtime]System.Object
3 | {
4 | .method public hidebysig static string
5 | NonNull(string x) cil managed
6 | {
7 | .maxstack 8
8 | IL_0000: ldarg.0
9 | IL_0001: ret
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/VerifyILTests.NullableDisabled.Debug.DotNet7_0.verified.txt:
--------------------------------------------------------------------------------
1 | .class public abstract auto ansi sealed beforefieldinit TestAssembly.NullableDisabled
2 | extends [System.Runtime]System.Object
3 | {
4 | .method public hidebysig static string
5 | NonNull(string x) cil managed
6 | {
7 | .maxstack 8
8 | IL_0000: ldarg.0
9 | IL_0001: ret
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/VerifyILTests.Pointers.Release.DotNet6_0.verified.txt:
--------------------------------------------------------------------------------
1 | .class public abstract auto ansi sealed beforefieldinit TestAssemblyPointers.Pointers
2 | extends [System.Runtime]System.Object
3 | {
4 | .method public hidebysig static int32*
5 | Ignored(int32* 'value') cil managed
6 | {
7 | .maxstack 8
8 | IL_0000: ldarg.0
9 | IL_0001: ret
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/VerifyILTests.Pointers.Release.DotNet7_0.verified.txt:
--------------------------------------------------------------------------------
1 | .class public abstract auto ansi sealed beforefieldinit TestAssemblyPointers.Pointers
2 | extends [System.Runtime]System.Object
3 | {
4 | .method public hidebysig static int32*
5 | Ignored(int32* 'value') cil managed
6 | {
7 | .maxstack 8
8 | IL_0000: ldarg.0
9 | IL_0001: ret
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/VerifyILTests.NullableDisabled.Release.DotNet6_0.verified.txt:
--------------------------------------------------------------------------------
1 | .class public abstract auto ansi sealed beforefieldinit TestAssembly.NullableDisabled
2 | extends [System.Runtime]System.Object
3 | {
4 | .method public hidebysig static string
5 | NonNull(string x) cil managed
6 | {
7 | .maxstack 8
8 | IL_0000: ldarg.0
9 | IL_0001: ret
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/VerifyILTests.NullableDisabled.Release.DotNet7_0.verified.txt:
--------------------------------------------------------------------------------
1 | .class public abstract auto ansi sealed beforefieldinit TestAssembly.NullableDisabled
2 | extends [System.Runtime]System.Object
3 | {
4 | .method public hidebysig static string
5 | NonNull(string x) cil managed
6 | {
7 | .maxstack 8
8 | IL_0000: ldarg.0
9 | IL_0001: ret
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/GeneratedCodeTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using TestAssembly;
4 |
5 | namespace RuntimeNullables.Fody.Tests;
6 |
7 | [TestClass]
8 | public class GeneratedCodeTests
9 | {
10 | [TestMethod]
11 | public void NoChecksOnGeneratedCode()
12 | {
13 | GeneratedCode.Method(null!);
14 | }
15 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "RuntimeNullables.Fody": {
4 | "commandName": "Executable",
5 | "executablePath": "C:\\Program Files\\dotnet\\dotnet.exe",
6 | "commandLineArgs": "msbuild -t:Rebuild",
7 | "workingDirectory": "C:\\Users\\mikem\\Documents\\Projects\\Singulink\\RuntimeNullables\\Source\\"
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/CheckOutputsFalseTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 | using TestAssemblyNonPublic;
3 |
4 | namespace RuntimeNullables.Fody.Tests;
5 |
6 | [TestClass]
7 | public class CheckOutputsFalseTests
8 | {
9 | [TestMethod]
10 | public void CheckOutputsFalse()
11 | {
12 | PublicBaseClass.UncheckedBadReferenceReturn();
13 | }
14 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/Contexts/GenericParameterInfo.cs:
--------------------------------------------------------------------------------
1 | using Mono.Cecil;
2 |
3 | namespace RuntimeNullables.Fody.Contexts;
4 |
5 | internal struct GenericParameterInfo
6 | {
7 | public GenericParameter Parameter { get; }
8 |
9 | public bool Nullable { get; }
10 |
11 | public GenericParameterInfo(GenericParameter parameter, bool nullable)
12 | {
13 | Parameter = parameter;
14 | Nullable = nullable;
15 | }
16 | }
--------------------------------------------------------------------------------
/Source/TestAssemblyNonPublic/PublicContainingNestedNonPublic.cs:
--------------------------------------------------------------------------------
1 | using RuntimeNullables;
2 |
3 | #pragma warning disable RCS1163 // Unused parameter.
4 | #pragma warning disable CA1801 // Review unused parameters
5 |
6 | namespace TestAssemblyNonPublic;
7 |
8 | [NullChecks(true)]
9 | public static class PublicContainingNestedNonPublic
10 | {
11 | internal static class Nested
12 | {
13 | public static void Method(string value) { }
14 | }
15 | }
--------------------------------------------------------------------------------
/Source/TestAssembly/Combo.cs:
--------------------------------------------------------------------------------
1 | namespace TestAssembly;
2 |
3 | public class Combo where TClass : notnull
4 | {
5 | public string GetValue(bool returnNull, TClass inputValue, ref TMethod refValue, bool outputNull) where TMethod : class
6 | {
7 | string returnValue = returnNull ? null! : inputValue.ToString() + refValue.ToString();
8 |
9 | if (outputNull)
10 | refValue = default!;
11 |
12 | return returnValue;
13 | }
14 | }
--------------------------------------------------------------------------------
/Source/stylecop.json:
--------------------------------------------------------------------------------
1 | {
2 | // Enabling configuration: https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md
3 |
4 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
5 | "settings": {
6 | "documentationRules": {
7 | "documentInternalElements": false,
8 | "documentInterfaces": false
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/Extensions/InstructionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Mono.Cecil.Cil;
2 |
3 | namespace RuntimeNullables.Fody.Extensions;
4 |
5 | public static class InstructionExtensions
6 | {
7 | public static Instruction Clone(this Instruction instruction)
8 | {
9 | if (instruction.Operand == null)
10 | return Instruction.Create(instruction.OpCode);
11 |
12 | return Instruction.Create(instruction.OpCode, (dynamic)instruction.Operand);
13 | }
14 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/RuntimeNullablesException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace RuntimeNullables.Fody;
4 |
5 | public class RuntimeNullablesException : Exception
6 | {
7 | public RuntimeNullablesException()
8 | {
9 | }
10 |
11 | public RuntimeNullablesException(string message) : base(message)
12 | {
13 | }
14 |
15 | public RuntimeNullablesException(string message, Exception innerException) : base(message, innerException)
16 | {
17 | }
18 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables/stylecop.json:
--------------------------------------------------------------------------------
1 | {
2 | // Enabling configuration: https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md
3 |
4 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
5 | "settings": {
6 | "documentationRules": {
7 | "documentExposedElements": true,
8 | "documentInternalElements": false
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/TestAssembly/stylecop.json:
--------------------------------------------------------------------------------
1 | {
2 | // Enabling configuration: https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md
3 |
4 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
5 | "settings": {
6 | "documentationRules": {
7 | "documentExposedElements": false,
8 | "documentInternalElements": false
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/stylecop.json:
--------------------------------------------------------------------------------
1 | {
2 | // Enabling configuration: https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md
3 |
4 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
5 | "settings": {
6 | "documentationRules": {
7 | "documentExposedElements": false,
8 | "documentInternalElements": false
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/TestAssemblyPointers/stylecop.json:
--------------------------------------------------------------------------------
1 | {
2 | // Enabling configuration: https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md
3 |
4 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
5 | "settings": {
6 | "documentationRules": {
7 | "documentExposedElements": false,
8 | "documentInternalElements": false
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/VerifyILTests.Pointers.Debug.DotNet6_0.verified.txt:
--------------------------------------------------------------------------------
1 | .class public abstract auto ansi sealed beforefieldinit TestAssemblyPointers.Pointers
2 | extends [System.Runtime]System.Object
3 | {
4 | .method public hidebysig static int32*
5 | Ignored(int32* 'value') cil managed
6 | {
7 | .maxstack 1
8 | .locals init (int32* V_0)
9 | IL_0000: nop
10 | IL_0001: ldarg.0
11 | IL_0002: stloc.0
12 | IL_0003: br.s IL_0005
13 | IL_0005: ldloc.0
14 | IL_0006: ret
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/VerifyILTests.Pointers.Debug.DotNet7_0.verified.txt:
--------------------------------------------------------------------------------
1 | .class public abstract auto ansi sealed beforefieldinit TestAssemblyPointers.Pointers
2 | extends [System.Runtime]System.Object
3 | {
4 | .method public hidebysig static int32*
5 | Ignored(int32* 'value') cil managed
6 | {
7 | .maxstack 1
8 | .locals init (int32* V_0)
9 | IL_0000: nop
10 | IL_0001: ldarg.0
11 | IL_0002: stloc.0
12 | IL_0003: br.s IL_0005
13 | IL_0005: ldloc.0
14 | IL_0006: ret
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Source/TestAssemblyThrowHelpers/stylecop.json:
--------------------------------------------------------------------------------
1 | {
2 | // Enabling configuration: https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md
3 |
4 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
5 | "settings": {
6 | "documentationRules": {
7 | "documentExposedElements": false,
8 | "documentInternalElements": false
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/stylecop.json:
--------------------------------------------------------------------------------
1 | {
2 | // Enabling configuration: https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md
3 |
4 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
5 | "settings": {
6 | "documentationRules": {
7 | "documentExposedElements": false,
8 | "documentInternalElements": false
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/PointerTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 | using TestAssemblyPointers;
3 |
4 | namespace RuntimeNullables.Fody.Tests;
5 |
6 | [TestClass]
7 | public class PointerTests
8 | {
9 | private readonly int _value = 5;
10 |
11 | [TestMethod]
12 | public unsafe void PointerIgnored()
13 | {
14 | fixed (int* value = &_value) {
15 | Pointers.Ignored(value);
16 | Pointers.Ignored(null);
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/Source/TestAssembly/GeneratedCode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace TestAssembly;
6 |
7 | [System.CodeDom.Compiler.GeneratedCodeAttribute("RuntimeNullables.Fody", "1.0.0")]
8 | public static class GeneratedCode
9 | {
10 | // Nested type without GeneratedCodeAttribute to ensure it doesn't trigger parent type context building (fixed in v1.0.5)
11 | public delegate void SomeDelegate(object obj);
12 |
13 | public static void Method(object obj)
14 | {
15 | }
16 | }
--------------------------------------------------------------------------------
/Source/TestAssemblyNonPublic/stylecop.json:
--------------------------------------------------------------------------------
1 | {
2 | // Enabling configuration: https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md
3 |
4 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
5 | "settings": {
6 | "documentationRules": {
7 | "documentExposedElements": false,
8 | "documentInternalElements": false,
9 | "documentInterfaces": false
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/Extensions/InstructionCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Mono.Cecil.Cil;
2 | using Mono.Collections.Generic;
3 |
4 | namespace RuntimeNullables.Fody.Extensions;
5 |
6 | internal static class InstructionCollectionExtensions
7 | {
8 | public static int LastIndexOf(this Collection collection, Instruction item)
9 | {
10 | for (int i = collection.Count - 1; i >= 0; i--) {
11 | if (collection[i] == item)
12 | return i;
13 | }
14 |
15 | return -1;
16 | }
17 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/RuntimeNullables.Fody.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 | 1591
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Source/TestAssemblyThrowHelpers/UsesThrowHelpers.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 | using System.Threading.Tasks;
3 |
4 | #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
5 |
6 | namespace TestAssemblyThrowHelpers;
7 |
8 | public static class UsesThrowHelpers
9 | {
10 | public static string ReturnParameter(string value) => value;
11 |
12 | public static string ReturnNullableParameterNonNullReturn(string? value) => value!;
13 |
14 | public static async Task ReturnAllowNullParameterNonNullReturnAsync([AllowNull] string value) => value!;
15 | }
--------------------------------------------------------------------------------
/Source/TestAssemblyThrowHelpers/ThrowHelpers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data;
3 | using System.IO;
4 |
5 | namespace RuntimeNullables;
6 |
7 | internal static class ThrowHelpers
8 | {
9 | // Pick different random exceptions just so we can make sure these helpers are being invoked.
10 |
11 | public static void ThrowArgumentNull(string paramName) => throw new InvalidOperationException(paramName);
12 |
13 | public static void ThrowOutputNull(string message) => throw new InvalidDataException(message);
14 |
15 | public static Exception GetAsyncResultNullException(string message) => new InvalidConstraintException(message);
16 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/VerifyILTests.PublicContainingNestedNonPublic.Release.DotNet6_0.verified.txt:
--------------------------------------------------------------------------------
1 | .class public abstract auto ansi sealed beforefieldinit TestAssemblyNonPublic.PublicContainingNestedNonPublic
2 | extends [System.Runtime]System.Object
3 | {
4 | .class abstract auto ansi sealed nested assembly beforefieldinit Nested
5 | extends [System.Runtime]System.Object
6 | {
7 | .method public hidebysig static void
8 | Method(string 'value') cil managed
9 | {
10 | .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 )
11 | .maxstack 8
12 | IL_0000: ret
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/VerifyILTests.PublicContainingNestedNonPublic.Release.DotNet7_0.verified.txt:
--------------------------------------------------------------------------------
1 | .class public abstract auto ansi sealed beforefieldinit TestAssemblyNonPublic.PublicContainingNestedNonPublic
2 | extends [System.Runtime]System.Object
3 | {
4 | .class abstract auto ansi sealed nested assembly beforefieldinit Nested
5 | extends [System.Runtime]System.Object
6 | {
7 | .method public hidebysig static void
8 | Method(string 'value') cil managed
9 | {
10 | .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 )
11 | .maxstack 8
12 | IL_0000: ret
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/RecordTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using TestAssembly;
4 |
5 | namespace RuntimeNullables.Fody.Tests;
6 |
7 | [TestClass]
8 | public class RecordTests
9 | {
10 | [TestMethod]
11 | public void Good()
12 | {
13 | var record = new Record("test", 5);
14 | record = record with { Name = "test2" };
15 | }
16 |
17 | [TestMethod]
18 | public void Bad()
19 | {
20 | var record = new Record("test", 5);
21 | Assert.ThrowsException(() => record = record with { Name = null! });
22 | }
23 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/Extensions/ParameterDefinitionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Mono.Cecil;
2 |
3 | namespace RuntimeNullables.Fody.Extensions;
4 |
5 | internal static class ParameterDefinitionExtensions
6 | {
7 | // Preconditions:
8 |
9 | public static bool HasAllowNullAttribute(this ParameterDefinition parameter)
10 | {
11 | return parameter.HasAttribute("System.Diagnostics.CodeAnalysis.AllowNullAttribute");
12 | }
13 |
14 | public static bool HasDisallowNullAttribute(this ParameterDefinition parameter)
15 | {
16 | return parameter.HasAttribute("System.Diagnostics.CodeAnalysis.DisallowNullAttribute");
17 | }
18 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/VerifyILTests.PublicContainingNestedNonPublic.Debug.DotNet6_0.verified.txt:
--------------------------------------------------------------------------------
1 | .class public abstract auto ansi sealed beforefieldinit TestAssemblyNonPublic.PublicContainingNestedNonPublic
2 | extends [System.Runtime]System.Object
3 | {
4 | .class abstract auto ansi sealed nested assembly beforefieldinit Nested
5 | extends [System.Runtime]System.Object
6 | {
7 | .method public hidebysig static void
8 | Method(string 'value') cil managed
9 | {
10 | .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 )
11 | .maxstack 8
12 | IL_0000: nop
13 | IL_0001: ret
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/VerifyILTests.PublicContainingNestedNonPublic.Debug.DotNet7_0.verified.txt:
--------------------------------------------------------------------------------
1 | .class public abstract auto ansi sealed beforefieldinit TestAssemblyNonPublic.PublicContainingNestedNonPublic
2 | extends [System.Runtime]System.Object
3 | {
4 | .class abstract auto ansi sealed nested assembly beforefieldinit Nested
5 | extends [System.Runtime]System.Object
6 | {
7 | .method public hidebysig static void
8 | Method(string 'value') cil managed
9 | {
10 | .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 )
11 | .maxstack 8
12 | IL_0000: nop
13 | IL_0001: ret
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/Extensions/ReadOnlyListExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace RuntimeNullables.Fody.Extensions;
4 |
5 | internal static class ReadOnlyListExtensions
6 | {
7 | public static int IndexOf(this IReadOnlyList readOnlyList, T item)
8 | {
9 | var comparer = EqualityComparer.Default;
10 |
11 | if (readOnlyList is IList list)
12 | return list.IndexOf(item);
13 |
14 | for (int i = 0; i < readOnlyList.Count; i++) {
15 | if (comparer.Equals(readOnlyList[i], item))
16 | return i;
17 | }
18 |
19 | return -1;
20 | }
21 | }
--------------------------------------------------------------------------------
/Source/TestAssemblyNonPublic/InternalSubClass.cs:
--------------------------------------------------------------------------------
1 | using RuntimeNullables;
2 |
3 | namespace TestAssemblyNonPublic;
4 |
5 | [NullChecks(true)]
6 | internal class InternalSubClass : PublicBaseClass, IPublicInterface, IInternalInterface
7 | {
8 | public override void AbstractPublicMethod(string value) { }
9 |
10 | public override void VirtualPublicMethod(string value) { }
11 |
12 | internal override void AbstractInternalMethod(string value) { }
13 |
14 | internal override void VirtualInternalMethod(string value) { }
15 |
16 | void IPublicInterface.InterfacePublicMethod(string value) { }
17 |
18 | void IInternalInterface.InterfaceInternalMethod(string value) { }
19 | }
--------------------------------------------------------------------------------
/Source/TestAssembly/Properties.cs:
--------------------------------------------------------------------------------
1 | namespace TestAssembly;
2 |
3 | ///
4 | /// Properties are all initially null, even for non-nullable properties.
5 | ///
6 | public class Properties
7 | {
8 | private string _reference = null!;
9 | private string? _nullableReference;
10 |
11 | public string ReferenceAuto { get; set; } = null!;
12 |
13 | public string Reference {
14 | get => _reference;
15 | set => _reference = value;
16 | }
17 |
18 | public string? NullableReferenceAuto { get; set; }
19 |
20 | public string? NullableReference {
21 | get => _nullableReference;
22 | set => _nullableReference = value;
23 | }
24 | }
--------------------------------------------------------------------------------
/Source/TestAssembly/NestedContainer.cs:
--------------------------------------------------------------------------------
1 | using RuntimeNullables;
2 |
3 | #pragma warning disable CA1801 // Review unused parameters
4 |
5 | namespace TestAssembly;
6 |
7 | public static class NestedContainer
8 | {
9 | [NullChecks(false)]
10 | public static class Nested
11 | {
12 | public static void Unchecked(string value) { }
13 |
14 | [NullChecks(true)]
15 | public static void Checked(string value) { }
16 |
17 | public static class NestedDeeper
18 | {
19 | public static void Unchecked(string value) { }
20 |
21 | [NullChecks(true)]
22 | public static void Checked(string value) { }
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/Source/TestAssemblyNonPublic/PublicBaseClass.cs:
--------------------------------------------------------------------------------
1 | using RuntimeNullables;
2 |
3 | namespace TestAssemblyNonPublic;
4 |
5 | [NullChecks(true)]
6 | public abstract class PublicBaseClass
7 | {
8 | ///
9 | /// CheckOutputs is turned off for this project so this should work without throwing an exception.
10 | ///
11 | public static string UncheckedBadReferenceReturn() => null!;
12 |
13 | public abstract void AbstractPublicMethod(string value);
14 |
15 | public virtual void VirtualPublicMethod(string value) { }
16 |
17 | internal abstract void AbstractInternalMethod(string value);
18 |
19 | internal virtual void VirtualInternalMethod(string value) { }
20 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/RuntimeNullables.Fody.xcf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Determines whether outputs (return values and out/ref parameters) have null checks injected.
6 |
7 |
8 |
9 |
10 | Determines whether non-public members have null checks injected or if only public entry points are checked.
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/Extensions/NullableValueExtensions.cs:
--------------------------------------------------------------------------------
1 | using RuntimeNullables.Fody.Contexts;
2 |
3 | namespace RuntimeNullables.Fody.Extensions;
4 |
5 | internal static class NullableValueExtensions
6 | {
7 | public static bool ToIsNullable(this NullableValue nullableValue, WeavingContext weavingContext)
8 | {
9 | switch (nullableValue) {
10 | case NullableValue.Oblivious:
11 | case NullableValue.Annotated:
12 | return true;
13 | case NullableValue.NotAnnotated:
14 | return false;
15 | default:
16 | weavingContext.WriteError("Unexpected nullable argument value.");
17 | return true;
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/NestedTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using TestAssembly;
4 | using TestAssemblyNonPublic;
5 |
6 | namespace RuntimeNullables.Fody.Tests;
7 |
8 | [TestClass]
9 | public class NestedTests
10 | {
11 | [TestMethod]
12 | public void NoNullChecksNested()
13 | {
14 | NestedContainer.Nested.Unchecked(null!);
15 | NestedContainer.Nested.NestedDeeper.Unchecked(null!);
16 | }
17 |
18 | [TestMethod]
19 | public void NullChecksNested()
20 | {
21 | Assert.ThrowsException(() => NestedContainer.Nested.Checked(null!));
22 | Assert.ThrowsException(() => NestedContainer.Nested.NestedDeeper.Checked(null!));
23 | }
24 |
25 | [TestMethod]
26 | public void PublicContainingNestedNonPublicClass()
27 | {
28 | PublicContainingNestedNonPublic.Nested.Method(null!);
29 | }
30 | }
--------------------------------------------------------------------------------
/Source/TestAssemblyPointers/TestAssemblyPointers.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0;net7.0
5 | true
6 |
7 |
8 | 1591
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | all
23 | runtime; build; native; contentfiles; analyzers; buildtransitive
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/ThrowHelpersTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data;
3 | using System.IO;
4 | using System.Threading.Tasks;
5 | using Microsoft.VisualStudio.TestTools.UnitTesting;
6 | using TestAssemblyThrowHelpers;
7 |
8 | namespace RuntimeNullables.Fody.Tests;
9 |
10 | [TestClass]
11 | public class ThrowHelpersTests
12 | {
13 | [TestMethod]
14 | public void ArgumentNull()
15 | {
16 | Assert.ThrowsException(() => UsesThrowHelpers.ReturnParameter(null!));
17 | }
18 |
19 | [TestMethod]
20 | public void OutputNull()
21 | {
22 | Assert.ThrowsException(() => UsesThrowHelpers.ReturnNullableParameterNonNullReturn(null));
23 | }
24 |
25 | [TestMethod]
26 | public Task OutputNullAsync()
27 | {
28 | return Assert.ThrowsExceptionAsync(() => UsesThrowHelpers.ReturnAllowNullParameterNonNullReturnAsync(null));
29 | }
30 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables/NullChecksAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace RuntimeNullables;
4 |
5 | ///
6 | /// Indicates whether nullable reference type null checks should be injected.
7 | ///
8 | [AttributeUsage(
9 | AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum |
10 | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.ReturnValue,
11 | Inherited = false)]
12 | public sealed class NullChecksAttribute : Attribute
13 | {
14 | ///
15 | /// Gets a value indicating whether nullable reference type null checks should be injected.
16 | ///
17 | public bool Enabled { get; }
18 |
19 | ///
20 | /// Initializes a new instance of the class.
21 | ///
22 | public NullChecksAttribute(bool enabled)
23 | {
24 | Enabled = enabled;
25 | }
26 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/VersioningTests.cs:
--------------------------------------------------------------------------------
1 | using System.CodeDom.Compiler;
2 | using System.Reflection;
3 | using Microsoft.VisualStudio.TestTools.UnitTesting;
4 | using TestAssembly;
5 |
6 | namespace RuntimeNullables.Fody.Tests;
7 |
8 | [TestClass]
9 | public class VersioningTests
10 | {
11 | [TestMethod]
12 | public void GeneratedCodeToolVersion()
13 | {
14 | // Ensure that the GeneratedCodeAttribute version placed on the throw helper class is correct.
15 |
16 | var throwHelperType = typeof(InputParameters).Assembly.GetType("RuntimeNullables.ThrowHelpers");
17 | string generatedCodeVersion = throwHelperType!.GetCustomAttribute()!.Version;
18 |
19 | string weaverVersion = new AssemblyName(typeof(ModuleWeaver).Assembly.FullName!).Version!.ToString();
20 | string addinVersion = new AssemblyName(typeof(NullChecksAttribute).Assembly.FullName!).Version!.ToString();
21 |
22 | Assert.AreEqual(weaverVersion, generatedCodeVersion);
23 | Assert.AreEqual(addinVersion, generatedCodeVersion);
24 | }
25 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/ModuleReferences.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Mono.Cecil;
3 |
4 | namespace RuntimeNullables.Fody;
5 |
6 | internal class ModuleReferences
7 | {
8 | private readonly MethodReference? _throwOutputNullMethod;
9 | private readonly MethodReference? _getAsyncResultNullExceptionMethod;
10 |
11 | public MethodReference ThrowArgumentNullMethod { get; }
12 |
13 | public MethodReference ThrowOutputNullMethod => _throwOutputNullMethod ?? throw new InvalidOperationException("Output throw helper not set.");
14 |
15 | public MethodReference GetAsyncResultNullExceptionMethod => _getAsyncResultNullExceptionMethod ?? throw new InvalidOperationException("Output throw helper not set.");
16 |
17 | public ModuleReferences(MethodReference throwArgumentNullMethod, MethodReference? throwOutputNullMethod, MethodReference? getAsyncResultNullExceptionMethod)
18 | {
19 | ThrowArgumentNullMethod = throwArgumentNullMethod;
20 | _throwOutputNullMethod = throwOutputNullMethod;
21 | _getAsyncResultNullExceptionMethod = getAsyncResultNullExceptionMethod;
22 | }
23 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Singulink
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/Contexts/PropertyContext.cs:
--------------------------------------------------------------------------------
1 | using Mono.Cecil;
2 |
3 | namespace RuntimeNullables.Fody.Contexts;
4 |
5 | internal sealed class PropertyContext : NullableContext
6 | {
7 | public PropertyDefinition Property { get; }
8 |
9 | public TypeContext TypeContext { get; }
10 |
11 | public MethodContext? GetMethodContext { get; private set; }
12 |
13 | public MethodContext? SetMethodContext { get; private set; }
14 |
15 | public PropertyContext(PropertyDefinition property, TypeContext typeContext) : base(property, typeContext)
16 | {
17 | Property = property;
18 | TypeContext = typeContext;
19 | }
20 |
21 | public override void Build()
22 | {
23 | base.Build();
24 |
25 | if (Property.GetMethod != null) {
26 | GetMethodContext = new MethodContext(Property.GetMethod, this);
27 | GetMethodContext.Build();
28 | }
29 |
30 | if (Property.SetMethod != null) {
31 | SetMethodContext = new MethodContext(Property.SetMethod, this);
32 | SetMethodContext.Build();
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody/Extensions/MethodDefinitionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Mono.Cecil;
2 | using RuntimeNullables.Fody.Contexts;
3 |
4 | namespace RuntimeNullables.Fody.Extensions;
5 |
6 | internal static class MethodDefinitionExtensions
7 | {
8 | public static TypeDefinition? GetIteratorStateMachineType(this MethodDefinition method, WeavingContext weavingContext)
9 | {
10 | return method.GetConstructorArgValue("System.Runtime.CompilerServices.IteratorStateMachineAttribute", weavingContext)?.Resolve();
11 | }
12 |
13 | public static TypeDefinition? GetAsyncStateMachineType(this MethodDefinition method, WeavingContext weavingContext)
14 | {
15 | return method.GetConstructorArgValue("System.Runtime.CompilerServices.AsyncStateMachineAttribute", weavingContext)?.Resolve();
16 | }
17 |
18 | public static TypeDefinition? GetAsyncIteratorStateMachineType(this MethodDefinition method, WeavingContext weavingContext)
19 | {
20 | return method.GetConstructorArgValue("System.Runtime.CompilerServices.AsyncIteratorStateMachineAttribute", weavingContext)?.Resolve();
21 | }
22 | }
--------------------------------------------------------------------------------
/Source/TestAssemblyThrowHelpers/TestAssemblyThrowHelpers.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0;net7.0
5 |
6 | 1591
7 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | all
25 | runtime; build; native; contentfiles; analyzers; buildtransitive
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Source/TestAssembly/TestAssembly.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0;net7.0
5 |
6 | 1591
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | all
21 | runtime; build; native; contentfiles; analyzers; buildtransitive
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Source/TestAssembly/Returns.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 | using RuntimeNullables;
3 |
4 | namespace TestAssembly;
5 |
6 | public static class Returns
7 | {
8 | public static string GoodReference() => string.Empty;
9 |
10 | public static string BadReference() => null!;
11 |
12 | public static string? NullableReference() => null;
13 |
14 | [return: NullChecks(false)]
15 | public static string NoNullChecksBadReference() => null!;
16 |
17 | [NullChecks(false)]
18 | [return: NullChecks(true)]
19 | public static string NullChecksOnNoNullChecksMethodBadReference() => null!;
20 |
21 | public static T GoodGenericNotNullConstraint() where T : notnull, new() => new T();
22 |
23 | public static T BadGenericNotNullConstraint() where T : notnull, new() => default!;
24 |
25 | [return: NotNull]
26 | public static T GoodGenericNotNullAttribute() where T : new() => new T();
27 |
28 | [return: NotNull]
29 | public static T BadGenericNotNullAttribute() => default!;
30 |
31 | [return: MaybeNull]
32 | public static T GenericMaybeNullAttribute() where T : class => null;
33 |
34 | public static T GenericUnconstrained() => default!;
35 | }
--------------------------------------------------------------------------------
/Source/RuntimeNullables.Fody.Tests/EnumerableTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 | using TestAssembly;
4 |
5 | namespace RuntimeNullables.Fody.Tests;
6 |
7 | [TestClass]
8 | public class EnumerableTests
9 | {
10 | [TestMethod]
11 | public void GoodGetReferences()
12 | {
13 | foreach (var value in Enumerables.GoodGetReferences()) { }
14 | }
15 |
16 | [TestMethod]
17 | public void BadGetReferences()
18 | {
19 | Assert.ThrowsException(() => {
20 | foreach (var value in Enumerables.BadGetReferences()) { }
21 | });
22 | }
23 |
24 | [TestMethod]
25 | public void GoodGetGenerics()
26 | {
27 | foreach (var value in Enumerables.GoodGetGenerics