Skip to content

Commit 9deb003

Browse files
authored
Merge pull request #621 from elachlan:Add-GeneratedCodeAttribute
Add GeneratedCodeAttribute to Generated code
2 parents 10caefc + 93800ce commit 9deb003

File tree

2 files changed

+387
-270
lines changed

2 files changed

+387
-270
lines changed

src/Microsoft.Windows.CsWin32/Generator.cs

Lines changed: 93 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ public class Generator : IDisposable
147147
.WithCloseBracketToken(TokenWithLineFeed(SyntaxKind.CloseBracketToken))
148148
.AddAttributes(Attribute(IdentifierName("DefaultDllImportSearchPaths")).AddArgumentListArguments(AttributeArgument(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(DllImportSearchPath)), IdentifierName(nameof(DllImportSearchPath.System32))))));
149149

150+
private static readonly AttributeSyntax GeneratedCodeAttribute = Attribute(IdentifierName("global::System.CodeDom.Compiler.GeneratedCode"))
151+
.WithArgumentList(FixTrivia(AttributeArgumentList().AddArguments(
152+
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(ThisAssembly.AssemblyName))),
153+
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(ThisAssembly.AssemblyInformationalVersion))))));
154+
150155
private static readonly HashSet<string> ImplicitConversionTypeDefs = new HashSet<string>(StringComparer.Ordinal)
151156
{
152157
"PWSTR",
@@ -465,13 +470,36 @@ private IEnumerable<MemberDeclarationSyntax> NamespaceMembers
465470
{
466471
get
467472
{
468-
IEnumerable<MemberDeclarationSyntax> result =
469-
from entry in this.committedCode.MembersByModule
470-
select ClassDeclaration(Identifier(this.options.ClassName))
471-
.AddModifiers(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.PartialKeyword))
472-
.AddMembers(entry.ToArray())
473-
.WithLeadingTrivia(ParseLeadingTrivia(string.Format(CultureInfo.InvariantCulture, PartialPInvokeContentComment, entry.Key)))
474-
.WithAdditionalAnnotations(new SyntaxAnnotation(SimpleFileNameAnnotation, $"{this.options.ClassName}.{entry.Key}"));
473+
IEnumerable<IGrouping<string, MemberDeclarationSyntax>> members = this.committedCode.MembersByModule;
474+
IEnumerable<MemberDeclarationSyntax> result = Enumerable.Empty<MemberDeclarationSyntax>();
475+
for (int i = 0; i < members.Count(); i++)
476+
{
477+
IGrouping<string, MemberDeclarationSyntax> entry = members.ElementAt(i);
478+
if (i == 0)
479+
{
480+
result = result.Concat(new MemberDeclarationSyntax[]
481+
{
482+
ClassDeclaration(Identifier(this.options.ClassName))
483+
.AddModifiers(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.PartialKeyword))
484+
.AddMembers(entry.ToArray())
485+
.AddAttributeLists(AttributeList().AddAttributes(GeneratedCodeAttribute))
486+
.WithLeadingTrivia(ParseLeadingTrivia(string.Format(CultureInfo.InvariantCulture, PartialPInvokeContentComment, entry.Key)))
487+
.WithAdditionalAnnotations(new SyntaxAnnotation(SimpleFileNameAnnotation, $"{this.options.ClassName}.{entry.Key}")),
488+
});
489+
}
490+
else
491+
{
492+
result = result.Concat(new MemberDeclarationSyntax[]
493+
{
494+
ClassDeclaration(Identifier(this.options.ClassName))
495+
.AddModifiers(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.PartialKeyword))
496+
.AddMembers(entry.ToArray())
497+
.WithLeadingTrivia(ParseLeadingTrivia(string.Format(CultureInfo.InvariantCulture, PartialPInvokeContentComment, entry.Key)))
498+
.WithAdditionalAnnotations(new SyntaxAnnotation(SimpleFileNameAnnotation, $"{this.options.ClassName}.{entry.Key}")),
499+
});
500+
}
501+
}
502+
475503
result = result.Concat(this.committedCode.GeneratedTypes);
476504

