Skip to content

Commit f0501f7

Browse files
Merge pull request #552 from fredrikhr/attribute-annotate
Add support for C/C++ attribute annotate
2 parents 549da90 + c62fb62 commit f0501f7

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ public void Close()
435435
GenerateNativeBitfieldAttribute(this, stream, leaveStreamOpen);
436436
GenerateNativeInheritanceAttribute(this, stream, leaveStreamOpen);
437437
GenerateNativeTypeNameAttribute(this, stream, leaveStreamOpen);
438+
GenerateNativeAnnotationAttribute(this, stream, leaveStreamOpen);
438439
GenerateSetsLastSystemErrorAttribute(this, stream, leaveStreamOpen);
439440
GenerateVtblIndexAttribute(this, stream, leaveStreamOpen);
440441
GenerateTransparentStructs(this, stream, leaveStreamOpen);
@@ -795,6 +796,96 @@ static void GenerateNativeTypeNameAttribute(PInvokeGenerator generator, Stream?
795796
}
796797
}
797798

799+
static void GenerateNativeAnnotationAttribute(PInvokeGenerator generator, Stream? stream, bool leaveStreamOpen)
800+
{
801+
const string AttributeName = "NativeAnnotationAttribute";
802+
var config = generator.Config;
803+
804+
var ns = generator.GetNamespace(AttributeName);
805+
if (config.ExcludedNames.Contains(AttributeName) || config.ExcludedNames.Contains($"{ns}.{AttributeName}"))
806+
{
807+
return;
808+
}
809+
810+
if (stream is null)
811+
{
812+
var outputPath = Path.Combine(config.OutputLocation, $"{AttributeName}.cs");
813+
stream = generator._outputStreamFactory(outputPath);
814+
}
815+
816+
using var sw = new StreamWriter(stream, s_defaultStreamWriterEncoding, DefaultStreamWriterBufferSize, leaveStreamOpen);
817+
sw.NewLine = "\n";
818+
819+
if (!string.IsNullOrEmpty(config.HeaderText))
820+
{
821+
sw.WriteLine(config.HeaderText);
822+
}
823+
824+
var indentString = " ";
825+
826+
sw.WriteLine("using System;");
827+
sw.WriteLine("using System.Diagnostics;");
828+
sw.WriteLine();
829+
830+
sw.Write("namespace ");
831+
sw.Write(ns);
832+
833+
if (generator.Config.GenerateFileScopedNamespaces)
834+
{
835+
sw.WriteLine(';');
836+
sw.WriteLine();
837+
indentString = "";
838+
}
839+
else
840+
{
841+
sw.WriteLine();
842+
sw.WriteLine('{');
843+
}
844+
845+
sw.Write(indentString);
846+
sw.WriteLine("/// <summary>Defines the annotation found in a native declaration.</summary>");
847+
sw.Write(indentString);
848+
sw.WriteLine("[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]");
849+
sw.Write(indentString);
850+
sw.WriteLine("[Conditional(\"DEBUG\")]");
851+
sw.Write(indentString);
852+
sw.WriteLine($"internal sealed partial class {AttributeName} : Attribute");
853+
sw.Write(indentString);
854+
sw.WriteLine('{');
855+
sw.Write(indentString);
856+
sw.WriteLine(" private readonly string _annotation;");
857+
sw.WriteLine();
858+
sw.Write(indentString);
859+
sw.WriteLine($" /// <summary>Initializes a new instance of the <see cref=\"{AttributeName}\" /> class.</summary>");
860+
sw.Write(indentString);
861+
sw.WriteLine(" /// <param name=\"annotation\">The annotation that was used in the native declaration.</param>");
862+
sw.Write(indentString);
863+
sw.WriteLine($" public {AttributeName}(string annotation)");
864+
sw.Write(indentString);
865+
sw.WriteLine(" {");
866+
sw.Write(indentString);
867+
sw.WriteLine(" _annotation = annotation;");
868+
sw.Write(indentString);
869+
sw.WriteLine(" }");
870+
sw.WriteLine();
871+
sw.Write(indentString);
872+
sw.WriteLine(" /// <summary>Gets the annotation that was used in the native declaration.</summary>");
873+
sw.Write(indentString);
874+
sw.WriteLine(" public string Annotation => _annotation;");
875+
sw.Write(indentString);
876+
sw.WriteLine('}');
877+
878+
if (!generator.Config.GenerateFileScopedNamespaces)
879+
{
880+
sw.WriteLine('}');
881+
}
882+
883+
if (!leaveStreamOpen)
884+
{
885+
stream = null;
886+
}
887+
}
888+
798889
static void GenerateSetsLastSystemErrorAttribute(PInvokeGenerator generator, Stream? stream, bool leaveStreamOpen)
799890
{
800891
var config = generator.Config;
@@ -6724,6 +6815,13 @@ private void WithAttributes(NamedDecl namedDecl, bool onlySupportedOSPlatform =
67246815
break;
67256816
}
67266817

6818+
case CX_AttrKind_Annotate:
6819+
{
6820+
var annotationText = attr.Spelling;
6821+
outputBuilder.WriteCustomAttribute($"""NativeAnnotation("{annotationText}")""");
6822+
break;
6823+
}
6824+
67276825
case CX_AttrKind_Format:
67286826
case CX_AttrKind_FormatArg:
67296827
case CX_AttrKind_MSNoVTable:

0 commit comments

Comments
 (0)