Пример #1
0
        public async Task SkipLocalsInitOnDownlevelTargetFrameworks(TestTargetFramework targetFramework, bool expectSkipLocalsInit)
        {
            string      source = $@"
using System.Runtime.InteropServices;
{CodeSnippets.LibraryImportAttributeDeclaration}
partial class C
{{
    [LibraryImportAttribute(""DoesNotExist"")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static partial bool Method();
}}";
            Compilation comp   = await TestUtils.CreateCompilation(source, targetFramework);

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

            ITypeSymbol   c          = newComp.GetTypeByMetadataName("C") !;
            IMethodSymbol stubMethod = c.GetMembers().OfType <IMethodSymbol>().Single(m => m.Name == "Method");

            if (expectSkipLocalsInit)
            {
                Assert.Contains(stubMethod.GetAttributes(), attr => attr.AttributeClass !.ToDisplayString() == typeof(SkipLocalsInitAttribute).FullName);
            }
            else
            {
                Assert.DoesNotContain(stubMethod.GetAttributes(), attr => attr.AttributeClass !.ToDisplayString() == typeof(SkipLocalsInitAttribute).FullName);
            }
        }
Пример #2
0
        public async Task ValidateSnippetsFallbackForwarder(string source, TestTargetFramework targetFramework, bool expectFallbackForwarder)
        {
            Compilation comp = await TestUtils.CreateCompilation(source, targetFramework);

            TestUtils.AssertPreSourceGeneratorCompilation(comp);

            var newComp = TestUtils.RunGenerators(
                comp,
                out var generatorDiags,
                new Microsoft.Interop.LibraryImportGenerator());

            Assert.Empty(generatorDiags);

            TestUtils.AssertPostSourceGeneratorCompilation(newComp);

            // Verify that the forwarder generates the method as a DllImport.
            SyntaxTree    generatedCode = newComp.SyntaxTrees.Last();
            SemanticModel model         = newComp.GetSemanticModel(generatedCode);
            var           methods       = generatedCode.GetRoot()
                                          .DescendantNodes().OfType <MethodDeclarationSyntax>()
                                          .ToList();
            MethodDeclarationSyntax generatedMethod = Assert.Single(methods);

            IMethodSymbol method = model.GetDeclaredSymbol(generatedMethod) !;

            // If we expect fallback forwarder, then the DllImportData will not be null.
            Assert.Equal(expectFallbackForwarder, method.GetDllImportData() is not null);
        }
Пример #3
0
 /// <summary>
 /// Create a compilation given sources
 /// </summary>
 /// <param name="sources">Sources to compile</param>
 /// <param name="targetFramework">Target framework of the compilation</param>
 /// <param name="outputKind">Output type</param>
 /// <returns>The resulting compilation</returns>
 public static Task <Compilation> CreateCompilation(string[] sources, TestTargetFramework targetFramework = TestTargetFramework.Net, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, IEnumerable <string>?preprocessorSymbols = null)
 {
     return(CreateCompilation(
                sources.Select(source =>
                               CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview, preprocessorSymbols: preprocessorSymbols))).ToArray(),
                targetFramework,
                outputKind));
 }
Пример #4
0
        public async Task SkipLocalsInitOnDownlevelTargetFrameworks(TestTargetFramework targetFramework, bool expectSkipLocalsInit)
        {
            string      source = $@"
using System.Runtime.InteropServices;
{CodeSnippets.GeneratedDllImportAttributeDeclaration}
namespace System.Runtime.InteropServices
{{
    sealed class NativeMarshallingAttribute : System.Attribute
    {{
        public NativeMarshallingAttribute(System.Type nativeType) {{ }}
    }}
}}
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, targetFramework);

            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");

            if (expectSkipLocalsInit)
            {
                Assert.Contains(stubMethod.GetAttributes(), attr => attr.AttributeClass !.ToDisplayString() == typeof(SkipLocalsInitAttribute).FullName);
            }
            else
            {
                Assert.DoesNotContain(stubMethod.GetAttributes(), attr => attr.AttributeClass !.ToDisplayString() == typeof(SkipLocalsInitAttribute).FullName);
            }
        }