477505
ClassDeclarationSyntax inlineArrayIndexerExtensionsClass = this.DeclareInlineArrayIndexerExtensionsClass();
@@ -1673,10 +1701,11 @@ internal void RequestConstant(FieldDefinitionHandle fieldDefHandle)
16731701
.AddModifiers(TokenWithSpace(this.Visibility))
16741702
.WithBaseList(BaseList(SingletonSeparatedList<BaseTypeSyntax>(SimpleBaseType(SafeHandleTypeSyntax))))
16751703
.AddMembers(members.ToArray())
1704+
.AddAttributeLists(AttributeList().AddAttributes(GeneratedCodeAttribute))
16761705
.WithLeadingTrivia(ParseLeadingTrivia($@"
1677-
/// <summary>
1678-
/// Represents a Win32 handle that can be closed with <see cref=""{this.options.ClassName}.{renamedReleaseMethod ?? releaseMethod}""/>.
1679-
/// </summary>
1706+
/// <summary>
1707+
/// Represents a Win32 handle that can be closed with <see cref=""{this.options.ClassName}.{renamedReleaseMethod ?? releaseMethod}""/>.
1708+
/// </summary>
16801709
"));
16811710

16821711
this.volatileCode.AddSafeHandleType(safeHandleDeclaration);
@@ -2070,33 +2099,32 @@ private static string GetClassNameForModule(string moduleName) =>
20702099
private static AttributeSyntax StructLayout(TypeAttributes typeAttributes, TypeLayout layout = default, CharSet charSet = CharSet.Ansi)
20712100
{
20722101
LayoutKind layoutKind = (typeAttributes & TypeAttributes.ExplicitLayout) == TypeAttributes.ExplicitLayout ? LayoutKind.Explicit : LayoutKind.Sequential;
2073-
AttributeSyntax? structLayoutAttribute = Attribute(IdentifierName("StructLayout")).AddArgumentListArguments(
2074-
AttributeArgument(MemberAccessExpression(
2075-
SyntaxKind.SimpleMemberAccessExpression,
2076-
IdentifierName(nameof(LayoutKind)),
2077-
IdentifierName(Enum.GetName(typeof(LayoutKind), layoutKind)!))));
2102+
List<AttributeArgumentSyntax> args = new();
2103+
AttributeSyntax? structLayoutAttribute = Attribute(IdentifierName("StructLayout"));
2104+
args.Add(AttributeArgument(MemberAccessExpression(
2105+
SyntaxKind.SimpleMemberAccessExpression,
2106+
IdentifierName(nameof(LayoutKind)),
2107+
IdentifierName(Enum.GetName(typeof(LayoutKind), layoutKind)!))));
20782108

20792109
if (layout.PackingSize > 0)
20802110
{
2081-
structLayoutAttribute = structLayoutAttribute.AddArgumentListArguments(
2082-
AttributeArgument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(layout.PackingSize)))
2111+
args.Add(AttributeArgument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(layout.PackingSize)))
20832112
.WithNameEquals(NameEquals(nameof(StructLayoutAttribute.Pack))));
20842113
}
20852114

20862115
if (layout.Size > 0)
20872116
{
2088-
structLayoutAttribute = structLayoutAttribute.AddArgumentListArguments(
2089-
AttributeArgument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(layout.Size)))
2117+
args.Add(AttributeArgument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(layout.Size)))
20902118
.WithNameEquals(NameEquals(nameof(StructLayoutAttribute.Size))));
20912119
}
20922120

20932121
if (charSet != CharSet.Ansi)
20942122
{
2095-
structLayoutAttribute = structLayoutAttribute.AddArgumentListArguments(
2096-
AttributeArgument(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(CharSet)), IdentifierName(Enum.GetName(typeof(CharSet), charSet)!)))
2123+
args.Add(AttributeArgument(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(CharSet)), IdentifierName(Enum.GetName(typeof(CharSet), charSet)!)))
20972124
.WithNameEquals(NameEquals(IdentifierName(nameof(StructLayoutAttribute.CharSet)))));
20982125
}
20992126

2127+
structLayoutAttribute = structLayoutAttribute.WithArgumentList(FixTrivia(AttributeArgumentList().AddArguments(args.ToArray())));
21002128
return structLayoutAttribute;
21012129
}
21022130

@@ -2117,25 +2145,24 @@ private static AttributeSyntax InterfaceType(ComInterfaceType interfaceType)
21172145

