9 public void Initialize(IncrementalGeneratorInitializationContext context)
11 context.RegisterPostInitializationOutput(
static context =>
13 context.AddSource(
"ExportAttribute.cs",
19 [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=false)]
20 internal sealed class ExportAttribute : Attribute {}
22 public static class Internal {
23 public delegate void FreeDelegate(IntPtr ptr);
25 public static void Free(IntPtr ptr) {
26 System.Runtime.InteropServices.GCHandle.FromIntPtr(ptr).Free();
33 var source = context.SyntaxProvider.ForAttributeWithMetadataName(
34 "MLLIF.ExportAttribute",
35 static (_, _) =>
true,
36 static (context, _) => context);
38 context.RegisterSourceOutput(source, Emit);
41 private static string ToNativeType(ITypeSymbol type)
43 if (type.IsReferenceType)
44 return "System.IntPtr";
46 return type.ToDisplayString();
49 private static Diagnostic CannotMangle(IMethodSymbol method)
52 $
"'{method.ToDisplayString()}' cannot be mangled",
53 DiagnosticSeverity.Error, DiagnosticSeverity.Error,
56 private void Emit(SourceProductionContext spc, GeneratorAttributeSyntaxContext gasc)
58 var symbol = (IMethodSymbol)gasc.TargetSymbol;
60 if (symbol.MangleName(spc) is not { } mangling)
62 spc.ReportDiagnostic(CannotMangle(symbol));
66 var builder =
new StringBuilder();
68 builder.Append(
"\tpublic delegate ");
69 builder.Append(ToNativeType(symbol.ReturnType));
70 builder.Append(
" __delegate");
71 builder.Append(mangling);
76 builder.Append(
"System.IntPtr self");
77 if (symbol.Parameters.Length > 0)
81 for (var i = 0; i < symbol.Parameters.Length; i++)
86 var param = symbol.Parameters[i];
88 .Append(ToNativeType(param.Type))
93 builder.Append(
");\n");
96 builder.Append(
"\tpublic static ");
97 builder.Append(ToNativeType(symbol.ReturnType));
99 builder.Append(mangling);
102 if (!symbol.IsStatic)
104 builder.Append(
"System.IntPtr self");
105 if (symbol.Parameters.Length > 0)
106 builder.Append(
", ");
109 for (var i = 0; i < symbol.Parameters.Length; i++)
112 builder.Append(
", ");
114 var param = symbol.Parameters[i];
116 .Append(ToNativeType(param.Type))
121 builder.Append(
") {\n");
123 if (!symbol.IsStatic)
124 builder.Append(
"\t\tvar handle = System.Runtime.InteropServices.GCHandle.FromIntPtr(self);\n");
126 builder.Append(
"\t\treturn ");
128 if (symbol.ReturnType.IsReferenceType)
130 builder.Append(
"System.Runtime.InteropServices.GCHandle.ToIntPtr(");
131 builder.Append(
"System.Runtime.InteropServices.GCHandle.Alloc(");
134 if (!symbol.IsStatic)
135 builder.Append(
"(handle.Target as ").Append(symbol.ContainingType.ToDisplayString()).Append(
").");
137 builder.Append(symbol.Name).Append(
'(');
139 for (var i = 0; i < symbol.Parameters.Length; i++)
142 builder.Append(
", ");
144 var param = symbol.Parameters[i];
146 if (param.Type.IsReferenceType)
147 builder.Append(
"System.Runtime.InteropServices.GCHandle.FromIntPtr(");
148 builder.Append(param.Name);
149 if (param.Type.IsReferenceType)
150 builder.Append(
").Target as ").Append(param.Type.ToDisplayString());
153 if (symbol.ReturnType.IsReferenceType)
154 builder.Append(
"))");
156 builder.Append(
");\n");
158 builder.Append(
"\t}\n");
160 spc.AddSource($
"{symbol.ContainingType.Name}.{symbol.Name}.g.cs",
162 namespace {{symbol.ContainingType.ContainingNamespace.ToDisplayString()}};
164 public partial class {{symbol.ContainingType.Name}} {