Skip to content

Commit ce36501

Browse files
committed
Added components for handling generic parameters
1 parent 287103c commit ce36501

8 files changed

+280
-146
lines changed

src/Thinktecture.Runtime.Extensions.SourceGenerator/CodeAnalysis/DelegateMethodState.cs

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -55,50 +55,4 @@ public override int GetHashCode()
5555
return hashCode;
5656
}
5757
}
58-
59-
public sealed class ParameterState : IEquatable<ParameterState>, IHashCodeComputable
60-
{
61-
public string Name { get; }
62-
public string Type { get; }
63-
public RefKind RefKind { get; }
64-
65-
public ParameterState(
66-
string name,
67-
string type,
68-
RefKind refKind)
69-
{
70-
Name = name;
71-
Type = type;
72-
RefKind = refKind;
73-
}
74-
75-
public override bool Equals(object? obj)
76-
{
77-
return obj is ParameterState other && Equals(other);
78-
}
79-
80-
public bool Equals(ParameterState? other)
81-
{
82-
if (other is null)
83-
return false;
84-
85-
if (ReferenceEquals(this, other))
86-
return true;
87-
88-
return Name == other.Name
89-
&& Type == other.Type
90-
&& RefKind == other.RefKind;
91-
}
92-
93-
public override int GetHashCode()
94-
{
95-
unchecked
96-
{
97-
var hashCode = Name.GetHashCode();
98-
hashCode = (hashCode * 397) ^ Type.GetHashCode();
99-
hashCode = (hashCode * 397) ^ (int)RefKind;
100-
return hashCode;
101-
}
102-
}
103-
}
10458
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
namespace Thinktecture.CodeAnalysis;
2+
3+
public sealed class GenericTypeParameterState : IEquatable<GenericTypeParameterState>, IHashCodeComputable
4+
{
5+
public string Name { get; }
6+
public IReadOnlyList<string> Constraints { get; }
7+
8+
public GenericTypeParameterState(
9+
string name,
10+
IReadOnlyList<string> constraints)
11+
{
12+
Name = name;
13+
Constraints = constraints;
14+
}
15+
16+
public override bool Equals(object? obj)
17+
{
18+
return obj is GenericTypeParameterState other && Equals(other);
19+
}
20+
21+
public bool Equals(GenericTypeParameterState? other)
22+
{
23+
if (other is null)
24+
return false;
25+
26+
if (ReferenceEquals(this, other))
27+
return true;
28+
29+
return Name == other.Name
30+
&& Constraints.SequenceEqual(other.Constraints);
31+
}
32+
33+
public override int GetHashCode()
34+
{
35+
unchecked
36+
{
37+
var hashCode = Name.GetHashCode();
38+
hashCode = (hashCode * 397) ^ Constraints.ComputeHashCode();
39+
return hashCode;
40+
}
41+
}
42+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
namespace Thinktecture.CodeAnalysis;
2+
3+
public sealed class ParameterState : IEquatable<ParameterState>, IHashCodeComputable
4+
{
5+
public string Name { get; }
6+
public string Type { get; }
7+
public RefKind RefKind { get; }
8+
9+
public ParameterState(
10+
string name,
11+
string type,
12+
RefKind refKind)
13+
{
14+
Name = name;
15+
Type = type;
16+
RefKind = refKind;
17+
}
18+
19+
public override bool Equals(object? obj)
20+
{
21+
return obj is ParameterState other && Equals(other);
22+
}
23+
24+
public bool Equals(ParameterState? other)
25+
{
26+
if (other is null)
27+
return false;
28+
29+
if (ReferenceEquals(this, other))
30+
return true;
31+
32+
return Name == other.Name
33+
&& Type == other.Type
34+
&& RefKind == other.RefKind;
35+
}
36+
37+
public override int GetHashCode()
38+
{
39+
unchecked
40+
{
41+
var hashCode = Name.GetHashCode();
42+
hashCode = (hashCode * 397) ^ Type.GetHashCode();
43+
hashCode = (hashCode * 397) ^ (int)RefKind;
44+
return hashCode;
45+
}
46+
}
47+
}

src/Thinktecture.Runtime.Extensions.SourceGenerator/Extensions/DelegateMethodStateExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ public static class DelegateMethodStateExtensions
66
{
77
public static bool NeedsCustomDelegate(this DelegateMethodState method)
88
{
9-
return method.DelegateName != null || method.Parameters.Any(p => p.RefKind != RefKind.None);
9+
return method.DelegateName != null
10+
|| method.Parameters.Any(p => p.RefKind != RefKind.None);
1011
}
1112
}

src/Thinktecture.Runtime.Extensions.SourceGenerator/Extensions/MethodSymbolExtensions.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Microsoft.CodeAnalysis.CSharp.Syntax;
2+
using Thinktecture.CodeAnalysis;
23

34
namespace Thinktecture;
45

@@ -25,4 +26,24 @@ public static bool IsArithmeticOperator(this IMethodSymbol method, ITypeSymbol t
2526
&& SymbolEqualityComparer.IncludeNullability.Equals(method.Parameters[0].Type, type)
2627
&& SymbolEqualityComparer.IncludeNullability.Equals(method.Parameters[1].Type, type);
2728
}
29+
30+
public static IReadOnlyList<GenericTypeParameterState> GetGenericTypeParameters(this IMethodSymbol method)
31+
{
32+
if (method.TypeParameters.Length <= 0)
33+
return [];
34+
35+
var genericTypeParameters = new List<GenericTypeParameterState>(method.TypeParameters.Length);
36+
37+
for (var i = 0; i < method.TypeParameters.Length; i++)
38+
{
39+
var typeParam = method.TypeParameters[i];
40+
var constraints = typeParam.GetConstraints();
41+
42+
genericTypeParameters.Add(new GenericTypeParameterState(
43+
typeParam.Name,
44+
constraints));
45+
}
46+
47+
return genericTypeParameters ?? [];
48+
}
2849
}