21182146
private static AttributeSyntax DllImport(MethodImport import, string moduleName, string? entrypoint)
21192147
{
2120-
AttributeSyntax? dllImportAttribute = Attribute(IdentifierName("DllImport"))
2121-
.WithArgumentList(FixTrivia(AttributeArgumentList().AddArguments(
2122-
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(moduleName))),
2123-
AttributeArgument(LiteralExpression(SyntaxKind.TrueLiteralExpression)).WithNameEquals(NameEquals(nameof(DllImportAttribute.ExactSpelling))))));
2148+
List<AttributeArgumentSyntax> args = new();
2149+
AttributeSyntax? dllImportAttribute = Attribute(IdentifierName("DllImport"));
2150+
args.Add(AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(moduleName))));
2151+
args.Add(AttributeArgument(LiteralExpression(SyntaxKind.TrueLiteralExpression)).WithNameEquals(NameEquals(nameof(DllImportAttribute.ExactSpelling))));
21242152

2125-
if (entrypoint is object)
2153+
if (entrypoint is not null)
21262154
{
2127-
dllImportAttribute = dllImportAttribute.AddArgumentListArguments(
2128-
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(entrypoint)))
2155+
args.Add(AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(entrypoint)))
21292156
.WithNameEquals(NameEquals(nameof(DllImportAttribute.EntryPoint))));
21302157
}
21312158

21322159
if ((import.Attributes & MethodImportAttributes.SetLastError) == MethodImportAttributes.SetLastError)
21332160
{
2134-
dllImportAttribute = dllImportAttribute.AddArgumentListArguments(
2135-
AttributeArgument(LiteralExpression(SyntaxKind.TrueLiteralExpression))
2161+
args.Add(AttributeArgument(LiteralExpression(SyntaxKind.TrueLiteralExpression))
21362162
.WithNameEquals(NameEquals(nameof(DllImportAttribute.SetLastError))));
21372163
}
21382164

2165+
dllImportAttribute = dllImportAttribute.WithArgumentList(FixTrivia(AttributeArgumentList().AddArguments(args.ToArray())));
21392166
return dllImportAttribute;
21402167
}
21412168

@@ -2861,6 +2888,15 @@ private bool HasObsoleteAttribute(CustomAttributeHandleCollection attributes)
28612888
return null;
28622889
}
28632890

2891+
// add generated code attribute.
2892+
if (typeDeclaration is not null)
2893+
{
2894+
typeDeclaration = typeDeclaration
2895+
.WithLeadingTrivia()
2896+
.AddAttributeLists(AttributeList().AddAttributes(GeneratedCodeAttribute))
2897+
.WithLeadingTrivia(typeDeclaration.GetLeadingTrivia());
2898+
}
2899+
28642900
return typeDeclaration;
28652901
}
28662902
catch (Exception ex)
@@ -3142,14 +3178,16 @@ private ClassDeclarationSyntax DeclareInlineArrayIndexerExtensionsClass()
31423178
{
31433179
return ClassDeclaration(InlineArrayIndexerExtensionsClassName.Identifier)
31443180
.AddMembers(this.committedCode.InlineArrayIndexerExtensions.ToArray())
3145-
.WithModifiers(TokenList(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.PartialKeyword)));
3181+
.WithModifiers(TokenList(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.PartialKeyword)))
3182+
.AddAttributeLists(AttributeList().AddAttributes(GeneratedCodeAttribute));
31463183
}
31473184

31483185
private ClassDeclarationSyntax DeclareComInterfaceFriendlyExtensionsClass()
31493186
{
31503187
return ClassDeclaration(ComInterfaceFriendlyExtensionsClassName.Identifier)
31513188
.AddMembers(this.committedCode.ComInterfaceExtensions.ToArray())
3152-
.WithModifiers(TokenList(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.PartialKeyword)));
3189+
.WithModifiers(TokenList(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.PartialKeyword)))
3190+
.AddAttributeLists(AttributeList().AddAttributes(GeneratedCodeAttribute));
31533191
}
31543192

31553193
/// <summary>
@@ -6151,6 +6189,21 @@ internal WhitespaceRewriter()
61516189
return result;
61526190
}
61536191

