1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Godot.SourceGenerators.Internal;
internal static class ExtensionMethods
{
public static AttributeData? GetGenerateUnmanagedCallbacksAttribute(this INamedTypeSymbol symbol)
=> symbol.GetAttributes()
.FirstOrDefault(a => a.AttributeClass?.IsGenerateUnmanagedCallbacksAttribute() ?? false);
private static bool HasGenerateUnmanagedCallbacksAttribute(
this ClassDeclarationSyntax cds, Compilation compilation,
out INamedTypeSymbol? symbol
)
{
var sm = compilation.GetSemanticModel(cds.SyntaxTree);
var classTypeSymbol = sm.GetDeclaredSymbol(cds);
if (classTypeSymbol == null)
{
symbol = null;
return false;
}
if (!classTypeSymbol.GetAttributes()
.Any(a => a.AttributeClass?.IsGenerateUnmanagedCallbacksAttribute() ?? false))
{
symbol = null;
return false;
}
symbol = classTypeSymbol;
return true;
}
private static bool IsGenerateUnmanagedCallbacksAttribute(this INamedTypeSymbol symbol)
=> symbol.ToString() == GeneratorClasses.GenerateUnmanagedCallbacksAttr;
public static IEnumerable<(ClassDeclarationSyntax cds, INamedTypeSymbol symbol)> SelectUnmanagedCallbacksClasses(
this IEnumerable<ClassDeclarationSyntax> source,
Compilation compilation
)
{
foreach (var cds in source)
{
if (cds.HasGenerateUnmanagedCallbacksAttribute(compilation, out var symbol))
yield return (cds, symbol!);
}
}
public static bool IsNested(this TypeDeclarationSyntax cds)
=> cds.Parent is TypeDeclarationSyntax;
public static bool IsPartial(this TypeDeclarationSyntax cds)
=> cds.Modifiers.Any(SyntaxKind.PartialKeyword);
public static bool AreAllOuterTypesPartial(
this TypeDeclarationSyntax cds,
out TypeDeclarationSyntax? typeMissingPartial
)
{
SyntaxNode? outerSyntaxNode = cds.Parent;
while (outerSyntaxNode is TypeDeclarationSyntax outerTypeDeclSyntax)
{
if (!outerTypeDeclSyntax.IsPartial())
{
typeMissingPartial = outerTypeDeclSyntax;
return false;
}
outerSyntaxNode = outerSyntaxNode.Parent;
}
typeMissingPartial = null;
return true;
}
public static string GetDeclarationKeyword(this INamedTypeSymbol namedTypeSymbol)
{
string? keyword = namedTypeSymbol.DeclaringSyntaxReferences
.OfType<TypeDeclarationSyntax>().FirstOrDefault()?
.Keyword.Text;
return keyword ?? namedTypeSymbol.TypeKind switch
{
TypeKind.Interface => "interface",
TypeKind.Struct => "struct",
_ => "class"
};
}
public static string NameWithTypeParameters(this INamedTypeSymbol symbol)
{
return symbol.IsGenericType ?
string.Concat(symbol.Name, "<", string.Join(", ", symbol.TypeParameters), ">") :
symbol.Name;
}
private static SymbolDisplayFormat FullyQualifiedFormatOmitGlobal { get; } =
SymbolDisplayFormat.FullyQualifiedFormat
.WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted);
private static SymbolDisplayFormat FullyQualifiedFormatIncludeGlobal { get; } =
SymbolDisplayFormat.FullyQualifiedFormat
.WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Included);
public static string FullQualifiedNameOmitGlobal(this ITypeSymbol symbol)
=> symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatOmitGlobal);
public static string FullQualifiedNameOmitGlobal(this INamespaceSymbol namespaceSymbol)
=> namespaceSymbol.ToDisplayString(FullyQualifiedFormatOmitGlobal);
public static string FullQualifiedNameIncludeGlobal(this ITypeSymbol symbol)
=> symbol.ToDisplayString(NullableFlowState.NotNull, FullyQualifiedFormatIncludeGlobal);
public static string FullQualifiedNameIncludeGlobal(this INamespaceSymbol namespaceSymbol)
=> namespaceSymbol.ToDisplayString(FullyQualifiedFormatIncludeGlobal);
public static string SanitizeQualifiedNameForUniqueHint(this string qualifiedName)
=> qualifiedName
// AddSource() doesn't support angle brackets
.Replace("<", "(Of ")
.Replace(">", ")");
}
|