Пример #5
0
        public async Task TargetFrameworkNotSupported_NoLibraryImport_NoDiagnostic(TestTargetFramework targetFramework)
        {
            string      source = @"
using System.Runtime.InteropServices;
partial class Test
{
    [DllImport(""DoesNotExist"")]
    public static extern void Method();
}
";
            Compilation comp   = await TestUtils.CreateCompilation(source, targetFramework);

            TestUtils.AssertPreSourceGeneratorCompilation(comp);

            var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());

            Assert.Empty(generatorDiags);

            var newCompDiags = newComp.GetDiagnostics();

            Assert.Empty(newCompDiags);
        }
Пример #6
0
        /// <summary>
        /// Get the reference assembly collection for the <see cref="TestTargetFramework"/>.
        /// </summary>
        /// <param name="targetFramework">The target framework.</param>
        /// <returns>The reference assembly collection and metadata references</returns>
        private static async Task <ImmutableArray <MetadataReference> > GetReferenceAssemblies(TestTargetFramework targetFramework = TestTargetFramework.Net)
        {
            // Compute the reference assemblies for the target framework.
            if (targetFramework == TestTargetFramework.Net)
            {
                return(SourceGenerators.Tests.LiveReferencePack.GetMetadataReferences());
            }
            else
            {
                var referenceAssembliesSdk = targetFramework switch
                {
                    TestTargetFramework.Framework => ReferenceAssemblies.NetFramework.Net48.Default,
                    TestTargetFramework.Standard => ReferenceAssemblies.NetStandard.NetStandard21,
                    TestTargetFramework.Core => ReferenceAssemblies.NetCore.NetCoreApp31,
                    TestTargetFramework.Net5 => ReferenceAssemblies.Net.Net50,
                    TestTargetFramework.Net6 => ReferenceAssemblies.Net.Net60,
                    _ => ReferenceAssemblies.Default
                };

                // Update the reference assemblies to include details from the NuGet.config.
                var referenceAssemblies = referenceAssembliesSdk
                                          .WithNuGetConfigFilePath(Path.Combine(Path.GetDirectoryName(typeof(TestUtils).Assembly.Location) !, "NuGet.config"));

                return(await ResolveReferenceAssemblies(referenceAssemblies));
            }
        }
Пример #7
0
        /// <summary>
        /// Create a compilation given sources
        /// </summary>
        /// <param name="sources">Sources to compile</param>
        /// <param name="targetFramework">Target framework of the compilation</param>
        /// <param name="outputKind">Output type</param>
        /// <param name="refs">Addtional metadata references</param>
        /// <returns>The resulting compilation</returns>
        public static async Task <Compilation> CreateCompilation(SyntaxTree[] sources, TestTargetFramework targetFramework = TestTargetFramework.Net, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, IEnumerable <MetadataReference>?refs = null)
        {
            var referenceAssemblies = await GetReferenceAssemblies(targetFramework);

            // [TODO] Can remove once ancillary logic is removed.
            if (targetFramework is TestTargetFramework.Net)
            {
                referenceAssemblies = referenceAssemblies.Add(GetAncillaryReference());
            }

            if (refs is not null)
            {
                referenceAssemblies = referenceAssemblies.AddRange(refs);
            }

            return(CSharpCompilation.Create("compilation",
                                            sources,
                                            referenceAssemblies,
                                            new CSharpCompilationOptions(outputKind, allowUnsafe: true, specificDiagnosticOptions: BindingRedirectWarnings)));
        }
