Skip to content

Commit 173c01d

Browse files
committed
Feat: StackBackports TryPop & TryPeek
1 parent f3f5465 commit 173c01d

File tree

4 files changed

+331
-172
lines changed

4 files changed

+331
-172
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,173 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
2-
// The .NET Foundation licenses this file to you under the MIT license.
3-
4-
// This was copied from https://github.com/dotnet/runtime/blob/39b9607807f29e48cae4652cd74735182b31182e/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs
5-
// and updated to have the scope of the attributes be public.
6-
7-
// Anna's note:
8-
// yes this is a copy instead of just a nice import of a package.
9-
// I have searched far and wide for a better solution, but here we are...
10-
// It isn't the perfect solution, but at least this way we don't have a complaining IDE / compiler anymore
11-
12-
// ReSharper disable once CheckNamespace
13-
// ReSharper disable UnusedAutoPropertyAccessor.Global
14-
// ReSharper disable UnusedType.Global
15-
namespace System.Diagnostics.CodeAnalysis;
16-
#if NETSTANDARD2_0
17-
18-
/// <summary>Specifies that null is allowed as an input even if the corresponding type disallows it.</summary>
19-
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property)]
20-
public sealed class AllowNullAttribute : Attribute;
21-
22-
/// <summary>Specifies that null is disallowed as an input even if the corresponding type allows it.</summary>
23-
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property)]
24-
public sealed class DisallowNullAttribute : Attribute;
25-
26-
/// <summary>Specifies that an output may be null even if the corresponding type disallows it.</summary>
27-
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue)]
28-
public sealed class MaybeNullAttribute : Attribute;
29-
30-
/// <summary>Specifies that an output will not be null even if the corresponding type allows it.</summary>
31-
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue)]
32-
public sealed class NotNullAttribute : Attribute;
33-
34-
/// <summary>
35-
/// Specifies that when a method returns <see cref="ReturnValue" />, the parameter may be null even if the
36-
/// corresponding type disallows it.
37-
/// </summary>
38-
[AttributeUsage(AttributeTargets.Parameter)]
39-
public sealed class MaybeNullWhenAttribute : Attribute {
40-
/// <summary>Initializes the attribute with the specified return value condition.</summary>
41-
/// <param name="returnValue">
42-
/// The return value condition. If the method returns this value, the associated parameter may be null.
43-
/// </param>
44-
public MaybeNullWhenAttribute(bool returnValue) {
45-
ReturnValue = returnValue;
46-
}
47-
48-
/// <summary> Gets the return value condition.</summary>
49-
public bool ReturnValue { get; }
50-
}
51-
52-
/// <summary>
53-
/// Specifies that when a method returns <see cref="ReturnValue" />, the parameter will not be null even if the
54-
/// corresponding type allows it.
55-
/// </summary>
56-
[AttributeUsage(AttributeTargets.Parameter)]
57-
public sealed class NotNullWhenAttribute : Attribute {
58-
/// <summary>Initializes the attribute with the specified return value condition.</summary>
59-
/// <param name="returnValue">
60-
/// The return value condition. If the method returns this value, the associated parameter will not be null.
61-
/// </param>
62-
public NotNullWhenAttribute(bool returnValue) {
63-
ReturnValue = returnValue;
64-
}
65-
66-
/// <summary>Gets the return value condition.</summary>
67-
public bool ReturnValue { get; }
68-
}
69-
70-
/// <summary>Specifies that the output will be non-null if the named parameter is non-null.</summary>
71-
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true)]
72-
public sealed class NotNullIfNotNullAttribute : Attribute {
73-
/// <summary>Initializes the attribute with the associated parameter name.</summary>
74-
/// <param name="parameterName">
75-
/// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null.
76-
/// </param>
77-
public NotNullIfNotNullAttribute(string parameterName) {
78-
ParameterName = parameterName;
79-
}
80-
81-
/// <summary>Gets the associated parameter name.</summary>
82-
public string ParameterName { get; }
83-
}
84-
85-
/// <summary>Applied to a method that will never return under any circumstance.</summary>
86-
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
87-
public sealed class DoesNotReturnAttribute : Attribute;
88-
89-
/// <summary>Specifies that the method will not return if the associated Boolean parameter is passed the specified value.</summary>
90-
[AttributeUsage(AttributeTargets.Parameter)]
91-
public sealed class DoesNotReturnIfAttribute : Attribute {
92-
/// <summary>Initializes the attribute with the specified parameter value.</summary>
93-
/// <param name="parameterValue">
94-
/// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument
95-
/// to
96-
/// the associated parameter matches this value.
97-
/// </param>
98-
public DoesNotReturnIfAttribute(bool parameterValue) {
99-
ParameterValue = parameterValue;
100-
}
101-
102-
/// <summary>Gets the condition parameter value.</summary>
103-
public bool ParameterValue { get; }
104-
}
105-
106-
#endif
107-
108-
#if !NETCOREAPP
109-
110-
/// <summary>
111-
/// Specifies that the method or property will ensure that the listed field and property members have not-null
112-
/// values.
113-
/// </summary>
114-
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
115-
public sealed class MemberNotNullAttribute : Attribute {
116-
/// <summary>Initializes the attribute with a field or property member.</summary>
117-
/// <param name="member">
118-
/// The field or property member that is promised to be not-null.
119-
/// </param>
120-
public MemberNotNullAttribute(string member) {
121-
Members = [member];
122-
}
123-
124-
/// <summary>Initializes the attribute with the list of field and property members.</summary>
125-
/// <param name="members">
126-
/// The list of field and property members that are promised to be not-null.
127-
/// </param>
128-
public MemberNotNullAttribute(params string[] members) {
129-
Members = members;
130-
}
131-
132-
/// <summary>Gets field or property member names.</summary>
133-
public string[] Members { get; }
134-
}
135-
136-
/// <summary>
137-
/// Specifies that the method or property will ensure that the listed field and property members have not-null
138-
/// values when returning with the specified return value condition.
139-
/// </summary>
140-
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
141-
public sealed class MemberNotNullWhenAttribute : Attribute {
142-
/// <summary>Initializes the attribute with the specified return value condition and a field or property member.</summary>
143-
/// <param name="returnValue">
144-
/// The return value condition. If the method returns this value, the associated parameter will not be null.
145-
/// </param>
146-
/// <param name="member">
147-
/// The field or property member that is promised to be not-null.
148-
/// </param>
149-
public MemberNotNullWhenAttribute(bool returnValue, string member) {
150-
ReturnValue = returnValue;
151-
Members = [member];
152-
}
153-
154-
/// <summary>Initializes the attribute with the specified return value condition and list of field and property members.</summary>
155-
/// <param name="returnValue">
156-
/// The return value condition. If the method returns this value, the associated parameter will not be null.
157-
/// </param>
158-
/// <param name="members">
159-
/// The list of field and property members that are promised to be not-null.
160-
/// </param>
161-
public MemberNotNullWhenAttribute(bool returnValue, params string[] members) {
162-
ReturnValue = returnValue;
163-
Members = members;
164-
}
165-
166-
/// <summary>Gets the return value condition.</summary>
167-
public bool ReturnValue { get; }
168-
169-
/// <summary>Gets field or property member names.</summary>
170-
public string[] Members { get; }
171-
}
172-
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
// This was copied from https://github.com/dotnet/runtime/blob/39b9607807f29e48cae4652cd74735182b31182e/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs
5+
// and updated to have the scope of the attributes be public.
6+
7+
// Anna's note:
8+
// yes this is a copy instead of just a nice import of a package.
9+
// I have searched far and wide for a better solution, but here we are...
10+
// It isn't the perfect solution, but at least this way we don't have a complaining IDE / compiler anymore
11+
12+
// ReSharper disable once CheckNamespace
13+
// ReSharper disable UnusedAutoPropertyAccessor.Global
14+
// ReSharper disable UnusedType.Global
15+
namespace System.Diagnostics.CodeAnalysis;
16+
#if NETSTANDARD2_0
17+
18+
/// <summary>Specifies that null is allowed as an input even if the corresponding type disallows it.</summary>
19+
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property)]
20+
public sealed class AllowNullAttribute : Attribute;
21+
22+
/// <summary>Specifies that null is disallowed as an input even if the corresponding type allows it.</summary>
23+
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property)]
24+
public sealed class DisallowNullAttribute : Attribute;
25+
26+
/// <summary>Specifies that an output may be null even if the corresponding type disallows it.</summary>
27+
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue)]
28+
public sealed class MaybeNullAttribute : Attribute;
29+
30+
/// <summary>Specifies that an output will not be null even if the corresponding type allows it.</summary>
31+
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue)]
32+
public sealed class NotNullAttribute : Attribute;
33+
34+
/// <summary>
35+
/// Specifies that when a method returns <see cref="ReturnValue" />, the parameter may be null even if the
36+
/// corresponding type disallows it.
37+
/// </summary>
38+
[AttributeUsage(AttributeTargets.Parameter)]
39+
public sealed class MaybeNullWhenAttribute : Attribute {
40+
/// <summary>Initializes the attribute with the specified return value condition.</summary>
41+
/// <param name="returnValue">
42+
/// The return value condition. If the method returns this value, the associated parameter may be null.
43+
/// </param>
44+
public MaybeNullWhenAttribute(bool returnValue) {
45+
ReturnValue = returnValue;
46+
}
47+
48+
/// <summary> Gets the return value condition.</summary>
49+
public bool ReturnValue { get; }
50+
}
51+
52+
/// <summary>
53+
/// Specifies that when a method returns <see cref="ReturnValue" />, the parameter will not be null even if the
54+
/// corresponding type allows it.
55+
/// </summary>
56+
[AttributeUsage(AttributeTargets.Parameter)]
57+
public sealed class NotNullWhenAttribute : Attribute {
58+
/// <summary>Initializes the attribute with the specified return value condition.</summary>
59+
/// <param name="returnValue">
60+
/// The return value condition. If the method returns this value, the associated parameter will not be null.
61+
/// </param>
62+
public NotNullWhenAttribute(bool returnValue) {
63+
ReturnValue = returnValue;
64+
}
65+
66+
/// <summary>Gets the return value condition.</summary>
67+
public bool ReturnValue { get; }
68+
}
69+
70+
/// <summary>Specifies that the output will be non-null if the named parameter is non-null.</summary>
71+
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true)]
72+
public sealed class NotNullIfNotNullAttribute : Attribute {
73+
/// <summary>Initializes the attribute with the associated parameter name.</summary>
74+
/// <param name="parameterName">
75+
/// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null.
76+
/// </param>
77+
public NotNullIfNotNullAttribute(string parameterName) {
78+
ParameterName = parameterName;
79+
}
80+
81+
/// <summary>Gets the associated parameter name.</summary>
82+
public string ParameterName { get; }
83+
}
84+
85+
/// <summary>Applied to a method that will never return under any circumstance.</summary>
86+
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
87+
public sealed class DoesNotReturnAttribute : Attribute;
88+
89+
/// <summary>Specifies that the method will not return if the associated Boolean parameter is passed the specified value.</summary>
90+
[AttributeUsage(AttributeTargets.Parameter)]
91+
public sealed class DoesNotReturnIfAttribute : Attribute {
92+
/// <summary>Initializes the attribute with the specified parameter value.</summary>
93+
/// <param name="parameterValue">
94+
/// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument
95+
/// to
96+
/// the associated parameter matches this value.
97+
/// </param>
98+
public DoesNotReturnIfAttribute(bool parameterValue) {
99+
ParameterValue = parameterValue;
100+
}
101+
102+
/// <summary>Gets the condition parameter value.</summary>
103+
public bool ParameterValue { get; }
104+
}
105+
106+
#endif
107+
108+
#if !NETCOREAPP
109+
110+
/// <summary>
111+
/// Specifies that the method or property will ensure that the listed field and property members have not-null
112+
/// values.
113+
/// </summary>
114+
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
115+
public sealed class MemberNotNullAttribute : Attribute {
116+
/// <summary>Initializes the attribute with a field or property member.</summary>
117+
/// <param name="member">
118+
/// The field or property member that is promised to be not-null.
119+
/// </param>
120+
public MemberNotNullAttribute(string member) {
121+
Members = [member];
122+
}
123+
124+
/// <summary>Initializes the attribute with the list of field and property members.</summary>
125+
/// <param name="members">
126+
/// The list of field and property members that are promised to be not-null.
127+
/// </param>
128+
public MemberNotNullAttribute(params string[] members) {
129+
Members = members;
130+
}
131+
132+
/// <summary>Gets field or property member names.</summary>
133+
public string[] Members { get; }
134+
}
135+
136+
/// <summary>
137+
/// Specifies that the method or property will ensure that the listed field and property members have not-null
138+
/// values when returning with the specified return value condition.
139+
/// </summary>
140+
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
141+
public sealed class MemberNotNullWhenAttribute : Attribute {
142+
/// <summary>Initializes the attribute with the specified return value condition and a field or property member.</summary>
143+
/// <param name="returnValue">
144+
/// The return value condition. If the method returns this value, the associated parameter will not be null.
145+
/// </param>
146+
/// <param name="member">
147+
/// The field or property member that is promised to be not-null.
148+
/// </param>
149+
public MemberNotNullWhenAttribute(bool returnValue, string member) {
150+
ReturnValue = returnValue;
151+
Members = [member];
152+
}
153+
154+
/// <summary>Initializes the attribute with the specified return value condition and list of field and property members.</summary>
155+
/// <param name="returnValue">
156+
/// The return value condition. If the method returns this value, the associated parameter will not be null.
157+
/// </param>
158+
/// <param name="members">
159+
/// The list of field and property members that are promised to be not-null.
160+
/// </param>
161+
public MemberNotNullWhenAttribute(bool returnValue, params string[] members) {
162+
ReturnValue = returnValue;
163+
Members = members;
164+
}
165+
166+
/// <summary>Gets the return value condition.</summary>
167+
public bool ReturnValue { get; }
168+
169+
/// <summary>Gets field or property member names.</summary>
170+
public string[] Members { get; }
171+
}
172+
173173
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
#if NETSTANDARD2_0
5+
using System.Diagnostics.CodeAnalysis;
6+
7+
// ReSharper disable once CheckNamespace
8+
namespace System.Collections.Generic;
9+
#else
10+
using System.Collections.Generic;
11+
using System.Diagnostics.CodeAnalysis;
12+
13+
namespace CodeOfChaos.GeneratorTools;
14+
#endif
15+
16+
// ---------------------------------------------------------------------------------------------------------------------
17+
// Code
18+
// ---------------------------------------------------------------------------------------------------------------------
19+
public static class StackBackports {
20+
#if NETSTANDARD2_0
21+
public static bool TryPop<T>(this Stack<T> stack, [NotNullWhen(true)] out T? result) {
22+
result = default;
23+
if (stack.Count == 0) return false;
24+
result = stack.Pop();
25+
return result is not null;
26+
}
27+
28+
public static bool TryPeek<T>(this Stack<T> stack, [NotNullWhen(true)] out T? result) {
29+
result = default;
30+
if (stack.Count == 0) return false;
31+
result = stack.Peek();
32+
return result is not null;
33+
}
34+
#endif
35+
36+
#if NET9_0_OR_GREATER
37+
public static bool TryPop<T>(Stack<T> stack, [NotNullWhen(true)] out T? result) {
38+
result = default;
39+
if (stack.Count == 0) return false;
40+
result = stack.Pop();
41+
return result is not null;
42+
}
43+
44+
public static bool TryPeek<T>(Stack<T> stack, [NotNullWhen(true)] out T? result) {
45+
result = default;
46+
if (stack.Count == 0) return false;
47+
result = stack.Peek();
48+
return result is not null;
49+
}
50+
#endif
51+
}

0 commit comments

Comments
 (0)