Skip to content

Commit

Permalink
Emit a GeneratedCodeAttibute on our generated stubs for better auditi…
Browse files Browse the repository at this point in the history
…ng purposes. Fixes dotnet#64562
  • Loading branch information
jkoritzinsky committed Feb 24, 2022
1 parent a41c7b3 commit 6098216
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public static bool AreCompilationSettingsEqual(StubEnvironment env1, StubEnviron

internal sealed class DllImportStubContext : IEquatable<DllImportStubContext>
{
private static readonly string GeneratorVersion = typeof(DllImportGenerator).Assembly.GetName().Version.ToString();

// We don't need the warnings around not setting the various
// non-nullable fields/properties on this type in the constructor
// since we always use a property initializer.
Expand Down Expand Up @@ -124,17 +126,27 @@ public static DllImportStubContext Create(
ImmutableArray<AttributeListSyntax>.Builder additionalAttrs = ImmutableArray.CreateBuilder<AttributeListSyntax>();

// Define additional attributes for the stub definition.
additionalAttrs.Add(
AttributeList(
SingletonSeparatedList(
Attribute(ParseName(TypeNames.System_CodeDom_Compiler_GeneratedCodeAttribute),
AttributeArgumentList(
SeparatedList(
new[]
{
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal("Microsoft.Interop.DllImportGenerator"))),
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(GeneratorVersion)))
}))))));

if (env.TargetFrameworkVersion >= new Version(5, 0) && !MethodIsSkipLocalsInit(env, method))
{
additionalAttrs.Add(
AttributeList(
SeparatedList(new[]
{
SingletonSeparatedList(
// Adding the skip locals init indiscriminately since the source generator is
// targeted at non-blittable method signatures which typically will contain locals
// in the generated code.
Attribute(ParseName(TypeNames.System_Runtime_CompilerServices_SkipLocalsInitAttribute))
})));
Attribute(ParseName(TypeNames.System_Runtime_CompilerServices_SkipLocalsInitAttribute)))));
}

return new DllImportStubContext()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,7 @@ public static string MarshalEx(InteropGenerationOptions options)
public const string DefaultDllImportSearchPathsAttribute = "System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute";

public const string DllImportSearchPath = "System.Runtime.InteropServices.DllImportSearchPath";

public const string System_CodeDom_Compiler_GeneratedCodeAttribute = "System.CodeDom.Compiler.GeneratedCodeAttribute";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,57 @@ partial class C
Assert.DoesNotContain(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == typeof(SkipLocalsInitAttribute).FullName);
}

[ConditionalFact]
public async Task GeneratedCodeAdded()
{
string source = @"
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly:DisableRuntimeMarshalling]
partial class C
{
[GeneratedDllImportAttribute(""DoesNotExist"")]
public static partial S Method();
}
[NativeMarshalling(typeof(Native))]
struct S
{
}
struct Native
{
public Native(S s) { }
public S ToManaged() { return default; }
}";
Compilation comp = await TestUtils.CreateCompilation(source);

Compilation newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.DllImportGenerator());

ITypeSymbol c = newComp.GetTypeByMetadataName("C")!;
IMethodSymbol stubMethod = c.GetMembers().OfType<IMethodSymbol>().Single(m => m.Name == "Method");
Assert.Contains(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == typeof(System.CodeDom.Compiler.GeneratedCodeAttribute).FullName);
}

[ConditionalFact]
public async Task GeneratedCodeNotAddedOnForwardingStub()
{
string source = @"
using System.Runtime.InteropServices;
partial class C
{
[GeneratedDllImportAttribute(""DoesNotExist"")]
public static partial void Method();
}";
Compilation comp = await TestUtils.CreateCompilation(source);

Compilation newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.DllImportGenerator());

ITypeSymbol c = newComp.GetTypeByMetadataName("C")!;
IMethodSymbol stubMethod = c.GetMembers().OfType<IMethodSymbol>().Single(m => m.Name == "Method");
Assert.DoesNotContain(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == typeof(System.CodeDom.Compiler.GeneratedCodeAttribute).FullName);
}

public static IEnumerable<object[]> GetDownlevelTargetFrameworks()
{
yield return new object[] { TestTargetFramework.Net, true };
Expand Down

0 comments on commit 6098216

Please sign in to comment.