Пример #8
0
 /// <summary>
 /// Create a compilation given source
 /// </summary>
 /// <param name="source">Source to compile</param>
 /// <param name="targetFramework">Target framework of the compilation</param>
 /// <param name="outputKind">Output type</param>
 /// <param name="refs">Addtional metadata references</param>
 /// <param name="preprocessorSymbols">Prepocessor symbols</param>
 /// <returns>The resulting compilation</returns>
 public static Task <Compilation> CreateCompilation(string source, TestTargetFramework targetFramework = TestTargetFramework.Net, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, IEnumerable <MetadataReference>?refs = null, IEnumerable <string>?preprocessorSymbols = null)
 {
     return(CreateCompilation(new[] { source }, targetFramework, outputKind, refs, preprocessorSymbols));
 }
Пример #9
0
 /// <summary>
 /// Create a compilation given source
 /// </summary>
 /// <param name="source">Source to compile</param>
 /// <param name="outputKind">Output type</param>
 /// <param name="allowUnsafe">Whether or not use of the unsafe keyword should be allowed</param>
 /// <returns>The resulting compilation</returns>
 public static Task <Compilation> CreateCompilation(string source, TestTargetFramework targetFramework = TestTargetFramework.Net, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true, IEnumerable <string>?preprocessorSymbols = null)
 {
     return(CreateCompilation(new[] { source }, targetFramework, outputKind, allowUnsafe, preprocessorSymbols));
 }
Пример #10
0
        /// <summary>
        /// Get the reference assembly collection for the <see cref="TestTargetFramework"/>.
        /// </summary>
        /// <param name="targetFramework">The target framework.</param>
        /// <returns>The reference assembly collection and metadata references</returns>
        public static (ReferenceAssemblies, MetadataReference) GetReferenceAssemblies(TestTargetFramework targetFramework = TestTargetFramework.Net)
        {
            // Compute the reference assemblies for the target framework.
            var referenceAssembliesSdk = targetFramework switch
            {
                TestTargetFramework.Framework => ReferenceAssemblies.NetFramework.Net48.Default,
                TestTargetFramework.Standard => ReferenceAssemblies.NetStandard.NetStandard21,
                TestTargetFramework.Core => ReferenceAssemblies.NetCore.NetCoreApp31,
                TestTargetFramework.Net => ReferenceAssemblies.Net.Net60,
                TestTargetFramework.Net5 => ReferenceAssemblies.Net.Net50,
                TestTargetFramework.Net6 => ReferenceAssemblies.Net.Net60,
                _ => ReferenceAssemblies.Default
            };

            // Update the reference assemblies to include details from the NuGet.config.
            var referenceAssemblies = referenceAssembliesSdk
                                      .WithNuGetConfigFilePath(Path.Combine(Path.GetDirectoryName(typeof(TestUtils).Assembly.Location) !, "NuGet.config"));

            // Include the assembly containing the new attribute and all of its references.
            // [TODO] Remove once the attribute has been added to the BCL
            var attrAssem = typeof(GeneratedDllImportAttribute).GetTypeInfo().Assembly;

            return(referenceAssemblies, MetadataReference.CreateFromFile(attrAssem.Location));
        }
Пример #11
0
        /// <summary>
        /// Create a compilation given sources
        /// </summary>
        /// <param name="sources">Sources to compile</param>
        /// <param name="outputKind">Output type</param>
        /// <param name="allowUnsafe">Whether or not use of the unsafe keyword should be allowed</param>
        /// <returns>The resulting compilation</returns>
        public static async Task <Compilation> CreateCompilation(SyntaxTree[] sources, TestTargetFramework targetFramework = TestTargetFramework.Net, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true, IEnumerable <string>?preprocessorSymbols = null)
        {
            var(mdRefs, ancillary) = GetReferenceAssemblies(targetFramework);

            var referenceAssemblies = await ResolveReferenceAssemblies(mdRefs);

            // [TODO] Can remove once ancillary logic is removed.
            if (targetFramework is TestTargetFramework.Net6 or TestTargetFramework.Net)
            {
                referenceAssemblies = referenceAssemblies.Add(ancillary);
            }

            return(CSharpCompilation.Create("compilation",
                                            sources,
                                            referenceAssemblies,
                                            new CSharpCompilationOptions(outputKind, allowUnsafe: allowUnsafe)));
        }