@@ -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