Skip to content

Commit 1d302e3

Browse files
committed
refactor
1 parent b74e49d commit 1d302e3

File tree

3 files changed

+84
-54
lines changed

3 files changed

+84
-54
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// SPDX-FileCopyrightText: 2022 smdn <smdn@smdn.jp>
2+
// SPDX-License-Identifier: MIT
3+
using System;
4+
using System.Linq;
5+
using System.Reflection;
6+
7+
namespace Smdn.Reflection;
8+
9+
internal static class MemberInfoNullableMetadataExtensions {
10+
private static bool IsNullableAttribute(CustomAttributeData attr)
11+
=> "System.Runtime.CompilerServices.NullableAttribute".Equals(attr.AttributeType.FullName, StringComparison.Ordinal);
12+
13+
private static bool IsNullableContextAttribute(CustomAttributeData attr)
14+
=> "System.Runtime.CompilerServices.NullableContextAttribute".Equals(attr.AttributeType.FullName, StringComparison.Ordinal);
15+
16+
internal static NullableMetadataValue? GetNullableAttributeMetadataValue(this MemberInfo memberOrType)
17+
{
18+
var data = memberOrType.CustomAttributes.FirstOrDefault(IsNullableAttribute);
19+
20+
if (data is null)
21+
return null;
22+
23+
return (NullableMetadataValue?)(byte?)data.ConstructorArguments[0].Value;
24+
}
25+
26+
internal static NullableMetadataValue? GetNullableContextAttributeMetadataValue(this MemberInfo memberOrType)
27+
{
28+
if (
29+
memberOrType is Type genericParameter &&
30+
#if SYSTEM_TYPE_ISGENERICMETHODPARAMETER
31+
genericParameter.IsGenericMethodParameter &&
32+
#else
33+
genericParameter.DeclaringMethod is not null &&
34+
genericParameter.IsGenericParameter &&
35+
#endif
36+
GetMetadataValue(genericParameter.DeclaringMethod!, out var valueOfGenericParameter)
37+
) {
38+
return valueOfGenericParameter;
39+
}
40+
41+
MemberInfo? m = memberOrType;
42+
43+
for (; ; ) {
44+
if (GetMetadataValue(m, out var value))
45+
return value;
46+
if ((m = m!.DeclaringType) is null)
47+
return null;
48+
49+
// retry against to the outer type
50+
continue;
51+
}
52+
53+
static bool GetMetadataValue(MemberInfo memberOrType, out NullableMetadataValue? value)
54+
{
55+
var data = memberOrType.CustomAttributes.FirstOrDefault(IsNullableContextAttribute);
56+
57+
if (data is null) {
58+
value = null;
59+
return false;
60+
}
61+
62+
value = (NullableMetadataValue?)(byte?)data.ConstructorArguments[0].Value;
63+
64+
return value.HasValue;
65+
}
66+
}
67+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// SPDX-FileCopyrightText: 2022 smdn <smdn@smdn.jp>
2+
// SPDX-License-Identifier: MIT
3+
using System;
4+
using System.Linq;
5+
using System.Reflection;
6+
7+
namespace Smdn.Reflection;
8+
9+
// ref: https://github.com/dotnet/roslyn/blob/main/docs/features/nullable-metadata.md
10+
internal enum NullableMetadataValue : byte {
11+
Oblivious = 0,
12+
NotAnnotated = 1,
13+
Annotated = 2,
14+
}

src/Smdn.Reflection.ReverseGenerating/Smdn.Reflection/TypeGenericParameterExtensions.cs

Lines changed: 3 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -23,63 +23,12 @@ public static bool HasGenericParameterNotNullConstraint(this Type genericParamet
2323
{
2424
ValidateGenericParameterArgument(genericParameter, nameof(genericParameter));
2525

26-
var attrNullable = genericParameter.CustomAttributes.FirstOrDefault(IsNullableAttribute);
27-
var attrNullableContext = FindNullableContextAttribute(genericParameter);
28-
29-
const byte notAnnotated = 1;
30-
31-
if (attrNullableContext is not null && notAnnotated.Equals(attrNullableContext.ConstructorArguments[0].Value))
26+
if (genericParameter.GetNullableContextAttributeMetadataValue() == NullableMetadataValue.NotAnnotated)
3227
// `#nullable enable` context
33-
return attrNullable is null;
28+
return genericParameter.GetNullableAttributeMetadataValue() == null;
3429
else
3530
// `#nullable disable` context
36-
return attrNullable is not null && notAnnotated.Equals(attrNullable.ConstructorArguments[0].Value);
37-
}
38-
39-
private static bool IsNullableAttribute(CustomAttributeData attr)
40-
=> "System.Runtime.CompilerServices.NullableAttribute".Equals(attr.AttributeType.FullName, StringComparison.Ordinal);
41-
42-
private static bool IsNullableContextAttribute(CustomAttributeData attr)
43-
=> "System.Runtime.CompilerServices.NullableContextAttribute".Equals(attr.AttributeType.FullName, StringComparison.Ordinal);
44-
45-
private static bool TryGetNullableContextAttribute(
46-
MemberInfo member,
47-
#if NULL_STATE_STATIC_ANALYSIS_ATTRIBUTES
48-
[NotNullWhen(true)]
49-
#endif
50-
out CustomAttributeData? attrNullableContext
51-
)
52-
{
53-
attrNullableContext = member.CustomAttributes.FirstOrDefault(IsNullableContextAttribute);
54-
55-
return attrNullableContext is not null;
56-
}
57-
58-
private static CustomAttributeData? FindNullableContextAttribute(Type genericParameter)
59-
{
60-
if (
61-
#if SYSTEM_TYPE_ISGENERICMETHODPARAMETER
62-
genericParameter.IsGenericMethodParameter &&
63-
#else
64-
genericParameter.DeclaringMethod is not null &&
65-
genericParameter.IsGenericParameter &&
66-
#endif
67-
TryGetNullableContextAttribute(genericParameter.DeclaringMethod!, out var methodAttr)
68-
) {
69-
return methodAttr;
70-
}
71-
72-
Type? t = genericParameter;
73-
74-
for (; ; ) {
75-
if ((t = t!.DeclaringType) is null)
76-
return null;
77-
if (TryGetNullableContextAttribute(t, out var typeAttr))
78-
return typeAttr;
79-
80-
// retry against to the outer type
81-
continue;
82-
}
31+
return genericParameter.GetNullableAttributeMetadataValue() == NullableMetadataValue.NotAnnotated;
8332
}
8433

8534
public static bool HasGenericParameterNoConstraints(this Type genericParameter)

0 commit comments

Comments
 (0)