src/Thinktecture.Runtime.Extensions.SourceGenerator/Extensions/StringBuilderExtensions.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,4 +402,42 @@ public static StringBuilder AppendDelegateType(
402402

403403
return sb.Append(">");
404404
}
405+
406+
public static StringBuilder AppendGenericTypeParameters(
407+
this StringBuilder sb,
408+
IReadOnlyList<GenericTypeParameterState> typeParameters)
409+
{
410+
if (typeParameters.Count <= 0)
411+
return sb;
412+
413+
sb.Append("<");
414+
415+
for (var i = 0; i < typeParameters.Count; i++)
416+
{
417+
if (i > 0)
418+
sb.Append(", ");
419+
420+
sb.Append(typeParameters[i].Name);
421+
}
422+
423+
return sb.Append(">");
424+
}
425+
426+
public static StringBuilder AppendGenericConstraints(
427+
this StringBuilder sb,
428+
IReadOnlyList<string> constraints)
429+
{
430+
if (constraints.Count <= 0)
431+
return sb;
432+
433+
for (var i = 0; i < constraints.Count; i++)
434+
{
435+
if (i > 0)
436+
sb.Append(", ");
437+
438+
sb.Append(constraints[i]);
439+
}
440+
441+
return sb;
442+
}
405443
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
namespace Thinktecture;
2+
3+
public static class TypeParameterExtensions
4+
{
5+
public static IReadOnlyList<string> GetConstraints(this ITypeParameterSymbol typeParam)
6+
{
7+
List<string>? constraints = null;
8+
9+
if (typeParam.HasReferenceTypeConstraint)
10+
{
11+
(constraints ??= []).Add("class");
12+
}
13+
else if (typeParam.HasValueTypeConstraint)
14+
{
15+
(constraints ??= []).Add("struct");
16+
}
17+
18+
foreach (var constraintType in typeParam.ConstraintTypes)
19+
{
20+
(constraints ??= []).Add(constraintType.ToFullyQualifiedDisplayString());
21+
}
22+
23+
if (typeParam.HasConstructorConstraint)
24+
(constraints ??= []).Add("new()");
25+
26+
return constraints ?? [];
27+
}
28+
}

0 commit comments

Comments
 (0)