Skip to content

Commit

Permalink
Merge pull request #552 from fredrikhr/attribute-annotate
Browse files Browse the repository at this point in the history
Add support for C/C++ attribute annotate
  • Loading branch information
tannergooding authored May 28, 2024
2 parents 549da90 + c62fb62 commit f0501f7
Showing 1 changed file with 98 additions and 0 deletions.
98 changes: 98 additions & 0 deletions sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ public void Close()
GenerateNativeBitfieldAttribute(this, stream, leaveStreamOpen);
GenerateNativeInheritanceAttribute(this, stream, leaveStreamOpen);
GenerateNativeTypeNameAttribute(this, stream, leaveStreamOpen);
GenerateNativeAnnotationAttribute(this, stream, leaveStreamOpen);
GenerateSetsLastSystemErrorAttribute(this, stream, leaveStreamOpen);
GenerateVtblIndexAttribute(this, stream, leaveStreamOpen);
GenerateTransparentStructs(this, stream, leaveStreamOpen);
Expand Down Expand Up @@ -795,6 +796,96 @@ static void GenerateNativeTypeNameAttribute(PInvokeGenerator generator, Stream?
}
}

static void GenerateNativeAnnotationAttribute(PInvokeGenerator generator, Stream? stream, bool leaveStreamOpen)
{
const string AttributeName = "NativeAnnotationAttribute";
var config = generator.Config;

var ns = generator.GetNamespace(AttributeName);
if (config.ExcludedNames.Contains(AttributeName) || config.ExcludedNames.Contains($"{ns}.{AttributeName}"))
{
return;
}

if (stream is null)
{
var outputPath = Path.Combine(config.OutputLocation, $"{AttributeName}.cs");
stream = generator._outputStreamFactory(outputPath);
}

using var sw = new StreamWriter(stream, s_defaultStreamWriterEncoding, DefaultStreamWriterBufferSize, leaveStreamOpen);
sw.NewLine = "\n";

if (!string.IsNullOrEmpty(config.HeaderText))
{
sw.WriteLine(config.HeaderText);
}

var indentString = " ";

sw.WriteLine("using System;");
sw.WriteLine("using System.Diagnostics;");
sw.WriteLine();

sw.Write("namespace ");
sw.Write(ns);

if (generator.Config.GenerateFileScopedNamespaces)
{
sw.WriteLine(';');
sw.WriteLine();
indentString = "";
}
else
{
sw.WriteLine();
sw.WriteLine('{');
}

sw.Write(indentString);
sw.WriteLine("/// <summary>Defines the annotation found in a native declaration.</summary>");
sw.Write(indentString);
sw.WriteLine("[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]");
sw.Write(indentString);
sw.WriteLine("[Conditional(\"DEBUG\")]");
sw.Write(indentString);
sw.WriteLine($"internal sealed partial class {AttributeName} : Attribute");
sw.Write(indentString);
sw.WriteLine('{');
sw.Write(indentString);
sw.WriteLine(" private readonly string _annotation;");
sw.WriteLine();
sw.Write(indentString);
sw.WriteLine($" /// <summary>Initializes a new instance of the <see cref=\"{AttributeName}\" /> class.</summary>");
sw.Write(indentString);
sw.WriteLine(" /// <param name=\"annotation\">The annotation that was used in the native declaration.</param>");
sw.Write(indentString);
sw.WriteLine($" public {AttributeName}(string annotation)");
sw.Write(indentString);
sw.WriteLine(" {");
sw.Write(indentString);
sw.WriteLine(" _annotation = annotation;");
sw.Write(indentString);
sw.WriteLine(" }");
sw.WriteLine();
sw.Write(indentString);
sw.WriteLine(" /// <summary>Gets the annotation that was used in the native declaration.</summary>");
sw.Write(indentString);
sw.WriteLine(" public string Annotation => _annotation;");
sw.Write(indentString);
sw.WriteLine('}');

if (!generator.Config.GenerateFileScopedNamespaces)
{
sw.WriteLine('}');
}

if (!leaveStreamOpen)
{
stream = null;
}
}

static void GenerateSetsLastSystemErrorAttribute(PInvokeGenerator generator, Stream? stream, bool leaveStreamOpen)
{
var config = generator.Config;
Expand Down Expand Up @@ -6724,6 +6815,13 @@ private void WithAttributes(NamedDecl namedDecl, bool onlySupportedOSPlatform =
break;
}

case CX_AttrKind_Annotate:
{
var annotationText = attr.Spelling;
outputBuilder.WriteCustomAttribute($"""NativeAnnotation("{annotationText}")""");
break;
}

case CX_AttrKind_Format:
case CX_AttrKind_FormatArg:
case CX_AttrKind_MSNoVTable:
Expand Down

0 comments on commit f0501f7

Please sign in to comment.