6192+
public override SyntaxNode? VisitInterfaceDeclaration(InterfaceDeclarationSyntax node)
6193+
{
6194+
node = this.WithIndentingTrivia(node)
6195+
.WithOpenBraceToken(node.OpenBraceToken.WithLeadingTrivia(TriviaList(this.IndentTrivia)))
6196+
.WithCloseBraceToken(node.CloseBraceToken.WithLeadingTrivia(TriviaList(this.IndentTrivia)));
6197+
using var indent = new Indent(this);
6198+
SyntaxNode? result = base.VisitInterfaceDeclaration(node);
6199+
if (result is InterfaceDeclarationSyntax c)
6200+
{
6201+
result = c.WithMembers(AddSpacingBetweenMembers(c.Members));
6202+
}
6203+
6204+
return result;
6205+
}
6206+
61546207
public override SyntaxNode? VisitEnumDeclaration(EnumDeclarationSyntax node)
61556208
{
61566209
node = this.WithIndentingTrivia(node)
@@ -6200,15 +6253,15 @@ internal WhitespaceRewriter()
62006253
{
62016254
if (node.Parent is ParameterSyntax)
62026255
{
6203-
return base.VisitAttributeList(node.WithCloseBracketToken(TokenWithSpace(SyntaxKind.CloseBracketToken)));
6256+
return node.WithCloseBracketToken(TokenWithSpace(SyntaxKind.CloseBracketToken));
62046257
}
62056258
else if (node.Parent is BaseTypeDeclarationSyntax)
62066259
{
6207-
return base.VisitAttributeList(this.WithOuterIndentingTrivia(node));
6260+
return this.WithOuterIndentingTrivia(node);
62086261
}
62096262
else
62106263
{
6211-
return base.VisitAttributeList(this.WithIndentingTrivia(node));
6264+
return this.WithIndentingTrivia(node);
62126265
}
62136266
}
62146267

@@ -6331,7 +6384,7 @@ public override SyntaxTriviaList VisitList(SyntaxTriviaList list)
63316384
{
63326385
if (list[i].GetStructure() is DocumentationCommentTriviaSyntax trivia)
63336386
{
6334-
indent ??= list[i].Token.Parent is BaseTypeDeclarationSyntax ? this.OuterIndentTrivia.ToString() : this.IndentTrivia.ToString();
6387+
indent ??= list[i].Token.Parent is BaseTypeDeclarationSyntax or AttributeListSyntax { Parent: BaseTypeDeclarationSyntax } ? this.OuterIndentTrivia.ToString() : this.IndentTrivia.ToString();
63356388
var comment = new StringBuilder(trivia.Content.ToFullString());
63366389
comment.Insert(0, indent);
63376390
comment.Replace("\n", "\n" + indent);
@@ -6368,7 +6421,7 @@ IndexerDeclarationSyntax or
63686421
return members;
63696422
}
63706423

6371-
private static TSyntax WithIndentingTrivia<TSyntax>(TSyntax node, SyntaxTrivia indentTrivia)
6424+
private TSyntax WithIndentingTrivia<TSyntax>(TSyntax node, SyntaxTrivia indentTrivia)
63726425
where TSyntax : SyntaxNode
63736426
{
63746427
if (node is MemberDeclarationSyntax memberDeclaration)
@@ -6378,7 +6431,7 @@ private static TSyntax WithIndentingTrivia<TSyntax>(TSyntax node, SyntaxTrivia i
63786431
}
63796432

63806433
// Take care to preserve xml doc comments, pragmas, etc.
6381-
return node.WithLeadingTrivia(node.HasLeadingTrivia ? node.GetLeadingTrivia().Add(indentTrivia) : TriviaList(indentTrivia));
6434+
return node.WithLeadingTrivia(node.HasLeadingTrivia ? this.VisitList(node.GetLeadingTrivia()).Add(indentTrivia) : TriviaList(indentTrivia));
63826435

63836436
static SyntaxToken GetFirstToken(MemberDeclarationSyntax memberDeclaration)
63846437
{
@@ -6400,13 +6453,13 @@ static SyntaxToken GetFirstToken(MemberDeclarationSyntax memberDeclaration)
64006453
private TSyntax WithIndentingTrivia<TSyntax>(TSyntax node)
64016454
where TSyntax : SyntaxNode
64026455
{
6403-
return WithIndentingTrivia(node, this.IndentTrivia);
6456+
return this.WithIndentingTrivia(node, this.IndentTrivia);
64046457
}
64056458

64066459
private TSyntax WithOuterIndentingTrivia<TSyntax>(TSyntax node)
64076460
where TSyntax : SyntaxNode
64086461
{
6409-
return WithIndentingTrivia(node, this.OuterIndentTrivia);
6462+
return this.WithIndentingTrivia(node, this.OuterIndentTrivia);
64106463
}
64116464

64126465
private struct Indent : IDisposable

0 commit comments

Comments
 (0)