Skip to content

Commit

Permalink
Merge branch 'feature/polyfills'
Browse files Browse the repository at this point in the history
  • Loading branch information
ByronMayne committed Jan 31, 2024
2 parents f6097d9 + b80fee9 commit 484bada
Show file tree
Hide file tree
Showing 23 changed files with 487 additions and 32 deletions.
27 changes: 2 additions & 25 deletions GitVersion.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,2 @@
branches:
main:
regex: ^master$|^main$
mode: ContinuousDelivery
tag: 'rc'
increment: Patch
prevent-increment-of-merged-branch-version: true
track-merge-target: false
source-branches: [ 'develop', 'release' ]
tracks-release-branches: false
is-release-branch: false
is-mainline: true
pre-release-weight: 55000
develop:
regex: ^dev(elop)?(ment)?$
mode: ContinuousDeployment
tag: alpha
increment: Minor
prevent-increment-of-merged-branch-version: false
track-merge-target: true
source-branches: []
tracks-release-branches: true
is-release-branch: false
is-mainline: false
pre-release-weight: 0
mode: ContinuousDeployment
branches: {}
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,45 @@ This will popup the following window and you have to select your visual studio i

![AutoAttach](./img/DebuggerAttach.gif)

## Polyfills

Source generators are written targeting `netstandard2.0` which means you don't have access to some features of the language. By using this library you will get the following.

### `init` Properties:
```cs
// init gives a compiler error without the polyfill
public string MyProperty { get; init; }
```
These can be disabled by setting the `<SgfAddInitPropertyPolyfill>false<SgfAddInitPropertyPolyfill>`. The default value is `true`.

### Required Members
A way of specifying that a property or field is required to be set during object initialization, forcing the instance creator to provide an initial value for the member in an object initializer at the creation site.

```cs
public class MyClass
{
public required string Name { get; init; }
}
```
These can be disabled by setting the `<SgfAddRequiredMemberPolyfill>false<SgfAddRequiredMemberPolyfill>`. The default value is `true`.

### Nullable Attributes
These attributes enable the compiler to provide warnings when you may dereference a null value, throwing a [System.NullReferenceException](https://learn.microsoft.com/en-us/dotnet/api/system.nullreferenceexception).
| Attribute | Category | Meaning |
|-----------|----------|---------|
| `AllowNull` | Precondition | A non-nullable parameter, field, or property may be null.
| `DisallowNull` | Precondition | A nullable parameter, field, or property should never be null.
| `MaybeNull` | Postcondition | A non-nullable parameter, field, property, or return value may be null.
| `NotNull` | Postcondition | A nullable parameter, field, property, or return value will never be null.
| `MaybeNullWhen` | Conditional postcondition | A non-nullable argument may be null when the method returns the specified bool value.
| `NotNullWhen` | Conditional postcondition | A nullable argument won't be null when the method returns the specified bool value.
| `NotNullIfNotNull` | Conditional postcondition | A return value, property, or argument isn't null if the argument for the specified parameter isn't null.
| `MemberNotNull` | Method and property helper methods | The listed member won't be null when the method returns.
| `MemberNotNullWhen` | Method and property helper methods | The listed member won't be null when the method returns the specified bool value.
| `DoesNotReturn` | Unreachable code | A method or property never returns. In other words, it always throws an exception.
| `DoesNotReturnIf` | Unreachable code | This method or property never returns if the associated bool parameter has the specified value.

These can be disabled by setting the `<SgfAddNullablePolyfill>false<SgfAddNullablePolyfill>`. The default value is `true`.

## Helpers

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace System.Runtime.CompilerServices
{
using System.ComponentModel;
/// <summary>
/// Reserved to be used by the compiler for tracking metadata.
/// This class should not be used by developers in source code.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
internal static class IsExternalInit
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#nullable enable
#pragma warning disable
namespace System.Diagnostics.CodeAnalysis
{
using global::System;

/// <summary>
/// Specifies that <see langword="null"/> is allowed as an input even if the
/// corresponding type disallows it.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
[ExcludeFromCodeCoverage, DebuggerNonUserCode]
internal sealed class AllowNullAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="AllowNullAttribute"/> class.
/// </summary>
public AllowNullAttribute() { }
}
}

#pragma warning restore
#nullable restore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#nullable enable
#pragma warning disable

namespace System.Diagnostics.CodeAnalysis
{
using global::System;

/// <summary>
/// Specifies that <see langword="null"/> is disallowed as an input even if the
/// corresponding type allows it.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
[ExcludeFromCodeCoverage, DebuggerNonUserCode]
internal sealed class DisallowNullAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="DisallowNullAttribute"/> class.
/// </summary>
public DisallowNullAttribute() { }
}
}

#pragma warning restore
#nullable restore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#nullable enable
#pragma warning disable

namespace System.Diagnostics.CodeAnalysis
{
using global::System;

/// <summary>
/// Specifies that a method that will never return under any circumstance.
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
[ExcludeFromCodeCoverage, DebuggerNonUserCode]
internal sealed class DoesNotReturnAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="DoesNotReturnAttribute"/> class.
/// </summary>
public DoesNotReturnAttribute() { }
}
}
#pragma warning restore
#nullable restore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#nullable enable
#pragma warning disable

namespace System.Diagnostics.CodeAnalysis
{
using global::System;

/// <summary>
/// Specifies that the method will not return if the associated <see cref="Boolean"/>
/// parameter is passed the specified value.
/// </summary>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
[ExcludeFromCodeCoverage, DebuggerNonUserCode]
internal sealed class DoesNotReturnIfAttribute : Attribute
{
/// <summary>
/// Gets the condition parameter value. Code after the method is considered unreachable
/// by diagnostics if the argument to the associated parameter matches this value.
/// </summary>
public bool ParameterValue { get; }

/// <summary>
/// Initializes a new instance of the <see cref="DoesNotReturnIfAttribute"/>
/// class with the specified parameter value.
/// </summary>
/// <param name="parameterValue">
/// The condition parameter value. Code after the method is considered
/// unreachable by diagnostics if the argument to the associated parameter matches this value.
/// </param>
public DoesNotReturnIfAttribute(bool parameterValue)
{
}
}
}

#pragma warning restore
#nullable restore
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#nullable enable
#pragma warning disable

namespace System.Diagnostics.CodeAnalysis
{
using global::System;

/// <summary>
/// Specifies that an output may be <see langword="null"/> even if the
/// corresponding type disallows it.
/// </summary>
[AttributeUsage(
AttributeTargets.Field | AttributeTargets.Parameter |
AttributeTargets.Property | AttributeTargets.ReturnValue,
Inherited = false
)]
[ExcludeFromCodeCoverage, DebuggerNonUserCode]
internal sealed class MaybeNullAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="MaybeNullAttribute"/> class.
/// </summary>
public MaybeNullAttribute() { }
}
}

#pragma warning restore
#nullable restore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#nullable enable
#pragma warning disable

namespace System.Diagnostics.CodeAnalysis
{
using global::System;

/// <summary>
/// Specifies that when a method returns <see cref="ReturnValue"/>,
/// the parameter may be <see langword="null"/> even if the corresponding type disallows it.
/// </summary>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
[ExcludeFromCodeCoverage, DebuggerNonUserCode]
internal sealed class MaybeNullWhenAttribute : Attribute
{
/// <summary>
/// Gets the return value condition.
/// If the method returns this value, the associated parameter may be <see langword="null"/>.
/// </summary>
public bool ReturnValue { get; }

/// <summary>
/// Initializes the attribute with the specified return value condition.
/// </summary>
/// <param name="returnValue">
/// The return value condition.
/// If the method returns this value, the associated parameter may be <see langword="null"/>.
/// </param>
public MaybeNullWhenAttribute(bool returnValue)
{
ReturnValue = returnValue;
}
}
}
#pragma warning restore
#nullable restore
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#nullable enable
#pragma warning disable

namespace System.Diagnostics.CodeAnalysis
{
using global::System;

/// <summary>
/// Specifies that the method or property will ensure that the listed field and property members have
/// not-<see langword="null"/> values.
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
[ExcludeFromCodeCoverage, DebuggerNonUserCode]
internal sealed class MemberNotNullAttribute : Attribute
{
/// <summary>
/// Gets field or property member names.
/// </summary>
public string[] Members { get; }

/// <summary>
/// Initializes the attribute with a field or property member.
/// </summary>
/// <param name="member">
/// The field or property member that is promised to be not-null.
/// </param>
public MemberNotNullAttribute(string member)
{
Members = new[] { member };
}

/// <summary>
/// Initializes the attribute with the list of field and property members.
/// </summary>
/// <param name="members">
/// The list of field and property members that are promised to be not-null.
/// </param>
public MemberNotNullAttribute(params string[] members)
{
Members = members;
}
}
}

#pragma warning restore
#nullable restore
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#nullable enable
#pragma warning disable

namespace System.Diagnostics.CodeAnalysis
{
using global::System;

/// <summary>
/// Specifies that the method or property will ensure that the listed field and property members have
/// non-<see langword="null"/> values when returning with the specified return value condition.
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
[ExcludeFromCodeCoverage, DebuggerNonUserCode]
internal sealed class MemberNotNullWhenAttribute : Attribute
{
/// <summary>
/// Gets the return value condition.
/// </summary>
public bool ReturnValue { get; }

/// <summary>
/// Gets field or property member names.
/// </summary>
public string[] Members { get; }

/// <summary>
/// Initializes the attribute with the specified return value condition and a field or property member.
/// </summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value,
/// the associated parameter will not be <see langword="null"/>.
/// </param>
/// <param name="member">
/// The field or property member that is promised to be not-<see langword="null"/>.
/// </param>
public MemberNotNullWhenAttribute(bool returnValue, string member)
{
ReturnValue = returnValue;
Members = new[] { member };
}

/// <summary>
/// Initializes the attribute with the specified return value condition and list
/// of field and property members.
/// </summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value,
/// the associated parameter will not be <see langword="null"/>.
/// </param>
/// <param name="members">
/// The list of field and property members that are promised to be not-null.
/// </param>
public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
{
ReturnValue = returnValue;
Members = members;
}
}
}

#pragma warning restore
#nullable restore
Loading

0 comments on commit 484bada

Please sign in to comment.