<GrpcToolsVersion>2.45.0</GrpcToolsVersion>
<!-- Uncomment to set a fixed version, else the latest is used -->
<!-- <SdkVersionForWorkloadTesting>8.0.100-alpha.1.23077.3</SdkVersionForWorkloadTesting> -->
- <CompilerPlatformTestingVersion>1.1.2-beta1.22403.2</CompilerPlatformTestingVersion>
+ <CompilerPlatformTestingVersion>1.1.2-beta1.23205.1</CompilerPlatformTestingVersion>
<!-- Docs -->
<MicrosoftPrivateIntellisenseVersion>7.0.0-preview-20221010.1</MicrosoftPrivateIntellisenseVersion>
<!-- ILLink -->
{
if (baseInterface is not null)
{
- return Diagnostic.Create(GeneratorDiagnostics.MultipleComInterfaceBaseTypesAttribute, syntax.Identifier.GetLocation(), type.ToDisplayString());
+ return Diagnostic.Create(GeneratorDiagnostics.MultipleComInterfaceBaseTypes, syntax.Identifier.GetLocation(), type.ToDisplayString());
}
baseInterface = implemented;
}
isEnabledByDefault: true,
description: GetResourceString(nameof(SR.InvalidGeneratedComInterfaceAttributeUsageDescription)));
- public static readonly DiagnosticDescriptor MultipleComInterfaceBaseTypesAttribute =
+ public static readonly DiagnosticDescriptor MultipleComInterfaceBaseTypes =
new DiagnosticDescriptor(
Ids.MultipleComInterfaceBaseTypes,
GetResourceString(nameof(SR.MultipleComInterfaceBaseTypesTitle)),
{
List<FunctionPointerParameterSyntax> functionPointerParameters = new();
var (paramList, retType, _) = _marshallers.GenerateTargetMethodSignatureData(_context);
- functionPointerParameters.AddRange(paramList.Parameters.Select(p => FunctionPointerParameter(p.Type)));
+ functionPointerParameters.AddRange(paramList.Parameters.Select(p => FunctionPointerParameter(attributeLists: default, p.Modifiers, p.Type)));
functionPointerParameters.Add(FunctionPointerParameter(retType));
// ((delegate* unmanaged<...>)<untypedFunctionPointerExpression>)
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
-using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Operations;
-using Microsoft.Interop.UnitTests;
+using Microsoft.CodeAnalysis.Testing;
using Xunit;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier<Microsoft.Interop.VtableIndexStubGenerator>;
+
namespace ComInterfaceGenerator.Unit.Tests
{
public class CallingConventionForwarding
void Method();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- // Allow the Native nested type name to be missing in the pre-source-generator compilation
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator());
- var signature = await FindFunctionPointerInvocationSignature(newComp, "INativeAPI", "Method");
-
- Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention);
- Assert.Empty(signature.UnmanagedCallingConventionTypes);
+ await VerifySourceGeneratorAsync(source, "INativeAPI", "Method", (compilation, signature) =>
+ {
+ Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention);
+ Assert.Empty(signature.UnmanagedCallingConventionTypes);
+ });
}
[Fact]
void Method();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- // Allow the Native nested type name to be missing in the pre-source-generator compilation
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator());
-
- var signature = await FindFunctionPointerInvocationSignature(newComp, "INativeAPI", "Method");
-
- Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention);
- Assert.Equal(newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvSuppressGCTransition"), Assert.Single(signature.UnmanagedCallingConventionTypes), SymbolEqualityComparer.Default);
+ await VerifySourceGeneratorAsync(source, "INativeAPI", "Method", (newComp, signature) =>
+ {
+ Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention);
+ Assert.Equal(newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvSuppressGCTransition"), Assert.Single(signature.UnmanagedCallingConventionTypes), SymbolEqualityComparer.Default);
+ });
}
[Fact]
void Method();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- // Allow the Native nested type name to be missing in the pre-source-generator compilation
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator());
-
- var signature = await FindFunctionPointerInvocationSignature(newComp, "INativeAPI", "Method");
-
- Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention);
- Assert.Empty(signature.UnmanagedCallingConventionTypes);
+ await VerifySourceGeneratorAsync(source, "INativeAPI", "Method", (_, signature) =>
+ {
+ Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention);
+ Assert.Empty(signature.UnmanagedCallingConventionTypes);
+ });
}
[Fact]
public async Task SimpleUnmanagedCallConvAttributeForwarded()
{
string source = $$"""
+ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
void Method();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- // Allow the Native nested type name to be missing in the pre-source-generator compilation
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator());
- var signature = await FindFunctionPointerInvocationSignature(newComp, "INativeAPI", "Method");
-
- Assert.Equal(SignatureCallingConvention.CDecl, signature.CallingConvention);
- Assert.Empty(signature.UnmanagedCallingConventionTypes);
+ await VerifySourceGeneratorAsync(source, "INativeAPI", "Method", (_, signature) =>
+ {
+ Assert.Equal(SignatureCallingConvention.CDecl, signature.CallingConvention);
+ Assert.Empty(signature.UnmanagedCallingConventionTypes);
+ });
}
[Fact]
public async Task ComplexUnmanagedCallConvAttributeForwarded()
{
string source = $$"""
+ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
void Method();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- // Allow the Native nested type name to be missing in the pre-source-generator compilation
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator());
- var signature = await FindFunctionPointerInvocationSignature(newComp, "INativeAPI", "Method");
-
- Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention);
- Assert.Equal(new[]
+ await VerifySourceGeneratorAsync(source, "INativeAPI", "Method", (newComp, signature) =>
{
- newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvCdecl"),
- newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvMemberFunction"),
- },
- signature.UnmanagedCallingConventionTypes,
- SymbolEqualityComparer.Default);
+ Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention);
+ Assert.Equal(new[]
+ {
+ newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvCdecl"),
+ newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvMemberFunction"),
+ },
+ signature.UnmanagedCallingConventionTypes,
+ SymbolEqualityComparer.Default);
+ });
}
[Fact]
public async Task ComplexUnmanagedCallConvAttributeWithSuppressGCTransitionForwarded()
{
string source = $$"""
+ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
void Method();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- // Allow the Native nested type name to be missing in the pre-source-generator compilation
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator());
-
- var signature = await FindFunctionPointerInvocationSignature(newComp, "INativeAPI", "Method");
+ await VerifySourceGeneratorAsync(source, "INativeAPI", "Method", (newComp, signature) =>
+ {
+ Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention);
+ Assert.Equal(new[]
+ {
+ newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvSuppressGCTransition"),
+ newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvCdecl"),
+ newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvMemberFunction"),
+ },
+ signature.UnmanagedCallingConventionTypes,
+ SymbolEqualityComparer.Default);
+ });
+ }
- Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention);
- Assert.Equal(new[]
+ private static async Task VerifySourceGeneratorAsync(string source, string interfaceName, string methodName, Action<Compilation, IMethodSymbol> signatureValidator)
+ {
+ CallingConventionForwardingTest test = new(interfaceName, methodName, signatureValidator)
{
- newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvSuppressGCTransition"),
- newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvCdecl"),
- newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvMemberFunction"),
- },
- signature.UnmanagedCallingConventionTypes,
- SymbolEqualityComparer.Default);
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
+
+ await test.RunAsync();
}
- private static async Task<IMethodSymbol> FindFunctionPointerInvocationSignature(Compilation compilation, string userDefinedInterfaceName, string methodName)
+ class CallingConventionForwardingTest : VerifyCS.Test
{
- INamedTypeSymbol? userDefinedInterface = compilation.Assembly.GetTypeByMetadataName(userDefinedInterfaceName);
- Assert.NotNull(userDefinedInterface);
+ private readonly Action<Compilation, IMethodSymbol> _signatureValidator;
+ private readonly string _interfaceName;
+ private readonly string _methodName;
+
+ public CallingConventionForwardingTest(string interfaceName, string methodName, Action<Compilation, IMethodSymbol> signatureValidator)
+ : base(referenceAncillaryInterop: true)
+ {
+ _signatureValidator = signatureValidator;
+ _interfaceName = interfaceName;
+ _methodName = methodName;
+ }
+
+ protected override void VerifyFinalCompilation(Compilation compilation)
+ {
+ _signatureValidator(compilation, FindFunctionPointerInvocationSignature(compilation));
+ }
+ private IMethodSymbol FindFunctionPointerInvocationSignature(Compilation compilation)
+ {
+ INamedTypeSymbol? userDefinedInterface = compilation.Assembly.GetTypeByMetadataName(_interfaceName);
+ Assert.NotNull(userDefinedInterface);
- INamedTypeSymbol generatedInterfaceImplementation = Assert.Single(userDefinedInterface.GetTypeMembers("Native"));
+ INamedTypeSymbol generatedInterfaceImplementation = Assert.Single(userDefinedInterface.GetTypeMembers("Native"));
- IMethodSymbol methodImplementation = Assert.Single(generatedInterfaceImplementation.GetMembers($"global::{userDefinedInterfaceName}.{methodName}").OfType<IMethodSymbol>());
+ IMethodSymbol methodImplementation = Assert.Single(generatedInterfaceImplementation.GetMembers($"global::{_interfaceName}.{_methodName}").OfType<IMethodSymbol>());
- SyntaxNode emittedImplementationSyntax = await methodImplementation.DeclaringSyntaxReferences[0].GetSyntaxAsync();
+ SyntaxNode emittedImplementationSyntax = methodImplementation.DeclaringSyntaxReferences[0].GetSyntax();
- SemanticModel model = compilation.GetSemanticModel(emittedImplementationSyntax.SyntaxTree);
+ SemanticModel model = compilation.GetSemanticModel(emittedImplementationSyntax.SyntaxTree);
- IOperation body = model.GetOperation(emittedImplementationSyntax)!;
+ IOperation body = model.GetOperation(emittedImplementationSyntax)!;
- return Assert.Single(body.Descendants().OfType<IFunctionPointerInvocationOperation>()).GetFunctionPointerSignature();
+ return Assert.Single(body.Descendants().OfType<IFunctionPointerInvocationOperation>()).GetFunctionPointerSignature();
+ }
}
}
}
partial interface INativeAPI
{
{{VirtualMethodIndex(0)}}
- {{methodModifiers}} {{typeName}} Method({{typeName}} value, in {{typeName}} inValue, ref {{typeName}} refValue, out {{typeName}} outValue);
+ {{methodModifiers}} {{typeName}} {|#0:Method|}({{typeName}} {|#1:value|}, in {{typeName}} {|#2:inValue|}, ref {{typeName}} {|#3:refValue|}, out {{typeName}} {|#4:outValue|});
}
{{_attributeProvider.AdditionalUserRequiredInterfaces("INativeAPI")}}
""";
void MethodA();
}
{{GeneratedComInterface}}
- partial interface IComInterface2 : IComInterface, IOtherComInterface
+ partial interface {|#0:IComInterface2|} : IComInterface, IOtherComInterface
{
void Method2();
}
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
-using Microsoft.Interop.UnitTests;
+using Microsoft.CodeAnalysis.Testing;
using Xunit;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier<Microsoft.Interop.ComClassGenerator>;
+
namespace ComInterfaceGenerator.Unit.Tests
{
public class ComClassGeneratorOutputShape
[GeneratedComClass]
partial class C : INativeAPI {}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.ComClassGenerator());
- TestUtils.AssertPostSourceGeneratorCompilation(newComp);
- // We'll create one syntax tree for the new interface.
- Assert.Equal(comp.SyntaxTrees.Count() + 1, newComp.SyntaxTrees.Count());
- VerifyShape(newComp, "C");
+ await VerifySourceGeneratorAsync(source, "C");
}
[Fact]
{
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.ComClassGenerator());
- TestUtils.AssertPostSourceGeneratorCompilation(newComp);
- // We'll create one syntax tree per user-defined interface.
- Assert.Equal(comp.SyntaxTrees.Count() + 3, newComp.SyntaxTrees.Count());
+ await VerifySourceGeneratorAsync(source, "C", "D", "E");
+ }
+
+ private static async Task VerifySourceGeneratorAsync(string source, params string[] typeNames)
+ {
+ GeneratedShapeTest test = new(typeNames)
+ {
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
- VerifyShape(newComp, "C");
- VerifyShape(newComp, "D");
- VerifyShape(newComp, "E");
+ await test.RunAsync();
}
- private static void VerifyShape(Compilation comp, string userDefinedClassMetadataName)
+ class GeneratedShapeTest : VerifyCS.Test
{
- INamedTypeSymbol? userDefinedClass = comp.Assembly.GetTypeByMetadataName(userDefinedClassMetadataName);
- Assert.NotNull(userDefinedClass);
+ private readonly string[] _typeNames;
- INamedTypeSymbol? comExposedClassAttribute = comp.GetTypeByMetadataName("System.Runtime.InteropServices.Marshalling.ComExposedClassAttribute`1");
+ public GeneratedShapeTest(params string[] typeNames)
+ :base(referenceAncillaryInterop: false)
+ {
+ _typeNames = typeNames;
+ }
- Assert.NotNull(comExposedClassAttribute);
+ protected override void VerifyFinalCompilation(Compilation compilation)
+ {
+ // Generate one source file per attributed interface.
+ Assert.Equal(TestState.Sources.Count + _typeNames.Length, compilation.SyntaxTrees.Count());
+ Assert.All(_typeNames, name => VerifyShape(compilation, name));
+ }
- AttributeData iUnknownDerivedAttribute = Assert.Single(
- userDefinedClass.GetAttributes(),
- attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass?.OriginalDefinition, comExposedClassAttribute));
+ private static void VerifyShape(Compilation comp, string userDefinedClassMetadataName)
+ {
+ INamedTypeSymbol? userDefinedClass = comp.Assembly.GetTypeByMetadataName(userDefinedClassMetadataName);
+ Assert.NotNull(userDefinedClass);
- Assert.Collection(Assert.IsAssignableFrom<INamedTypeSymbol>(iUnknownDerivedAttribute.AttributeClass).TypeArguments,
- infoType =>
- {
- Assert.True(Assert.IsAssignableFrom<INamedTypeSymbol>(infoType).IsFileLocal);
- });
+ INamedTypeSymbol? comExposedClassAttribute = comp.GetTypeByMetadataName("System.Runtime.InteropServices.Marshalling.ComExposedClassAttribute`1");
+
+ Assert.NotNull(comExposedClassAttribute);
+
+ AttributeData iUnknownDerivedAttribute = Assert.Single(
+ userDefinedClass.GetAttributes(),
+ attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass?.OriginalDefinition, comExposedClassAttribute));
+
+ Assert.Collection(Assert.IsAssignableFrom<INamedTypeSymbol>(iUnknownDerivedAttribute.AttributeClass).TypeArguments,
+ infoType =>
+ {
+ Assert.True(Assert.IsAssignableFrom<INamedTypeSymbol>(infoType).IsFileLocal);
+ });
+ }
}
}
}
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
Link="Verifiers\CSharpAnalyzerVerifier.cs"/>
<Compile Include="..\Common\Verifiers\CSharpCodeFixVerifier.cs"
Link="Verifiers\CSharpCodeFixVerifier.cs"/>
+ <Compile Include="..\Common\Verifiers\CSharpSourceGeneratorVerifier.cs"
+ Link="Verifiers\CSharpSourceGeneratorVerifier.cs"/>
<Compile Include="..\Common\Verifiers\CSharpVerifierHelper.cs"
Link="Verifiers\CSharpVerifierHelper.cs"/>
</ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="$(MicrosoftCodeAnalysisVersion)" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.XUnit" Version="$(CompilerPlatformTestingVersion)" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing.XUnit" Version="$(CompilerPlatformTestingVersion)" />
+ <PackageReference Include="Microsoft.CodeAnalysis.CSharp.SourceGenerators.Testing.XUnit" Version="$(CompilerPlatformTestingVersion)" />
</ItemGroup>
<ItemGroup>
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
+using Microsoft;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Testing;
using Microsoft.Interop.UnitTests;
using Xunit;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier<Microsoft.Interop.ComInterfaceGenerator>;
+
namespace ComInterfaceGenerator.Unit.Tests
{
public class ComInterfaceGeneratorOutputShape
void Method2();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.ComInterfaceGenerator());
- TestUtils.AssertPostSourceGeneratorCompilation(newComp);
- // We'll create one syntax tree for the new interface.
- Assert.Equal(comp.SyntaxTrees.Count() + 1, newComp.SyntaxTrees.Count());
- VerifyShape(newComp, "INativeAPI");
+ await VerifySourceGeneratorAsync(source, "INativeAPI");
}
[Fact]
void Method2();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.ComInterfaceGenerator());
- TestUtils.AssertPostSourceGeneratorCompilation(newComp);
- // We'll create one syntax tree per user-defined interface.
- Assert.Equal(comp.SyntaxTrees.Count() + 2, newComp.SyntaxTrees.Count());
- VerifyShape(newComp, "I");
- VerifyShape(newComp, "J");
+ await VerifySourceGeneratorAsync(source, "I", "J");
}
[Fact]
void Method2();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.ComInterfaceGenerator());
- TestUtils.AssertPostSourceGeneratorCompilation(newComp);
- // We'll create one syntax tree per user-defined interface.
- Assert.Equal(comp.SyntaxTrees.Count() + 3, newComp.SyntaxTrees.Count());
-
- VerifyShape(newComp, "I");
- VerifyShape(newComp, "Empty");
- VerifyShape(newComp, "J");
+ await VerifySourceGeneratorAsync(source, "I", "Empty", "J");
}
[Fact]
void MethodB();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.ComInterfaceGenerator());
- TestUtils.AssertPostSourceGeneratorCompilation(newComp);
- // We'll create one syntax tree per user-defined interface.
- Assert.Equal(comp.SyntaxTrees.Count() + 2, newComp.SyntaxTrees.Count());
- VerifyShape(newComp, "I");
- VerifyShape(newComp, "J");
+ await VerifySourceGeneratorAsync(source, "I", "J");
}
- private static void VerifyShape(Compilation comp, string userDefinedInterfaceMetadataName)
+ private static async Task VerifySourceGeneratorAsync(string source, params string[] typeNames)
{
- INamedTypeSymbol? userDefinedInterface = comp.Assembly.GetTypeByMetadataName(userDefinedInterfaceMetadataName);
- Assert.NotNull(userDefinedInterface);
-
- INamedTypeSymbol? iUnknownDerivedAttributeType = comp.GetTypeByMetadataName("System.Runtime.InteropServices.Marshalling.IUnknownDerivedAttribute`2");
+ GeneratedShapeTest test = new(typeNames)
+ {
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
- Assert.NotNull(iUnknownDerivedAttributeType);
-
- AttributeData iUnknownDerivedAttribute = Assert.Single(
- userDefinedInterface.GetAttributes(),
- attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass?.OriginalDefinition, iUnknownDerivedAttributeType));
-
- Assert.Collection(Assert.IsAssignableFrom<INamedTypeSymbol>(iUnknownDerivedAttribute.AttributeClass).TypeArguments,
- infoType =>
- {
- Assert.True(Assert.IsAssignableFrom<INamedTypeSymbol>(infoType).IsFileLocal);
- },
- implementationType =>
- {
- Assert.True(Assert.IsAssignableFrom<INamedTypeSymbol>(implementationType).IsFileLocal);
- Assert.Contains(userDefinedInterface, implementationType.Interfaces, SymbolEqualityComparer.Default);
- Assert.Contains(implementationType.GetAttributes(), attr => attr.AttributeClass?.ToDisplayString() == typeof(DynamicInterfaceCastableImplementationAttribute).FullName);
- Assert.All(userDefinedInterface.GetMembers().OfType<IMethodSymbol>().Where(method => method.IsAbstract && !method.IsStatic),
- method =>
- {
- Assert.NotNull(implementationType.FindImplementationForInterfaceMember(method));
- });
- });
+ await test.RunAsync();
+ }
+ class GeneratedShapeTest : VerifyCS.Test
+ {
+ private readonly string[] _typeNames;
+
+ public GeneratedShapeTest(params string[] typeNames)
+ : base(referenceAncillaryInterop: false)
+ {
+ _typeNames = typeNames;
+ }
+
+ protected override void VerifyFinalCompilation(Compilation compilation)
+ {
+ // Generate one source file per attributed interface.
+ Assert.Equal(TestState.Sources.Count + _typeNames.Length, compilation.SyntaxTrees.Count());
+ Assert.All(_typeNames, name => VerifyShape(compilation, name));
+ }
+
+ private static void VerifyShape(Compilation comp, string userDefinedInterfaceMetadataName)
+ {
+ INamedTypeSymbol? userDefinedInterface = comp.Assembly.GetTypeByMetadataName(userDefinedInterfaceMetadataName);
+ Assert.NotNull(userDefinedInterface);
+
+ INamedTypeSymbol? iUnknownDerivedAttributeType = comp.GetTypeByMetadataName("System.Runtime.InteropServices.Marshalling.IUnknownDerivedAttribute`2");
+
+ Assert.NotNull(iUnknownDerivedAttributeType);
+
+ AttributeData iUnknownDerivedAttribute = Assert.Single(
+ userDefinedInterface.GetAttributes(),
+ attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass?.OriginalDefinition, iUnknownDerivedAttributeType));
+
+ Assert.Collection(Assert.IsAssignableFrom<INamedTypeSymbol>(iUnknownDerivedAttribute.AttributeClass).TypeArguments,
+ infoType =>
+ {
+ Assert.True(Assert.IsAssignableFrom<INamedTypeSymbol>(infoType).IsFileLocal);
+ },
+ implementationType =>
+ {
+ Assert.True(Assert.IsAssignableFrom<INamedTypeSymbol>(implementationType).IsFileLocal);
+ Assert.Contains(userDefinedInterface, implementationType.Interfaces, SymbolEqualityComparer.Default);
+ Assert.Contains(implementationType.GetAttributes(), attr => attr.AttributeClass?.ToDisplayString() == typeof(DynamicInterfaceCastableImplementationAttribute).FullName);
+ Assert.All(userDefinedInterface.GetMembers().OfType<IMethodSymbol>().Where(method => method.IsAbstract && !method.IsStatic),
+ method =>
+ {
+ Assert.NotNull(implementationType.FindImplementationForInterfaceMember(method));
+ });
+ });
+ }
}
}
}
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Testing;
using Microsoft.Interop.UnitTests;
using Xunit;
+using System.Diagnostics;
+
+
+using VerifyComInterfaceGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier<Microsoft.Interop.ComInterfaceGenerator>;
+using Microsoft.Interop;
+
namespace ComInterfaceGenerator.Unit.Tests
{
public class CompileFails
{
CodeSnippets codeSnippets = new(new GeneratedComInterfaceAttributeProvider());
// Inheriting from multiple GeneratedComInterface-marked interfaces.
- yield return new object[] { ID(), codeSnippets.DerivedComInterfaceTypeMultipleComInterfaceBases, 1, 0 };
+ yield return new object[] { ID(), codeSnippets.DerivedComInterfaceTypeMultipleComInterfaceBases, new[] {
+ VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.MultipleComInterfaceBaseTypes)
+ .WithLocation(0)
+ .WithArguments("IComInterface2")
+ } };
}
[Theory]
[MemberData(nameof(ComInterfaceGeneratorSnippetsToCompile))]
- public async Task ValidateComInterfaceGeneratorSnippets(string id, string source, int expectedGeneratorErrors, int expectedCompilerErrors)
+ public async Task ValidateComInterfaceGeneratorSnippets(string id, string source, DiagnosticResult[] expectedDiagnostics)
{
TestUtils.Use(id);
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.ComInterfaceGenerator());
-
- // Verify the compilation failed with errors.
- IEnumerable<Diagnostic> generatorErrors = generatorDiags.Where(d => d.Severity == DiagnosticSeverity.Error);
- int generatorErrorCount = generatorErrors.Count();
- Assert.True(
- expectedGeneratorErrors == generatorErrorCount,
- $"Expected {expectedGeneratorErrors} errors, but encountered {generatorErrorCount}. Errors: {string.Join(Environment.NewLine, generatorErrors.Select(d => d.ToString()))}");
-
- IEnumerable<Diagnostic> compilerErrors = newComp.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error);
- int compilerErrorCount = compilerErrors.Count();
- Assert.True(
- expectedCompilerErrors == compilerErrorCount,
- $"Expected {expectedCompilerErrors} errors, but encountered {compilerErrorCount}. Errors: {string.Join(Environment.NewLine, compilerErrors.Select(d => d.ToString()))}");
+ await VerifyComInterfaceGenerator.VerifySourceGeneratorAsync(source, expectedDiagnostics);
+ }
+
+ private static IComInterfaceAttributeProvider GetAttributeProvider(GeneratorKind generator)
+ => generator switch
+ {
+ GeneratorKind.VTableIndexStubGenerator => new VirtualMethodIndexAttributeProvider(),
+ GeneratorKind.ComInterfaceGenerator => new GeneratedComInterfaceAttributeProvider(),
+ _ => throw new UnreachableException(),
+ };
+
+ public static IEnumerable<object[]> InvalidUnmanagedToManagedCodeSnippetsToCompile(GeneratorKind generator)
+ {
+ CodeSnippets codeSnippets = new(GetAttributeProvider(generator));
+
+ // SafeHandles
+ yield return new object[] { ID(), codeSnippets.BasicParametersAndModifiers("Microsoft.Win32.SafeHandles.SafeFileHandle"), new[]
+ {
+ VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails).WithLocation(0).WithArguments("The specified parameter needs to be marshalled from managed to unmanaged, but the marshaller type 'global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller<global::Microsoft.Win32.SafeHandles.SafeFileHandle>' does not support it.", "Method"),
+ VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails).WithLocation(1).WithArguments("The specified parameter needs to be marshalled from unmanaged to managed, but the marshaller type 'global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller<global::Microsoft.Win32.SafeHandles.SafeFileHandle>' does not support it.", "value"),
+ // /0/Test0.cs(13,151): error SYSLIB1051: The type 'Microsoft.Win32.SafeHandles.SafeFileHandle' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter 'inValue'.
+ VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails).WithLocation(2).WithArguments("The specified parameter needs to be marshalled from unmanaged to managed, but the marshaller type 'global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller<global::Microsoft.Win32.SafeHandles.SafeFileHandle>' does not support it.", "inValue"),
+ // /0/Test0.cs(13,207): error SYSLIB1051: The type 'Microsoft.Win32.SafeHandles.SafeFileHandle' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter 'refValue'.
+ VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails).WithLocation(3).WithArguments("The specified parameter needs to be marshalled from managed to unmanaged and unmanaged to managed, but the marshaller type 'global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller<global::Microsoft.Win32.SafeHandles.SafeFileHandle>' does not support it.", "refValue"),
+ // /0/Test0.cs(13,264): error SYSLIB1051: The type 'Microsoft.Win32.SafeHandles.SafeFileHandle' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter 'outValue'.
+ VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails).WithLocation(4).WithArguments("The specified parameter needs to be marshalled from managed to unmanaged, but the marshaller type 'global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller<global::Microsoft.Win32.SafeHandles.SafeFileHandle>' does not support it.", "outValue"),
+ } };
+
+
+ // Marshallers with only support for their expected places in the signatures in
+ // ManagedToUnmanaged marshal modes.
+
+ DiagnosticResult invalidManagedToUnmanagedParameterDiagnostic = VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The specified parameter needs to be marshalled from managed to unmanaged, but the marshaller type 'global::Marshaller' does not support it.", "value");
+ DiagnosticResult invalidUnmanagedToManagedParameterDiagnostic = VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The specified parameter needs to be marshalled from unmanaged to managed, but the marshaller type 'global::Marshaller' does not support it.", "value");
+ DiagnosticResult invalidReturnTypeDiagnostic = VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The specified parameter needs to be marshalled from managed to unmanaged, but the marshaller type 'global::Marshaller' does not support it.", "Method");
+ CustomStructMarshallingCodeSnippets customStructMarshallingCodeSnippets = new(new CodeSnippets.Bidirectional(GetAttributeProvider(generator)));
+ yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateless.NativeToManagedOnlyOutParameter, new[] { invalidManagedToUnmanagedParameterDiagnostic } };
+ yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateless.NativeToManagedOnlyReturnValue, new[] { invalidReturnTypeDiagnostic } };
+ yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateless.ByValueInParameter, new[] { invalidUnmanagedToManagedParameterDiagnostic } };
+ yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateful.NativeToManagedOnlyOutParameter, new[] { invalidManagedToUnmanagedParameterDiagnostic } };
+ yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateful.NativeToManagedOnlyReturnValue, new[] { invalidReturnTypeDiagnostic } };
+ yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateful.ByValueInParameter, new[] { invalidUnmanagedToManagedParameterDiagnostic } };
+ }
+
+ public static IEnumerable<object[]> InvalidManagedToUnmanagedCodeSnippetsToCompile(GeneratorKind generator)
+ {
+ // Marshallers with only support for their expected places in the signatures in
+ // UnmanagedToManaged marshal modes.
+ CustomStructMarshallingCodeSnippets customStructMarshallingCodeSnippets = new(new CodeSnippets.Bidirectional(GetAttributeProvider(generator)));
+
+ yield return new[] { ID(), customStructMarshallingCodeSnippets.Stateless.NativeToManagedOnlyInParameter };
+ yield return new[] { ID(), customStructMarshallingCodeSnippets.Stateless.ByValueOutParameter };
+ yield return new[] { ID(), customStructMarshallingCodeSnippets.Stateful.NativeToManagedOnlyInParameter };
+ yield return new[] { ID(), customStructMarshallingCodeSnippets.Stateful.ByValueOutParameter };
+ }
+
+ [Theory]
+ [MemberData(nameof(InvalidUnmanagedToManagedCodeSnippetsToCompile), GeneratorKind.ComInterfaceGenerator)]
+ public async Task ValidateInvalidUnmanagedToManagedCodeSnippets(string id, string source, DiagnosticResult[] expectedDiagnostics)
+ {
+ _ = id;
+ VerifyComInterfaceGenerator.Test test = new(referenceAncillaryInterop: false)
+ {
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck,
+ // Our fallback mechanism for invalid code for unmanaged->managed stubs sometimes generates invalid code.
+ CompilerDiagnostics = CompilerDiagnostics.None,
+ };
+ test.ExpectedDiagnostics.AddRange(expectedDiagnostics);
+ await test.RunAsync();
+ }
+
+ [Theory]
+ [MemberData(nameof(InvalidManagedToUnmanagedCodeSnippetsToCompile), GeneratorKind.ComInterfaceGenerator)]
+ public async Task ValidateInvalidManagedToUnmanagedCodeSnippets(string id, string source)
+ {
+ _ = id;
+
+ DiagnosticResult expectedDiagnostic = VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The specified parameter needs to be marshalled from managed to unmanaged, but the marshaller type 'global::Marshaller' does not support it.", "value");
+ await VerifyComInterfaceGenerator.VerifySourceGeneratorAsync(source, expectedDiagnostic);
}
}
}
using Microsoft.Interop.UnitTests;
using Xunit;
+using VerifyVTableGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier<Microsoft.Interop.VtableIndexStubGenerator>;
+using VerifyComInterfaceGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier<Microsoft.Interop.ComInterfaceGenerator>;
+using Microsoft.CodeAnalysis.Testing;
+
namespace ComInterfaceGenerator.Unit.Tests
{
public class Compiles
yield return new[] { ID(), codeSnippets.BasicParametersAndModifiersNoImplicitThis<IntPtr>() };
yield return new[] { ID(), codeSnippets.BasicParametersAndModifiersNoImplicitThis<UIntPtr>() };
+ // Custom type marshalling bidirectional
+ CustomStructMarshallingCodeSnippets customStructMarshallingCodeSnippetsBidirectional = new(new CodeSnippets.Bidirectional(GetAttributeProvider(generator)));
+ yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateless.ParametersAndModifiers };
+ yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateless.MarshalUsingParametersAndModifiers };
+ yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateless.RefParameter };
+ yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateless.OptionalStackallocParametersAndModifiers };
+ yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateful.ParametersAndModifiers };
+ yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateful.ParametersAndModifiersWithFree };
+ yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateful.ParametersAndModifiersWithOnInvoked };
+ yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateful.MarshalUsingParametersAndModifiers };
+ yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateful.RefParameter };
+ yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateful.OptionalStackallocParametersAndModifiers };
+
+ // Exception Handling
+ // HResult
+ yield return new[] { ID(), codeSnippets.BasicReturnTypeComExceptionHandling("int") };
+ yield return new[] { ID(), codeSnippets.BasicReturnTypeComExceptionHandling("uint") };
+ // NaN
+ yield return new[] { ID(), codeSnippets.BasicReturnTypeComExceptionHandling("float") };
+ yield return new[] { ID(), codeSnippets.BasicReturnTypeComExceptionHandling("double") };
+ // Default Value
+ yield return new[] { ID(), codeSnippets.BasicReturnTypeComExceptionHandling("nint") };
+ // Void
+ yield return new[] { ID(), codeSnippets.BasicReturnTypeComExceptionHandling("void") };
+ }
+
+ public static IEnumerable<object[]> ManagedToUnmanagedCodeSnippetsToCompile(GeneratorKind generator)
+ {
+ CodeSnippets codeSnippets = new(GetAttributeProvider(generator));
+
+ // SafeHandles
+ yield return new[] { ID(), codeSnippets.BasicParametersAndModifiersManagedToUnmanaged("Microsoft.Win32.SafeHandles.SafeFileHandle") };
+
// Custom type marshalling managed-to-unmanaged
CustomStructMarshallingCodeSnippets customStructMarshallingCodeSnippetsManagedToUnmanaged = new(new CodeSnippets.ManagedToUnmanaged(GetAttributeProvider(generator)));
yield return new[] { ID(), customStructMarshallingCodeSnippetsManagedToUnmanaged.Stateless.ParametersAndModifiers };
yield return new[] { ID(), customStructMarshallingCodeSnippetsManagedToUnmanaged.Stateful.OptionalStackallocParametersAndModifiers };
yield return new[] { ID(), customStructMarshallingCodeSnippetsManagedToUnmanaged.Stateful.DefaultModeByValueInParameter };
yield return new[] { ID(), customStructMarshallingCodeSnippetsManagedToUnmanaged.Stateful.DefaultModeReturnValue };
+ }
+ public static IEnumerable<object[]> UnmanagedToManagedCodeSnippetsToCompile(GeneratorKind generator)
+ {
// Custom type marshalling unmanaged-to-managed
CustomStructMarshallingCodeSnippets customStructMarshallingCodeSnippetsUnmanagedToManaged = new(new CodeSnippets.UnmanagedToManaged(GetAttributeProvider(generator)));
yield return new[] { ID(), customStructMarshallingCodeSnippetsUnmanagedToManaged.Stateless.ParametersAndModifiers };
yield return new[] { ID(), customStructMarshallingCodeSnippetsUnmanagedToManaged.Stateful.ByValueOutParameter };
yield return new[] { ID(), customStructMarshallingCodeSnippetsUnmanagedToManaged.Stateful.RefParameter };
yield return new[] { ID(), customStructMarshallingCodeSnippetsUnmanagedToManaged.Stateful.OptionalStackallocParametersAndModifiers };
-
- // Custom type marshalling bidirectional
- CustomStructMarshallingCodeSnippets customStructMarshallingCodeSnippetsBidirectional = new(new CodeSnippets.Bidirectional(GetAttributeProvider(generator)));
- yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateless.ParametersAndModifiers };
- yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateless.MarshalUsingParametersAndModifiers };
- yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateless.RefParameter };
- yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateless.OptionalStackallocParametersAndModifiers };
- yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateful.ParametersAndModifiers };
- yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateful.ParametersAndModifiersWithFree };
- yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateful.ParametersAndModifiersWithOnInvoked };
- yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateful.MarshalUsingParametersAndModifiers };
- yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateful.RefParameter };
- yield return new[] { ID(), customStructMarshallingCodeSnippetsBidirectional.Stateful.OptionalStackallocParametersAndModifiers };
-
- // SafeHandles
- yield return new[] { ID(), codeSnippets.BasicParametersAndModifiersManagedToUnmanaged("Microsoft.Win32.SafeHandles.SafeFileHandle") };
-
- // Exception Handling
- // HResult
- yield return new[] { ID(), codeSnippets.BasicReturnTypeComExceptionHandling("int") };
- yield return new[] { ID(), codeSnippets.BasicReturnTypeComExceptionHandling("uint") };
- // NaN
- yield return new[] { ID(), codeSnippets.BasicReturnTypeComExceptionHandling("float") };
- yield return new[] { ID(), codeSnippets.BasicReturnTypeComExceptionHandling("double") };
- // Default Value
- yield return new[] { ID(), codeSnippets.BasicReturnTypeComExceptionHandling("nint") };
- // Void
- yield return new[] { ID(), codeSnippets.BasicReturnTypeComExceptionHandling("void") };
}
public static IEnumerable<object[]> CustomCollections(GeneratorKind generator)
{
// Custom collection marshalling
+ CodeSnippets codeSnippets = new(GetAttributeProvider(generator));
+ yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<byte[]>() };
+ yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<sbyte[]>() };
+ yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<short[]>() };
+ yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<ushort[]>() };
+ yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<int[]>() };
+ yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<uint[]>() };
+ yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<long[]>() };
+ yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<ulong[]>() };
+ yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<float[]>() };
+ yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<double[]>() };
+ yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<IntPtr[]>() };
+ yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<UIntPtr[]>() };
+
+ CustomCollectionMarshallingCodeSnippets customCollectionMarshallingCodeSnippetsBidirectional = new(new CodeSnippets.Bidirectional(GetAttributeProvider(generator)));
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<byte>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<sbyte>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<short>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<ushort>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<int>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<uint>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<long>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<ulong>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<float>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<double>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<IntPtr>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<UIntPtr>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<byte>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<sbyte>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<short>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<ushort>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<int>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<uint>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<long>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<ulong>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<float>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<double>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<IntPtr>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<UIntPtr>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerReturnValueLength<int>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.NestedMarshallerParametersAndModifiers<int>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.NonBlittableElementParametersAndModifiers };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomElementMarshalling };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<byte>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<sbyte>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<short>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<ushort>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<int>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<uint>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<long>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<ulong>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<float>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<double>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<IntPtr>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<UIntPtr>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<byte>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<sbyte>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<short>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<ushort>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<int>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<uint>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<long>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<ulong>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<float>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<double>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<IntPtr>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<UIntPtr>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerReturnValueLength<int>() };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.NonBlittableElementParametersAndModifiers };
+ yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomElementMarshalling };
+ }
+
+ public static IEnumerable<object[]> CustomCollectionsManagedToUnmanaged(GeneratorKind generator)
+ {
CustomCollectionMarshallingCodeSnippets customCollectionMarshallingCodeSnippetsManagedToUnmanaged = new(new CodeSnippets.ManagedToUnmanaged(GetAttributeProvider(generator)));
yield return new[] { ID(), customCollectionMarshallingCodeSnippetsManagedToUnmanaged.Stateless.ByValue<byte>() };
yield return new[] { ID(), customCollectionMarshallingCodeSnippetsManagedToUnmanaged.Stateless.ByValue<sbyte>() };
yield return new[] { ID(), customCollectionMarshallingCodeSnippetsManagedToUnmanaged.Stateful.NonBlittableElementByValue };
yield return new[] { ID(), customCollectionMarshallingCodeSnippetsManagedToUnmanaged.Stateful.NonBlittableElementNativeToManagedOnlyOutParameter };
yield return new[] { ID(), customCollectionMarshallingCodeSnippetsManagedToUnmanaged.Stateful.NonBlittableElementNativeToManagedOnlyReturnValue };
-
- CodeSnippets codeSnippets = new(GetAttributeProvider(generator));
- yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<byte[]>() };
- yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<sbyte[]>() };
- yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<short[]>() };
- yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<ushort[]>() };
- yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<int[]>() };
- yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<uint[]>() };
- yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<long[]>() };
- yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<ulong[]>() };
- yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<float[]>() };
- yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<double[]>() };
- yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<IntPtr[]>() };
- yield return new[] { ID(), codeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers<UIntPtr[]>() };
-
- CustomCollectionMarshallingCodeSnippets customCollectionMarshallingCodeSnippetsBidirectional = new(new CodeSnippets.Bidirectional(GetAttributeProvider(generator)));
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<byte>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<sbyte>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<short>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<ushort>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<int>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<uint>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<long>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<ulong>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<float>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<double>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<IntPtr>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.DefaultMarshallerParametersAndModifiers<UIntPtr>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<byte>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<sbyte>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<short>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<ushort>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<int>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<uint>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<long>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<ulong>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<float>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<double>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<IntPtr>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerParametersAndModifiers<UIntPtr>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomMarshallerReturnValueLength<int>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.NestedMarshallerParametersAndModifiers<int>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.NonBlittableElementParametersAndModifiers };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateless.CustomElementMarshalling };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<byte>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<sbyte>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<short>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<ushort>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<int>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<uint>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<long>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<ulong>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<float>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<double>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<IntPtr>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.DefaultMarshallerParametersAndModifiers<UIntPtr>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<byte>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<sbyte>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<short>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<ushort>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<int>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<uint>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<long>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<ulong>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<float>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<double>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<IntPtr>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerParametersAndModifiers<UIntPtr>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomMarshallerReturnValueLength<int>() };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.NonBlittableElementParametersAndModifiers };
- yield return new[] { ID(), customCollectionMarshallingCodeSnippetsBidirectional.Stateful.CustomElementMarshalling };
}
[Theory]
[MemberData(nameof(CodeSnippetsToCompile), GeneratorKind.VTableIndexStubGenerator)]
+ [MemberData(nameof(ManagedToUnmanagedCodeSnippetsToCompile), GeneratorKind.VTableIndexStubGenerator)]
+ [MemberData(nameof(UnmanagedToManagedCodeSnippetsToCompile), GeneratorKind.VTableIndexStubGenerator)]
+ [MemberData(nameof(CustomCollectionsManagedToUnmanaged), GeneratorKind.VTableIndexStubGenerator)]
+ [MemberData(nameof(CustomCollections), GeneratorKind.VTableIndexStubGenerator)]
[MemberData(nameof(CustomCollections), GeneratorKind.VTableIndexStubGenerator)]
public async Task ValidateVTableIndexSnippets(string id, string source)
{
_ = id;
- Compilation comp = await TestUtils.CreateCompilation(source);
- // Allow the Native nested type name to be missing in the pre-source-generator compilation
- // We allow duplicate usings here since some of the shared snippets add a using for System.Runtime.InteropServices.Marshalling when we already have one in our base snippets.
- TestUtils.AssertPreSourceGeneratorCompilation(comp, "CS0426", "CS0105");
-
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.VtableIndexStubGenerator());
- Assert.Empty(generatorDiags);
-
- TestUtils.AssertPostSourceGeneratorCompilation(newComp, "CS0105");
+ await VerifyVTableGenerator.VerifySourceGeneratorWithAncillaryInteropAsync(source);
}
public static IEnumerable<object[]> ComInterfaceSnippetsToCompile()
public async Task ValidateComInterfaceSnippets(string id, string source)
{
_ = id;
- Compilation comp = await TestUtils.CreateCompilation(source);
- // Allow the Native nested type name to be missing in the pre-source-generator compilation
- // We allow duplicate usings here since some of the shared snippets add a using for System.Runtime.InteropServices.Marshalling when we already have one in our base snippets.
- TestUtils.AssertPreSourceGeneratorCompilation(comp, "CS0426", "CS0105");
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.ComInterfaceGenerator());
- Assert.Empty(generatorDiags.Where(IsValidGeneratorDiagnostic));
-
- List<string> allowedDiagnostics = new()
- {
- // Duplicate 'using'
- "CS0105",
- // Variable assigned to but never read
- "CS0219"
- };
- // There are valid warnings from the generator --
- if (generatorDiags.Length != 0)
- {
- List<string> additionalDiags = new() {
- // No overload for 'ABI_Method' matches function pointer 'delegate* unmanaged<...>'
- "CS8757",
- // Cannot use 'parameterType' as a parameter type on a method attributed with 'UnmanagedCallersOnly'.
- "CS8894",
- // The out parameter 'paramName' must be assigned to before control leaves the current method
- "CS0177",
- // Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
- "CS8977",
- // The type 'SafeFileHandle' must be a non-nullable value type, along with all fields at any level of nesting,
- // in order to use it as parameter 'T' in the generic type or method 'ExceptionAsDefaultMarshaller<T>'
- "CS8377",
- // Argument N may not be passed with the 'in' keyword
- "CS1615"
- };
- allowedDiagnostics.AddRange(additionalDiags);
- }
-
- TestUtils.AssertPostSourceGeneratorCompilation(newComp, allowedDiagnostics.ToArray());
+ await VerifyComInterfaceGenerator.VerifySourceGeneratorAsync(source);
}
-
- private bool IsValidGeneratorDiagnostic(Diagnostic diag)
- => diag.Id != "SYSLIB1051"
- && diag.GetMessage().Contains("The specified parameter needs to be marshalled from managed to unmanaged, but the marshaller type '")
- && diag.GetMessage().Contains("' does not support it. The generated source will not handle marshalling of parameter");
}
}
using Microsoft.Interop.Analyzers;
using Xunit;
-using VerifyCS = LibraryImportGenerator.UnitTests.Verifiers.CSharpAnalyzerVerifier<Microsoft.Interop.Analyzers.GeneratedComInterfaceAttributeAnalyzer>;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpAnalyzerVerifier<Microsoft.Interop.Analyzers.GeneratedComInterfaceAttributeAnalyzer>;
namespace ComInterfaceGenerator.Unit.Tests
{
partial interface INativeAPI
{
{{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
- void Method({{typeName}} value);
+ void Method({{typeName}} {|#0:value|});
}
{{AttributeProvider.AdditionalUserRequiredInterfaces("INativeAPI")}}
""";
partial interface INativeAPI
{
{{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
- void Method({{modifier}} {{typeName}} value);
+ void Method({{modifier}} {{typeName}} {|#0:value|});
}
{{AttributeProvider.AdditionalUserRequiredInterfaces("INativeAPI")}}
""";
partial interface INativeAPI
{
{{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
- {{typeName}} Method();
+ {{typeName}} {|#0:Method|}();
}
{{AttributeProvider.AdditionalUserRequiredInterfaces("INativeAPI")}}
""";
public string GenericCollectionMarshallingArityMismatch => _provider.BasicParameterByValue("TestCollection<int>", DisableRuntimeMarshalling)
+ """
- [NativeMarshalling(typeof(Marshaller<,,>))]
+ [{|#10:NativeMarshalling(typeof(Marshaller<,,>))|}]
class TestCollection<T> {}
[CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,,>))]
private static readonly string UsingSystemRuntimeInteropServicesMarshalling = "using System.Runtime.InteropServices.Marshalling;";
public static string NonBlittableUserDefinedType(bool defineNativeMarshalling = true) => $$"""
- {{(defineNativeMarshalling ? "[NativeMarshalling(typeof(Marshaller))]" : string.Empty)}}
+ {{(defineNativeMarshalling ? "[{|#10:NativeMarshalling(typeof(Marshaller))|}]" : string.Empty)}}
public struct S
{
#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value
+ NonBlittableUserDefinedType()
+ Ref;
- public string StackallocOnlyRefParameter => _provider.BasicParameterWithByRefModifier("ref", "S")
- + NonBlittableUserDefinedType()
- + InOutBuffer;
+ public string StackallocOnlyRefParameter => _provider.BasicParameterWithByRefModifier("ref", "S")
+ + NonBlittableUserDefinedType()
+ + InOutBuffer;
public string OptionalStackallocParametersAndModifiers => _provider.BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling)
+ NonBlittableUserDefinedType()
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Testing;
-using Microsoft.DotNet.XUnitExtensions;
-using SourceGenerators.Tests;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Testing;
-namespace LibraryImportGenerator.UnitTests.Verifiers
+namespace Microsoft.Interop.UnitTests.Verifiers
{
public static class CSharpAnalyzerVerifier<TAnalyzer>
where TAnalyzer : DiagnosticAnalyzer, new()
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Testing;
using Microsoft.CodeAnalysis.Testing.Verifiers;
-using Microsoft.Interop.UnitTests;
-namespace LibraryImportGenerator.UnitTests.Verifiers
+namespace Microsoft.Interop.UnitTests.Verifiers
{
public static class CSharpCodeFixVerifier<TAnalyzer, TCodeFix>
where TAnalyzer : DiagnosticAnalyzer, new()
TestState.AdditionalReferences.AddRange(SourceGenerators.Tests.LiveReferencePack.GetMetadataReferences());
TestState.AdditionalReferences.Add(TestUtils.GetAncillaryReference());
- SolutionTransforms.Add((solution, projectId) =>
- {
- var project = solution.GetProject(projectId)!;
- var compilationOptions = project.CompilationOptions!;
- var diagnosticOptions = compilationOptions.SpecificDiagnosticOptions.SetItems(CSharpVerifierHelper.NullableWarnings);
-
- // Explicitly enable diagnostics that are not enabled by default
- var enableAnalyzersOptions = new System.Collections.Generic.Dictionary<string, ReportDiagnostic>();
- foreach (var analyzer in GetDiagnosticAnalyzers().ToImmutableArray())
- {
- foreach (var diagnostic in analyzer.SupportedDiagnostics)
- {
- if (diagnostic.IsEnabledByDefault)
- continue;
-
- // Map the default severity to the reporting behaviour.
- // We cannot simply use ReportDiagnostic.Default here, as diagnostics that are not enabled by default
- // are treated as suppressed (regardless of their default severity).
- var report = diagnostic.DefaultSeverity switch
- {
- DiagnosticSeverity.Error => ReportDiagnostic.Error,
- DiagnosticSeverity.Warning => ReportDiagnostic.Warn,
- DiagnosticSeverity.Info => ReportDiagnostic.Info,
- DiagnosticSeverity.Hidden => ReportDiagnostic.Hidden,
- _ => ReportDiagnostic.Default
- };
- enableAnalyzersOptions.Add(diagnostic.Id, report);
- }
- }
-
- compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(
- compilationOptions.SpecificDiagnosticOptions
- .SetItems(CSharpVerifierHelper.NullableWarnings)
- .AddRange(enableAnalyzersOptions)
- .AddRange(TestUtils.BindingRedirectWarnings));
- solution = solution.WithProjectCompilationOptions(projectId, compilationOptions);
- solution = solution.WithProjectParseOptions(projectId, ((CSharpParseOptions)project.ParseOptions!).WithLanguageVersion(LanguageVersion.Preview));
- return solution;
- });
+ SolutionTransforms.Add(CSharpVerifierHelper.GetAllDiagonsticsEnabledTransform(GetDiagnosticAnalyzers()));
}
protected override CompilationWithAnalyzers CreateCompilationWithAnalyzers(Compilation compilation, ImmutableArray<DiagnosticAnalyzer> analyzers, AnalyzerOptions options, CancellationToken cancellationToken)
return true;
}));
}
+
+ protected override ParseOptions CreateParseOptions()
+ {
+ return new CSharpParseOptions(LanguageVersion.Preview, DocumentationMode.Diagnose);
+ }
}
}
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Testing;
+using Microsoft.CodeAnalysis.CSharp.Testing.XUnit;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Testing;
+using Microsoft.CodeAnalysis.Testing.Verifiers;
+
+namespace Microsoft.Interop.UnitTests.Verifiers
+{
+ public static class CSharpSourceGeneratorVerifier<TSourceGenerator>
+ where TSourceGenerator : IIncrementalGenerator, new()
+ {
+ public static DiagnosticResult Diagnostic(string diagnosticId)
+ => new DiagnosticResult(diagnosticId, DiagnosticSeverity.Error);
+
+ public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor)
+ => new DiagnosticResult(descriptor);
+
+ /// <summary>
+ /// Create a <see cref="DiagnosticResult"/> with the diagnostic message created with the provided arguments.
+ /// A <see cref="DiagnosticResult"/> with the <see cref="DiagnosticResult.Message"/> property set instead of just the <see cref="DiagnosticResult.MessageArguments"/> property
+ /// binds more strongly to the "correct" diagnostic as the test harness will match the diagnostic on the exact message instead of just on the message arguments.
+ /// </summary>
+ /// <param name="descriptor">The diagnostic descriptor</param>
+ /// <param name="arguments">The arguments to use to format the diagnostic message</param>
+ /// <returns>A <see cref="DiagnosticResult"/> with a <see cref="DiagnosticResult.Message"/> set with the <paramref name="descriptor"/>'s message format and the <paramref name="arguments"/>.</returns>
+ public static DiagnosticResult DiagnosticWithArguments(DiagnosticDescriptor descriptor, params object[] arguments)
+ {
+ // Generate the specific message here to ensure a stronger match with the correct diagnostic.
+ return Diagnostic(descriptor).WithMessage(string.Format(descriptor.MessageFormat.ToString(), arguments)).WithArguments(arguments);
+ }
+
+ public static async Task VerifySourceGeneratorAsync(string source, params DiagnosticResult[] expected)
+ {
+ var test = new Test(referenceAncillaryInterop: false)
+ {
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
+
+ test.ExpectedDiagnostics.AddRange(expected);
+ await test.RunAsync(CancellationToken.None);
+ }
+
+ public static async Task VerifySourceGeneratorWithAncillaryInteropAsync(string source, params DiagnosticResult[] expected)
+ {
+ var test = new Test(referenceAncillaryInterop: true)
+ {
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
+
+ test.ExpectedDiagnostics.AddRange(expected);
+ await test.RunAsync(CancellationToken.None);
+ }
+
+ public static async Task VerifySourceGeneratorAsync(string[] sources, params DiagnosticResult[] expected)
+ {
+ var test = new Test(referenceAncillaryInterop: false)
+ {
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
+
+ foreach (var source in sources)
+ {
+ test.TestState.Sources.Add(source);
+ }
+
+ test.ExpectedDiagnostics.AddRange(expected);
+ await test.RunAsync(CancellationToken.None);
+ }
+
+ internal class Test : CSharpSourceGeneratorTest<TSourceGenerator, XUnitVerifier>
+ {
+ public Test(TestTargetFramework targetFramework)
+ {
+ if (targetFramework == TestTargetFramework.Net)
+ {
+ // Clear out the default reference assemblies. We explicitly add references from the live ref pack,
+ // so we don't want the Roslyn test infrastructure to resolve/add any default reference assemblies
+ ReferenceAssemblies = new ReferenceAssemblies(string.Empty);
+ TestState.AdditionalReferences.AddRange(SourceGenerators.Tests.LiveReferencePack.GetMetadataReferences());
+ }
+ else
+ {
+ ReferenceAssemblies = targetFramework switch
+ {
+ TestTargetFramework.Framework => ReferenceAssemblies.NetFramework.Net48.Default,
+ TestTargetFramework.Standard => ReferenceAssemblies.NetStandard.NetStandard21,
+ TestTargetFramework.Core => ReferenceAssemblies.NetCore.NetCoreApp31,
+ TestTargetFramework.Net6 => ReferenceAssemblies.Net.Net60,
+ _ => ReferenceAssemblies.Default
+ };
+ }
+ SolutionTransforms.Add(CSharpVerifierHelper.GetTargetFrameworkAnalyzerOptionsProviderTransform(targetFramework));
+ }
+ public Test(bool referenceAncillaryInterop)
+ :this(TestTargetFramework.Net)
+ {
+ if (referenceAncillaryInterop)
+ {
+ TestState.AdditionalReferences.Add(TestUtils.GetAncillaryReference());
+ }
+
+ SolutionTransforms.Add(CSharpVerifierHelper.GetAllDiagonsticsEnabledTransform(GetDiagnosticAnalyzers()));
+ }
+
+ protected override CompilationWithAnalyzers CreateCompilationWithAnalyzers(Compilation compilation, ImmutableArray<DiagnosticAnalyzer> analyzers, AnalyzerOptions options, CancellationToken cancellationToken)
+ {
+ return new CompilationWithAnalyzers(
+ compilation,
+ analyzers,
+ new CompilationWithAnalyzersOptions(
+ options,
+ onAnalyzerException: null,
+ concurrentAnalysis: !Debugger.IsAttached,
+ logAnalyzerExecutionTime: true,
+ reportSuppressedDiagnostics: false,
+ analyzerExceptionFilter: ex =>
+ {
+ // We're hunting down a intermittent issue that causes NullReferenceExceptions deep in Roslyn. To ensure that we get an actionable dump, we're going to FailFast here to force a process dump.
+ if (ex is NullReferenceException)
+ {
+ // Break a debugger here so there's a chance to investigate if someone is already attached.
+ if (System.Diagnostics.Debugger.IsAttached)
+ {
+ System.Diagnostics.Debugger.Break();
+ }
+ Environment.FailFast($"Encountered a NullReferenceException while running an analyzer. Taking the process down to get an actionable crash dump. Exception information:{ex.ToString()}");
+ }
+ return true;
+ }));
+ }
+
+ protected override ParseOptions CreateParseOptions()
+ {
+ return new CSharpParseOptions(LanguageVersion.Preview, DocumentationMode.Diagnose);
+ }
+
+ protected async override Task<(Compilation compilation, ImmutableArray<Diagnostic> generatorDiagnostics)> GetProjectCompilationAsync(Project project, IVerifier verifier, CancellationToken cancellationToken)
+ {
+ var (compilation, diagnostics) = await base.GetProjectCompilationAsync(project, verifier, cancellationToken);
+ VerifyFinalCompilation(compilation);
+ return (compilation, diagnostics);
+ }
+
+ /// <summary>
+ /// Verify any expected invariants on the final compilation after the source generators have been applied.
+ /// </summary>
+ /// <param name="compilation">The compilation.</param>
+ /// <remarks>
+ /// This function is useful for basic semantic testing of the generated code and can be used instead of verification testing of an exact match to the expected source output.
+ /// </remarks>
+ protected virtual void VerifyFinalCompilation(Compilation compilation)
+ {
+ }
+ }
+ }
+}
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Testing;
+using Microsoft.CodeAnalysis.Text;
-namespace LibraryImportGenerator.UnitTests.Verifiers
+namespace Microsoft.Interop.UnitTests.Verifiers
{
internal static class CSharpVerifierHelper
{
var commandLineArguments = CSharpCommandLineParser.Default.Parse(args, baseDirectory: Environment.CurrentDirectory, sdkDirectory: Environment.CurrentDirectory);
return commandLineArguments.CompilationOptions.SpecificDiagnosticOptions;
}
+
+ internal static Func<Solution, ProjectId, Solution> GetAllDiagonsticsEnabledTransform(IEnumerable<DiagnosticAnalyzer> analyzers)
+ {
+ return (solution, projectId) =>
+ {
+ var project = solution.GetProject(projectId)!;
+ var compilationOptions = project.CompilationOptions!;
+ var diagnosticOptions = compilationOptions.SpecificDiagnosticOptions.SetItems(NullableWarnings);
+
+ // Explicitly enable diagnostics that are not enabled by default
+ var enableAnalyzersOptions = new Dictionary<string, ReportDiagnostic>();
+ foreach (var analyzer in analyzers)
+ {
+ foreach (var diagnostic in analyzer.SupportedDiagnostics)
+ {
+ if (diagnostic.IsEnabledByDefault)
+ continue;
+
+ // Map the default severity to the reporting behaviour.
+ // We cannot simply use ReportDiagnostic.Default here, as diagnostics that are not enabled by default
+ // are treated as suppressed (regardless of their default severity).
+ var report = diagnostic.DefaultSeverity switch
+ {
+ DiagnosticSeverity.Error => ReportDiagnostic.Error,
+ DiagnosticSeverity.Warning => ReportDiagnostic.Warn,
+ DiagnosticSeverity.Info => ReportDiagnostic.Info,
+ DiagnosticSeverity.Hidden => ReportDiagnostic.Hidden,
+ _ => ReportDiagnostic.Default
+ };
+ enableAnalyzersOptions.Add(diagnostic.Id, report);
+ }
+ }
+
+ compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(
+ compilationOptions.SpecificDiagnosticOptions
+ .SetItems(NullableWarnings)
+ .AddRange(enableAnalyzersOptions)
+ .AddRange(TestUtils.BindingRedirectWarnings));
+ solution = solution.WithProjectCompilationOptions(projectId, compilationOptions);
+ return solution;
+ };
+ }
+
+ internal static Func<Solution, ProjectId, Solution> GetTargetFrameworkAnalyzerOptionsProviderTransform(TestTargetFramework targetFramework)
+ {
+ return (solution, projectId) =>
+ {
+ var project = solution.GetProject(projectId)!;
+ string tfmEditorConfig = targetFramework switch
+ {
+ TestTargetFramework.Framework => """
+ is_global = true
+ build_property.TargetFrameworkIdentifier = .NETFramework
+ build_property.TargetFrameworkVersion = v4.8
+ """,
+ TestTargetFramework.Standard => """
+ is_global = true
+ build_property.TargetFrameworkIdentifier = .NETStandard
+ build_property.TargetFrameworkVersion = v2.0
+ """,
+ TestTargetFramework.Core => """
+ is_global = true
+ build_property.TargetFrameworkIdentifier = .NETCoreApp
+ build_property.TargetFrameworkVersion = v3.1
+ """,
+ TestTargetFramework.Net6 => """
+ is_global = true
+ build_property.TargetFrameworkIdentifier = .NETCoreApp
+ build_property.TargetFrameworkVersion = v6.0
+ """,
+ // Replicate the product case where we don't have these properties
+ // since we don't have a good mechanism to ship MSBuild files from dotnet/runtime
+ // in the SDK.
+ TestTargetFramework.Net => string.Empty,
+ _ => throw new System.Diagnostics.UnreachableException()
+ };
+ return solution.AddAnalyzerConfigDocument(
+ DocumentId.CreateNewId(projectId),
+ "TargetFrameworkConfig.editorconfig",
+ SourceText.From(tfmEditorConfig, encoding: System.Text.Encoding.UTF8),
+ filePath: "/TargetFrameworkConfig.editorconfig");
+ };
+ }
}
}
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
-using System.Linq;
-using System.Text;
-using System.Threading;
using System.Threading.Tasks;
-using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Testing;
-using Microsoft.CodeAnalysis.CSharp.Testing;
-using Microsoft.CodeAnalysis.Diagnostics;
-using Microsoft.CodeAnalysis.Testing.Model;
-using Microsoft.CodeAnalysis.Testing.Verifiers;
-using Microsoft.Interop.Analyzers;
-using Microsoft.CodeAnalysis.CSharp;
using Microsoft.Interop;
-
-using VerifyCS = LibraryImportGenerator.UnitTests.Verifiers.CSharpCodeFixVerifier<
- LibraryImportGenerator.UnitTests.AddDisableRuntimeMarshallingAttributeFixerTests.MockAnalyzer,
- Microsoft.Interop.Analyzers.AddDisableRuntimeMarshallingAttributeFixer>;
using Xunit;
using System.IO;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpCodeFixVerifier<
+ Microsoft.CodeAnalysis.Testing.EmptyDiagnosticAnalyzer,
+ Microsoft.Interop.Analyzers.AddDisableRuntimeMarshallingAttributeFixer>;
+
namespace LibraryImportGenerator.UnitTests
{
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/60650", TestRuntimes.Mono)]
public class AddDisableRuntimeMarshallingAttributeFixerTests
{
[Fact]
partial class Foo
{
[LibraryImport("Foo")]
- public static partial void {|CS8795:PInvoke|}(S {|#0:s|});
+ public static partial void PInvoke(S {|#0:s|});
}
[NativeMarshalling(typeof(Marshaller))]
struct Native
{
+ public bool b;
}
[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))]
""";
var expectedPropertiesFile = "[assembly: System.Runtime.CompilerServices.DisableRuntimeMarshalling]" + Environment.NewLine;
- var diagnostic = VerifyCS.Diagnostic(GeneratorDiagnostics.Ids.TypeNotSupported).WithLocation(0).WithArguments("S", "s");
+ var diagnostic = VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "s");
await VerifyCodeFixAsync(source, propertiesFile: null, expectedPropertiesFile, diagnostic);
}
partial class Foo
{
[LibraryImport("Foo")]
- public static partial void {|CS8795:PInvoke|}(S {|#0:s|});
+ public static partial void PInvoke(S {|#0:s|});
}
[NativeMarshalling(typeof(Marshaller))]
struct Native
{
+ public bool b;
}
[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))]
""";
- var diagnostic = VerifyCS.Diagnostic(GeneratorDiagnostics.Ids.TypeNotSupported).WithLocation(0).WithArguments("S", "s");
+ var diagnostic = VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "s");
await VerifyCodeFixAsync(source, propertiesFile, expectedPropertiesFile, diagnostic);
}
private static async Task VerifyCodeFixAsync(string source, string? propertiesFile, string? expectedPropertiesFile, DiagnosticResult diagnostic)
{
- var test = new Test();
- // We don't care about validating the settings for the MockAnalyzer and we're also hitting failures on Mono
- // with this check in this case, so skip the check for now.
- test.TestBehaviors = TestBehaviors.SkipGeneratedCodeCheck;
- test.TestCode = source;
- test.FixedCode = source;
- test.BatchFixedCode = source;
+ var test = new Test
+ {
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck,
+ TestCode = source,
+ FixedCode = source,
+ BatchFixedCode = source
+ };
test.ExpectedDiagnostics.Add(diagnostic);
if (propertiesFile is not null)
{
class Test : VerifyCS.Test
{
+ private static readonly ImmutableArray<Type> GeneratorTypes = ImmutableArray.Create(typeof(Microsoft.Interop.LibraryImportGenerator));
+
public const string FilePathPrefix = "/Project/";
protected override string DefaultFilePathPrefix => FilePathPrefix;
- }
-
- // The Roslyn SDK doesn't provide a good test harness for testing a code fix that triggers
- // on a source-generator-introduced diagnostic. This analyzer does a decent enough job of triggering
- // the specific diagnostic in the right place for us to test the code fix.
- [DiagnosticAnalyzer(LanguageNames.CSharp)]
- public class MockAnalyzer : DiagnosticAnalyzer
- {
- private static readonly DiagnosticDescriptor AddDisableRuntimeMarshallingAttributeRule = GeneratorDiagnostics.ParameterTypeNotSupported;
- public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(AddDisableRuntimeMarshallingAttributeRule);
-
- public override void Initialize(AnalysisContext context)
+ protected override IEnumerable<Type> GetSourceGenerators()
{
- context.EnableConcurrentExecution();
- context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
- context.RegisterSymbolAction(context =>
- {
- var symbol = (IParameterSymbol)context.Symbol;
-
- if (context.Symbol.ContainingAssembly.GetAttributes().Any(attr => attr.AttributeClass!.ToDisplayString() == TypeNames.System_Runtime_CompilerServices_DisableRuntimeMarshallingAttribute))
- {
- return;
- }
-
- if (symbol.ContainingSymbol is IMethodSymbol { IsStatic: true, IsPartialDefinition: true })
- {
- context.ReportDiagnostic(context.Symbol.CreateDiagnostic(
- AddDisableRuntimeMarshallingAttributeRule,
- ImmutableDictionary<string, string>.Empty
- .Add(
- GeneratorDiagnosticProperties.AddDisableRuntimeMarshallingAttribute,
- GeneratorDiagnosticProperties.AddDisableRuntimeMarshallingAttribute),
- symbol.Type.ToDisplayString(), symbol.Name));
- }
- }, SymbolKind.Parameter);
+ return GeneratorTypes;
}
}
}
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Testing;
using Microsoft.Interop.UnitTests;
-using SourceGenerators.Tests;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Xunit;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier<Microsoft.Interop.LibraryImportGenerator>;
+
namespace LibraryImportGenerator.UnitTests
{
public class AdditionalAttributesOnStub
public static S ConvertToManaged(Native n) => default;
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
-
- 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");
- Assert.Contains(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == typeof(SkipLocalsInitAttribute).FullName);
+ await VerifySourceGeneratorAsync(source, "C", "Method", typeof(SkipLocalsInitAttribute).FullName, attributeAdded: true, TestTargetFramework.Net);
}
[Fact]
public static partial void Method();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
-
- 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");
- Assert.DoesNotContain(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == typeof(SkipLocalsInitAttribute).FullName);
+ await VerifySourceGeneratorAsync(source, "C", "Method", typeof(SkipLocalsInitAttribute).FullName, attributeAdded: false, TestTargetFramework.Net);
}
[Fact]
public static S ConvertToManaged(Native n) => default;
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
-
- 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");
- Assert.Contains(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == typeof(System.CodeDom.Compiler.GeneratedCodeAttribute).FullName);
+ await VerifySourceGeneratorAsync(source, "C", "Method", typeof(System.CodeDom.Compiler.GeneratedCodeAttribute).FullName, attributeAdded: true, TestTargetFramework.Net);
}
[Fact]
public static partial void Method();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
-
- 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");
- Assert.DoesNotContain(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == typeof(System.CodeDom.Compiler.GeneratedCodeAttribute).FullName);
+ await VerifySourceGeneratorAsync(source, "C", "Method", typeof(System.CodeDom.Compiler.GeneratedCodeAttribute).FullName, attributeAdded: false, TestTargetFramework.Net);
}
public static IEnumerable<object[]> GetDownlevelTargetFrameworks()
public static partial bool Method();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source, targetFramework);
-
- Compilation newComp = TestUtils.RunGenerators(comp, new GlobalOptionsOnlyProvider(new TargetFrameworkConfigOptions(targetFramework)), 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);
- }
+ await VerifySourceGeneratorAsync(source, "C", "Method", typeof(SkipLocalsInitAttribute).FullName, attributeAdded: expectSkipLocalsInit, targetFramework);
}
[Fact]
public static S ConvertToManaged(Native n) => default;
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
-
- 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");
- Assert.DoesNotContain(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == typeof(SkipLocalsInitAttribute).FullName);
+ await VerifySourceGeneratorAsync(source, "C", "Method", typeof(SkipLocalsInitAttribute).FullName, attributeAdded: false, TestTargetFramework.Net);
}
[Fact]
public static S ConvertToManaged(Native n) => default;
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
-
- 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");
- Assert.DoesNotContain(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == typeof(SkipLocalsInitAttribute).FullName);
+ await VerifySourceGeneratorAsync(source, "C", "Method", typeof(SkipLocalsInitAttribute).FullName, attributeAdded: false, TestTargetFramework.Net);
}
[Fact]
public static S ConvertToManaged(Native n) => default;
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
+ // Verify that we get no diagnostics from applying the attribute twice.
+ await VerifyCS.VerifySourceGeneratorAsync(source);
+ }
- Compilation newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.LibraryImportGenerator());
+ private static Task VerifySourceGeneratorAsync(string source, string typeName, string methodName, string? attributeName, bool attributeAdded, TestTargetFramework targetFramework)
+ {
+ AttributeAddedTest test = new(typeName, methodName, attributeName, attributeAdded, targetFramework)
+ {
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
+ return test.RunAsync();
+ }
+
+ class AttributeAddedTest : VerifyCS.Test
+ {
+ private readonly string _typeName;
+ private readonly string _methodName;
+ private readonly string? _attributeName;
+ private readonly bool _expectSkipLocalsInit;
- ITypeSymbol c = newComp.GetTypeByMetadataName("C")!;
- IMethodSymbol stubMethod = c.GetMembers().OfType<IMethodSymbol>().Single(m => m.Name == "Method");
- Assert.DoesNotContain(newComp.GetDiagnostics(), d => d.Id != "CS0579"); // No duplicate attribute error
+ public AttributeAddedTest(string typeName, string methodName, string? attributeName, bool expectSkipLocalsInitOnMethod, TestTargetFramework targetFramework)
+ : base(targetFramework)
+ {
+ _typeName = typeName;
+ _methodName = methodName;
+ _attributeName = attributeName;
+ _expectSkipLocalsInit = expectSkipLocalsInitOnMethod;
+ }
+
+ protected override void VerifyFinalCompilation(Compilation compilation)
+ {
+ ITypeSymbol c = compilation.GetTypeByMetadataName(_typeName)!;
+ IMethodSymbol stubMethod = c.GetMembers().OfType<IMethodSymbol>().Single(m => m.Name == _methodName);
+ if (_expectSkipLocalsInit)
+ {
+ Assert.Contains(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == _attributeName);
+ }
+ else
+ {
+ Assert.DoesNotContain(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == _attributeName);
+ }
+ }
}
}
}
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Testing;
using Microsoft.Interop;
using Microsoft.Interop.UnitTests;
using SourceGenerators.Tests;
using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
using System.Linq;
using System.Runtime.InteropServices;
-using System.Text;
using System.Threading.Tasks;
using Xunit;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier<Microsoft.Interop.LibraryImportGenerator>;
namespace LibraryImportGenerator.UnitTests
{
public static S ConvertToManaged(Native n) => default;
}
""";
- Compilation origComp = await TestUtils.CreateCompilation(source);
- Compilation newComp = TestUtils.RunGenerators(origComp, out _, new Microsoft.Interop.LibraryImportGenerator());
- Assert.Empty(newComp.GetDiagnostics());
- ITypeSymbol attributeType = newComp.GetTypeByMetadataName(attributeMetadataName)!;
-
- Assert.NotNull(attributeType);
-
- IMethodSymbol targetMethod = GetGeneratedPInvokeTargetFromCompilation(newComp);
+ await VerifySourceGeneratorAsync(
+ source,
+ (targetMethod, newComp) =>
+ {
+ ITypeSymbol attributeType = newComp.GetTypeByMetadataName(attributeMetadataName)!;
+ Assert.NotNull(attributeType);
- Assert.Contains(
- targetMethod.GetAttributes(),
- attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType));
+ Assert.Contains(
+ targetMethod.GetAttributes(),
+ attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType));
+ });
}
[Fact]
public static S ConvertToManaged(Native n) => default;
}
""";
- Compilation origComp = await TestUtils.CreateCompilation(source);
- Compilation newComp = TestUtils.RunGenerators(origComp, out _, new Microsoft.Interop.LibraryImportGenerator());
- Assert.Empty(newComp.GetDiagnostics());
-
- ITypeSymbol attributeType = newComp.GetTypeByMetadataName("System.Runtime.InteropServices.UnmanagedCallConvAttribute")!;
-
- Assert.NotNull(attributeType);
-
- IMethodSymbol targetMethod = GetGeneratedPInvokeTargetFromCompilation(newComp);
- Assert.Contains(
- targetMethod.GetAttributes(),
- attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType)
- && attr.NamedArguments.Length == 1
- && attr.NamedArguments[0].Key == "CallConvs"
- && attr.NamedArguments[0].Value.Values.Length == 0);
+ await VerifySourceGeneratorAsync(
+ source,
+ (targetMethod, newComp) =>
+ {
+ ITypeSymbol attributeType = newComp.GetTypeByMetadataName("System.Runtime.InteropServices.UnmanagedCallConvAttribute")!;
+ Assert.NotNull(attributeType);
+
+ Assert.Contains(
+ targetMethod.GetAttributes(),
+ attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType)
+ && attr.NamedArguments.Length == 1
+ && attr.NamedArguments[0].Key == "CallConvs"
+ && attr.NamedArguments[0].Value.Values.Length == 0);
+ });
}
[Fact]
public static S ConvertToManaged(Native n) => default;
}
""";
- Compilation origComp = await TestUtils.CreateCompilation(source);
- Compilation newComp = TestUtils.RunGenerators(origComp, out _, new Microsoft.Interop.LibraryImportGenerator());
- Assert.Empty(newComp.GetDiagnostics());
-
- ITypeSymbol attributeType = newComp.GetTypeByMetadataName("System.Runtime.InteropServices.UnmanagedCallConvAttribute")!;
- ITypeSymbol callConvType = newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvStdcall")!;
-
- Assert.NotNull(attributeType);
-
- IMethodSymbol targetMethod = GetGeneratedPInvokeTargetFromCompilation(newComp);
-
- Assert.Contains(
- targetMethod.GetAttributes(),
- attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType)
- && attr.NamedArguments.Length == 1
- && attr.NamedArguments[0].Key == "CallConvs"
- && attr.NamedArguments[0].Value.Values.Length == 1
- && SymbolEqualityComparer.Default.Equals(
- (INamedTypeSymbol?)attr.NamedArguments[0].Value.Values[0].Value!,
- callConvType));
+
+ await VerifySourceGeneratorAsync(
+ source,
+ (targetMethod, newComp) =>
+ {
+ ITypeSymbol attributeType = newComp.GetTypeByMetadataName("System.Runtime.InteropServices.UnmanagedCallConvAttribute")!;
+ ITypeSymbol callConvType = newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvStdcall")!;
+
+ Assert.NotNull(attributeType);
+
+ Assert.Contains(
+ targetMethod.GetAttributes(),
+ attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType)
+ && attr.NamedArguments.Length == 1
+ && attr.NamedArguments[0].Key == "CallConvs"
+ && attr.NamedArguments[0].Value.Values.Length == 1
+ && SymbolEqualityComparer.Default.Equals(
+ (INamedTypeSymbol?)attr.NamedArguments[0].Value.Values[0].Value!,
+ callConvType));
+ });
}
[Fact]
public static S ConvertToManaged(Native n) => default;
}
""";
- Compilation origComp = await TestUtils.CreateCompilation(source);
- Compilation newComp = TestUtils.RunGenerators(origComp, out _, new Microsoft.Interop.LibraryImportGenerator());
- Assert.Empty(newComp.GetDiagnostics());
-
- ITypeSymbol attributeType = newComp.GetTypeByMetadataName("System.Runtime.InteropServices.UnmanagedCallConvAttribute")!;
- ITypeSymbol callConvType = newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvStdcall")!;
- ITypeSymbol callConvType2 = newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvSuppressGCTransition")!;
-
- Assert.NotNull(attributeType);
-
- IMethodSymbol targetMethod = GetGeneratedPInvokeTargetFromCompilation(newComp);
-
- Assert.Contains(
- targetMethod.GetAttributes(),
- attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType)
- && attr.NamedArguments.Length == 1
- && attr.NamedArguments[0].Key == "CallConvs"
- && attr.NamedArguments[0].Value.Values.Length == 2
- && SymbolEqualityComparer.Default.Equals(
- (INamedTypeSymbol?)attr.NamedArguments[0].Value.Values[0].Value!,
- callConvType)
- && SymbolEqualityComparer.Default.Equals(
- (INamedTypeSymbol?)attr.NamedArguments[0].Value.Values[1].Value!,
- callConvType2));
+
+ await VerifySourceGeneratorAsync(
+ source,
+ (targetMethod, newComp) =>
+ {
+ ITypeSymbol attributeType = newComp.GetTypeByMetadataName("System.Runtime.InteropServices.UnmanagedCallConvAttribute")!;
+ ITypeSymbol callConvType = newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvStdcall")!;
+ ITypeSymbol callConvType2 = newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvSuppressGCTransition")!;
+
+ Assert.NotNull(attributeType);
+
+ Assert.Contains(
+ targetMethod.GetAttributes(),
+ attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType)
+ && attr.NamedArguments.Length == 1
+ && attr.NamedArguments[0].Key == "CallConvs"
+ && attr.NamedArguments[0].Value.Values.Length == 2
+ && SymbolEqualityComparer.Default.Equals(
+ (INamedTypeSymbol?)attr.NamedArguments[0].Value.Values[0].Value!,
+ callConvType)
+ && SymbolEqualityComparer.Default.Equals(
+ (INamedTypeSymbol?)attr.NamedArguments[0].Value.Values[1].Value!,
+ callConvType2));
+ });
}
[Fact]
public static S ConvertToManaged(Native n) => default;
}
""";
- Compilation origComp = await TestUtils.CreateCompilation(source);
- Compilation newComp = TestUtils.RunGenerators(origComp, out _, new Microsoft.Interop.LibraryImportGenerator());
- Assert.Empty(newComp.GetDiagnostics());
-
- ITypeSymbol attributeType = newComp.GetTypeByMetadataName("System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute")!;
- Assert.NotNull(attributeType);
+ await VerifySourceGeneratorAsync(
+ source,
+ (targetMethod, newComp) =>
+ {
+ ITypeSymbol attributeType = newComp.GetTypeByMetadataName("System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute")!;
- IMethodSymbol targetMethod = GetGeneratedPInvokeTargetFromCompilation(newComp);
+ Assert.NotNull(attributeType);
- DllImportSearchPath expected = DllImportSearchPath.System32 | DllImportSearchPath.UserDirectories;
+ DllImportSearchPath expected = DllImportSearchPath.System32 | DllImportSearchPath.UserDirectories;
- Assert.Contains(
- targetMethod.GetAttributes(),
- attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType)
- && attr.ConstructorArguments.Length == 1
- && expected == (DllImportSearchPath)attr.ConstructorArguments[0].Value!);
+ Assert.Contains(
+ targetMethod.GetAttributes(),
+ attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType)
+ && attr.ConstructorArguments.Length == 1
+ && expected == (DllImportSearchPath)attr.ConstructorArguments[0].Value!);
+ });
}
[Fact]
public static S ConvertToManaged(Native n) => default;
}
""";
- Compilation origComp = await TestUtils.CreateCompilation(source);
- Compilation newComp = TestUtils.RunGenerators(origComp, out _, new Microsoft.Interop.LibraryImportGenerator());
-
- Assert.Empty(newComp.GetDiagnostics());
- ITypeSymbol attributeType = newComp.GetTypeByMetadataName("OtherAttribute")!;
+ await VerifySourceGeneratorAsync(
+ source,
+ (targetMethod, newComp) =>
+ {
+ ITypeSymbol attributeType = newComp.GetTypeByMetadataName("OtherAttribute")!;
- Assert.NotNull(attributeType);
+ Assert.NotNull(attributeType);
- IMethodSymbol targetMethod = GetGeneratedPInvokeTargetFromCompilation(newComp);
- Assert.DoesNotContain(
- targetMethod.GetAttributes(),
- attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType));
+ Assert.DoesNotContain(
+ targetMethod.GetAttributes(),
+ attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType));
+ });
}
[Fact]
{
[LibraryImportAttribute("DoesNotExist")]
[return: MarshalAs(UnmanagedType.Bool)]
- public static partial bool Method1([In, Out] int a);
+ public static partial bool Method1([In, Out] int {|SYSLIB1051:a|});
}
""" + CodeSnippets.LibraryImportAttributeDeclaration;
- Compilation origComp = await TestUtils.CreateCompilation(source, TestTargetFramework.Standard);
- Compilation newComp = TestUtils.RunGenerators(
- origComp,
- new GlobalOptionsOnlyProvider(new TargetFrameworkConfigOptions(TestTargetFramework.Standard)),
- out _,
- new Microsoft.Interop.LibraryImportGenerator());
-
- IMethodSymbol targetMethod = GetGeneratedPInvokeTargetFromCompilation(newComp);
-
- INamedTypeSymbol marshalAsAttribute = newComp.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute)!;
- INamedTypeSymbol inAttribute = newComp.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_InAttribute)!;
- INamedTypeSymbol outAttribute = newComp.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_OutAttribute)!;
- Assert.Collection(targetMethod.Parameters,
- param => Assert.Collection(param.GetAttributes(),
- attr =>
- {
- Assert.Equal(inAttribute, attr.AttributeClass, SymbolEqualityComparer.Default);
- Assert.Empty(attr.ConstructorArguments);
- Assert.Empty(attr.NamedArguments);
- },
- attr =>
- {
- Assert.Equal(outAttribute, attr.AttributeClass, SymbolEqualityComparer.Default);
- Assert.Empty(attr.ConstructorArguments);
- Assert.Empty(attr.NamedArguments);
- }));
+
+ await VerifySourceGeneratorAsync(
+ source,
+ (targetMethod, newComp) =>
+ {
+ INamedTypeSymbol marshalAsAttribute = newComp.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute)!;
+ INamedTypeSymbol inAttribute = newComp.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_InAttribute)!;
+ INamedTypeSymbol outAttribute = newComp.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_OutAttribute)!;
+ Assert.Collection(targetMethod.Parameters,
+ param => Assert.Collection(param.GetAttributes(),
+ attr =>
+ {
+ Assert.Equal(inAttribute, attr.AttributeClass, SymbolEqualityComparer.Default);
+ Assert.Empty(attr.ConstructorArguments);
+ Assert.Empty(attr.NamedArguments);
+ },
+ attr =>
+ {
+ Assert.Equal(outAttribute, attr.AttributeClass, SymbolEqualityComparer.Default);
+ Assert.Empty(attr.ConstructorArguments);
+ Assert.Empty(attr.NamedArguments);
+ }));
+ },
+ TestTargetFramework.Standard);
}
[Fact]
public static partial bool Method1([MarshalAs(UnmanagedType.I2)] int a);
}
""" + CodeSnippets.LibraryImportAttributeDeclaration;
- Compilation origComp = await TestUtils.CreateCompilation(source, TestTargetFramework.Standard);
- Compilation newComp = TestUtils.RunGenerators(
- origComp,
- new GlobalOptionsOnlyProvider(new TargetFrameworkConfigOptions(TestTargetFramework.Standard)),
- out _,
- new Microsoft.Interop.LibraryImportGenerator());
-
- IMethodSymbol targetMethod = GetGeneratedPInvokeTargetFromCompilation(newComp);
-
- INamedTypeSymbol marshalAsAttribute = newComp.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute)!;
- Assert.Collection(targetMethod.Parameters,
- param => Assert.Collection(param.GetAttributes(),
- attr =>
- {
- Assert.Equal(marshalAsAttribute, attr.AttributeClass, SymbolEqualityComparer.Default);
- Assert.Equal(UnmanagedType.I2, (UnmanagedType)attr.ConstructorArguments[0].Value!);
- Assert.Empty(attr.NamedArguments);
- }));
+
+ await VerifySourceGeneratorAsync(
+ source,
+ (targetMethod, newComp) =>
+ {
+ INamedTypeSymbol marshalAsAttribute = newComp.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute)!;
+ Assert.Collection(targetMethod.Parameters,
+ param => Assert.Collection(param.GetAttributes(),
+ attr =>
+ {
+ Assert.Equal(marshalAsAttribute, attr.AttributeClass, SymbolEqualityComparer.Default);
+ Assert.Equal(UnmanagedType.I2, (UnmanagedType)attr.ConstructorArguments[0].Value!);
+ Assert.Empty(attr.NamedArguments);
+ }));
+ },
+ TestTargetFramework.Standard);
+ }
+
+ private static Task VerifySourceGeneratorAsync(string source, Action<IMethodSymbol, Compilation> targetPInvokeAssertion, TestTargetFramework targetFramework = TestTargetFramework.Net)
+ {
+ var test = new GeneratedTargetPInvokeTest(targetPInvokeAssertion, targetFramework)
+ {
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
+
+ return test.RunAsync();
}
- private static IMethodSymbol GetGeneratedPInvokeTargetFromCompilation(Compilation newComp)
+ class GeneratedTargetPInvokeTest : VerifyCS.Test
{
- // The last syntax tree is the generated code
- SyntaxTree generatedCode = newComp.SyntaxTrees.Last();
- SemanticModel model = newComp.GetSemanticModel(generatedCode);
-
- var localFunctions = generatedCode.GetRoot()
- .DescendantNodes().OfType<LocalFunctionStatementSyntax>()
- .ToList();
- LocalFunctionStatementSyntax innerDllImport = Assert.Single(localFunctions);
- IMethodSymbol targetMethod = (IMethodSymbol)model.GetDeclaredSymbol(innerDllImport)!;
- return targetMethod;
+ private readonly Action<IMethodSymbol, Compilation> _targetPInvokeAssertion;
+
+ public GeneratedTargetPInvokeTest(Action<IMethodSymbol, Compilation> targetPInvokeAssertion, TestTargetFramework targetFramework)
+ :base(targetFramework)
+ {
+ _targetPInvokeAssertion = targetPInvokeAssertion;
+ }
+
+ private static IMethodSymbol GetGeneratedPInvokeTargetFromCompilation(Compilation compilation)
+ {
+ // The last syntax tree is the generated code
+ SyntaxTree generatedCode = compilation.SyntaxTrees.Last();
+ SemanticModel model = compilation.GetSemanticModel(generatedCode);
+
+ var localFunctions = generatedCode.GetRoot()
+ .DescendantNodes().OfType<LocalFunctionStatementSyntax>()
+ .ToList();
+ LocalFunctionStatementSyntax innerDllImport = Assert.Single(localFunctions);
+ IMethodSymbol targetMethod = (IMethodSymbol)model.GetDeclaredSymbol(innerDllImport)!;
+ return targetMethod;
+ }
+
+ protected override void VerifyFinalCompilation(Compilation compilation)
+ {
+ _targetPInvokeAssertion(GetGeneratedPInvokeTargetFromCompilation(compilation), compilation);
+ }
}
}
}
/// </summary>
public static readonly string TrivialClassDeclarations = """
using System.Runtime.InteropServices;
- partial class Basic
+ partial class {|#0:Basic|}
{
[LibraryImportAttribute("DoesNotExist")]
public static partial void Method1();
using System.Runtime.InteropServices;
partial class Test
{
- [LCIDConversion(0)]
+ [{|#0:LCIDConversion(0)|}]
[LibraryImport("DoesNotExist")]
public static partial void Method();
}
partial class Test
{
[LibraryImport("DoesNotExist")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NS.MyCustomMarshaler), MarshalCookie="COOKIE1")]
- public static partial bool Method1([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NS.MyCustomMarshaler), MarshalCookie="COOKIE2")]bool t);
+ [return: {|#0:MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NS.MyCustomMarshaler), MarshalCookie="COOKIE1")|}]
+ public static partial bool {|#1:Method1|}([{|#2:MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NS.MyCustomMarshaler), MarshalCookie="COOKIE2")|}]bool {|#3:t|});
[LibraryImport("DoesNotExist")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "NS.MyCustomMarshaler", MarshalCookie="COOKIE3")]
- public static partial bool Method2([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "NS.MyCustomMarshaler", MarshalCookie="COOKIE4")]bool t);
+ [return: {|#4:MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "NS.MyCustomMarshaler", MarshalCookie="COOKIE3")|}]
+ public static partial bool {|#5:Method2|}([{|#6:MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "NS.MyCustomMarshaler", MarshalCookie="COOKIE4")|}]bool {|#7:t|});
}
""";
partial class Test
{
[ATTRIBUTELibraryImportAttribute("DoesNotExist")]
- public static partial void Method1();
+ public static partial void {|CS8795:Method1|}();
[ATTRIBUTELibraryImport("DoesNotExist")]
- public static partial void Method2();
+ public static partial void {|CS8795:Method2|}();
[System.Runtime.InteropServices.ATTRIBUTELibraryImport("DoesNotExist")]
- public static partial void Method3();
+ public static partial void {|CS8795:Method3|}();
}
""";
{{preDeclaration}}
partial class Test
{
- [LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.{{value}})]
- public static partial {{typename}} Method(
- {{typename}} p,
- in {{typename}} pIn,
- ref {{typename}} pRef,
- out {{typename}} pOut);
+ [{|#0:LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.{{value}})|}]
+ public static partial {{typename}} {|#1:Method|}(
+ {{typename}} {|#2:p|},
+ in {{typename}} {|#3:pIn|},
+ ref {{typename}} {|#4:pRef|},
+ out {{typename}} {|#5:pOut|});
}
""";
partial class Test
{
[LibraryImport("DoesNotExist", StringMarshallingCustomType = typeof({{stringMarshallingCustomTypeName}}))]
- public static partial {{typeName}} Method(
- {{typeName}} p,
- in {{typeName}} pIn,
- ref {{typeName}} pRef,
- out {{typeName}} pOut);
+ public static partial {{typeName}} {|#0:Method|}(
+ {{typeName}} {|#1:p|},
+ in {{typeName}} {|#2:pIn|},
+ ref {{typeName}} {|#3:pRef|},
+ out {{typeName}} {|#4:pOut|});
}
""";
partial class Test
{
[LibraryImport("DoesNotExist")]
- public static partial {{typeName}} Method(
- {{typeName}} p,
- in {{typeName}} pIn,
- ref {{typeName}} pRef,
- out {{typeName}} pOut);
+ public static partial {{typeName}} {|#0:Method|}(
+ {{typeName}} {|#1:p|},
+ in {{typeName}} {|#2:pIn|},
+ ref {{typeName}} {|#3:pRef|},
+ out {{typeName}} {|#4:pOut|});
}
""";
partial class Test
{
[LibraryImport("DoesNotExist")]
- public static partial {{typeName}} Method(
- {{typeName}} p,
- in {{typeName}} pIn,
- out {{typeName}} pOut);
+ public static partial {{typeName}} {|#0:Method|}(
+ {{typeName}} {|#1:p|},
+ in {{typeName}} {|#2:pIn|},
+ out {{typeName}} {|#4:pOut|});
}
""";
partial class Test
{
[LibraryImport("DoesNotExist")]
- public static unsafe partial {{typeName}} Method(
- {{typeName}} p,
- in {{typeName}} pIn,
- ref {{typeName}} pRef,
- out {{typeName}} pOut);
+ public static unsafe partial {{typeName}} {|#0:Method|}(
+ {{typeName}} {|#1:p|},
+ in {{typeName}} {|#2:pIn|},
+ ref {{typeName}} {|#3:pRef|},
+ out {{typeName}} {|#4:pOut|});
}
""";
{
[LibraryImport("DoesNotExist")]
public static partial void Method(
- [{{attributeName}}] {{typeName}} p);
+ [{{attributeName}}] {{typeName}} {|#0:p|});
}
""";
partial class Test
{
[LibraryImport("DoesNotExist")]
- [return: MarshalAs(UnmanagedType.{{unmanagedType}})]
- public static partial {{typeName}} Method(
- [MarshalAs(UnmanagedType.{{unmanagedType}})] {{typeName}} p,
- [MarshalAs(UnmanagedType.{{unmanagedType}})] in {{typeName}} pIn,
- [MarshalAs(UnmanagedType.{{unmanagedType}})] ref {{typeName}} pRef,
- [MarshalAs(UnmanagedType.{{unmanagedType}})] out {{typeName}} pOut);
+ [return: {|#10:MarshalAs(UnmanagedType.{{unmanagedType}})|}]
+ public static partial {{typeName}} {|#0:Method|}(
+ [{|#11:MarshalAs(UnmanagedType.{{unmanagedType}})|}] {{typeName}} {|#1:p|},
+ [{|#12:MarshalAs(UnmanagedType.{{unmanagedType}})|}] in {{typeName}} {|#2:pIn|},
+ [{|#13:MarshalAs(UnmanagedType.{{unmanagedType}})|}] ref {{typeName}} {|#3:pRef|},
+ [{|#14:MarshalAs(UnmanagedType.{{unmanagedType}})|}] out {{typeName}} {|#4:pOut|});
}
""";
{
[LibraryImport("DoesNotExist")]
[return: MarshalAs(UnmanagedType.{{unmanagedType}})]
- public static unsafe partial {{typeName}} Method(
- [MarshalAs(UnmanagedType.{{unmanagedType}})] {{typeName}} p,
- [MarshalAs(UnmanagedType.{{unmanagedType}})] in {{typeName}} pIn,
- [MarshalAs(UnmanagedType.{{unmanagedType}})] ref {{typeName}} pRef,
- [MarshalAs(UnmanagedType.{{unmanagedType}})] out {{typeName}} pOut);
+ public static unsafe partial {{typeName}} {|#0:Method|}(
+ [MarshalAs(UnmanagedType.{{unmanagedType}})] {{typeName}} {|#1:p|},
+ [MarshalAs(UnmanagedType.{{unmanagedType}})] in {{typeName}} {|#2:pIn|},
+ [MarshalAs(UnmanagedType.{{unmanagedType}})] ref {{typeName}} {|#3:pRef|},
+ [MarshalAs(UnmanagedType.{{unmanagedType}})] out {{typeName}} {|#4:pOut|});
}
""";
{
[LibraryImport("DoesNotExist")]
[return:MarshalAs(UnmanagedType.LPArray, SizeConst=10)]
- public static partial {{elementType}}[] Method(
- {{elementType}}[] p,
- in {{elementType}}[] pIn,
- int pRefSize,
- [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] ref {{elementType}}[] pRef,
- [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=5, SizeConst=4)] out {{elementType}}[] pOut,
- out int pOutSize
+ public static partial {{elementType}}[] {|#0:Method|}(
+ {{elementType}}[] {|#1:p|},
+ in {{elementType}}[] {|#2:pIn|},
+ int {|#3:pRefSize|},
+ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] ref {{elementType}}[] {|#4:pRef|},
+ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=5, SizeConst=4)] out {{elementType}}[] {|#5:pOut|},
+ out int {|#6:pOutSize|}
);
}
""";
{
[LibraryImport("DoesNotExist")]
public static partial void Method(
- {{(isByRef ? "ref" : "")}} {{sizeParamType}} pRefSize,
- [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] ref int[] pRef
+ {{(isByRef ? "ref" : "")}} {{sizeParamType}} {|#0:pRefSize|},
+ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] ref int[] {|#1:pRef|}
);
}
""";
/// <summary>
/// Declaration with parameters with MarshalAs.
/// </summary>
+ //public static string MarshalUsingParametersAndModifiers(string typeName, string nativeTypeName, string preDeclaration = "") => $$"""
+ // using System.Runtime.InteropServices;
+ // using System.Runtime.InteropServices.Marshalling;
+ // {{preDeclaration}}
+ // partial class Test
+ // {
+ // [LibraryImport("DoesNotExist")]
+ // [return: MarshalUsing(typeof({{nativeTypeName}}))]
+ // public static partial {{typeName}} Method(
+ // [MarshalUsing(typeof({{nativeTypeName}}))] {{typeName}} p,
+ // [MarshalUsing(typeof({{nativeTypeName}}))] in {{typeName}} pIn,
+ // [MarshalUsing(typeof({{nativeTypeName}}))] ref {{typeName}} pRef,
+ // [MarshalUsing(typeof({{nativeTypeName}}))] out {{typeName}} pOut);
+ // }
+ // """;
public static string MarshalUsingParametersAndModifiers(string typeName, string nativeTypeName, string preDeclaration = "") => $$"""
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
{
[LibraryImport("DoesNotExist")]
[return: MarshalUsing(typeof({{nativeTypeName}}))]
- public static partial {{typeName}} Method(
- [MarshalUsing(typeof({{nativeTypeName}}))] {{typeName}} p,
- [MarshalUsing(typeof({{nativeTypeName}}))] in {{typeName}} pIn,
- [MarshalUsing(typeof({{nativeTypeName}}))] ref {{typeName}} pRef,
- [MarshalUsing(typeof({{nativeTypeName}}))] out {{typeName}} pOut);
+ public static partial {{typeName}} {|#0:Method|}(
+ [MarshalUsing(typeof({{nativeTypeName}}))] {{typeName}} {|#1:p|},
+ [MarshalUsing(typeof({{nativeTypeName}}))] in {{typeName}} {|#2:pIn|},
+ [MarshalUsing(typeof({{nativeTypeName}}))] ref {{typeName}} {|#3:pRef|},
+ [MarshalUsing(typeof({{nativeTypeName}}))] out {{typeName}} {|#4:pOut|});
}
""";
public static string BasicParameterWithByRefModifier(string byRefKind, string typeName, string preDeclaration = "") => $$"""
{
[LibraryImport("DoesNotExist")]
public static partial void Method(
- {{byRefKind}} {{typeName}} p);
+ {{byRefKind}} {{typeName}} {|#0:p|});
}
""";
{
[LibraryImport("DoesNotExist")]
public static partial void Method(
- {{typeName}} p);
+ {{typeName}} {|#0:p|});
}
""";
partial class Test
{
[LibraryImport("DoesNotExist")]
- public static partial {{typeName}} Method();
+ public static partial {{typeName}} {|#0:Method|}();
}
""";
public static string RecursiveImplicitlyBlittableStruct => BasicParametersAndModifiers("RecursiveStruct", DisableRuntimeMarshalling) + """
struct RecursiveStruct
{
- RecursiveStruct s;
+ RecursiveStruct {|CS0523:s|};
int i;
}
""";
public static string MutuallyRecursiveImplicitlyBlittableStruct => BasicParametersAndModifiers("RecursiveStruct1", DisableRuntimeMarshalling) + """
struct RecursiveStruct1
{
- RecursiveStruct2 s;
+ RecursiveStruct2 {|CS0523:s|};
int i;
}
struct RecursiveStruct2
{
- RecursiveStruct1 s;
+ RecursiveStruct1 {|CS0523:s|};
int i;
}
""";
[LibraryImport("DoesNotExist")]
public static partial void Method(
int pRefSize,
- [MarshalUsing(ConstantElementCount = 10, CountElementName = "pRefSize")] ref int[] pRef
+ [{|#0:MarshalUsing(ConstantElementCount = 10, CountElementName = "pRefSize")|}] ref int[] {|#1:pRef|}
);
}
""";
[LibraryImport("DoesNotExist")]
public static partial void Method(
int pRefSize,
- [MarshalUsing(CountElementName = null)] ref int[] pRef
+ [{|#0:MarshalUsing(CountElementName = null)|}] ref int[] {|#1:pRef|}
);
}
""";
{
[LibraryImport("DoesNotExist")]
[return:MarshalUsing(ConstantElementCount=10)]
- [return:MarshalAs(UnmanagedType.LPArray, SizeConst=10)]
+ [return:{|#0:MarshalAs(UnmanagedType.LPArray, SizeConst=10)|}]
public static partial int[] Method();
}
""";
{
[LibraryImport("DoesNotExist")]
public static partial void Method(
- [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] TestCollection<int> p);
+ [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] [{|#0:MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)|}] TestCollection<int> p);
}
"""
+ CustomCollectionMarshallingCodeSnippets.TestCollection()
{
[LibraryImport("DoesNotExist")]
public static partial void Method(
- [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 2)] TestCollection<int> p);
+ [{|#0:MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 2)|}] TestCollection<int> p);
}
"""
+ CustomCollectionMarshallingCodeSnippets.TestCollection()
partial class Test
{
[LibraryImport("DoesNotExist")]
- [return:MarshalUsing(CountElementName=MarshalUsingAttribute.ReturnsCountValue)]
- public static partial int[] Method();
+ [return:{|#0:MarshalUsing(CountElementName=MarshalUsingAttribute.ReturnsCountValue)|}]
+ public static partial int[] {|#1:Method|}();
}
""";
{
[LibraryImport("DoesNotExist")]
public static partial void Method(
- [MarshalUsing(CountElementName="arr")] ref int[] arr
+ [{|#0:MarshalUsing(CountElementName="arr")|}] ref int[] {|#1:arr|}
);
}
""";
{
[LibraryImport("DoesNotExist")]
public static partial void Method(
- [MarshalUsing(CountElementName="arr2")] ref int[] arr,
- [MarshalUsing(CountElementName="arr")] ref int[] arr2
+ [{|#0:MarshalUsing(CountElementName="arr2")|}] ref int[] {|#1:arr|},
+ [{|#2:MarshalUsing(CountElementName="arr")|}] ref int[] {|#3:arr2|}
);
}
""";
{
[LibraryImport("DoesNotExist")]
public static partial void Method(
- [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] ref int[] arr,
- [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] ref int[] arr2
+ [{|#0:MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)|}] ref int[] {|#1:arr|},
+ [{|#2:MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)|}] ref int[] {|#3:arr2|}
);
}
""";
partial struct Basic
{
[LibraryImport("DoesNotExist")]
- public static partial ref {{typeName}} RefReturn();
+ public static partial ref {{typeName}} {|#0:RefReturn|}();
[LibraryImport("DoesNotExist")]
- public static partial ref readonly {{typeName}} RefReadonlyReturn();
+ public static partial ref readonly {{typeName}} {|#1:RefReadonlyReturn|}();
}
""";
partial struct Basic
{
- [LibraryImport("DoesNotExist", SetLa)]
+ [{|CS1729:LibraryImport("DoesNotExist", {|CS0103:SetLa|})|}]
public static partial void Method();
}
""";
partial struct Basic
{
- [LibraryImport(DoesNotExist)]
+ [LibraryImport({|CS0103:DoesNotExist|})]
public static partial void Method();
}
""";
partial struct Basic
{
- [LibraryImport("DoesNotExist", SetLastError = "Foo")]
+ [LibraryImport("DoesNotExist", SetLastError = {|CS0029:"Foo"|})]
public static partial void Method();
}
""";
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Testing;
+using Microsoft.Interop;
using Microsoft.Interop.UnitTests;
using Xunit;
+using StringMarshalling = System.Runtime.InteropServices.StringMarshalling;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier<Microsoft.Interop.LibraryImportGenerator>;
+
namespace LibraryImportGenerator.UnitTests
{
public class CompileFails
public static IEnumerable<object[]> CodeSnippetsToCompile()
{
// Not LibraryImportAttribute
- yield return new object[] { ID(), CodeSnippets.UserDefinedPrefixedAttributes, 0, 3 };
+ yield return new object[] { ID(), CodeSnippets.UserDefinedPrefixedAttributes, Array.Empty<DiagnosticResult>() };
// No explicit marshalling for char or string
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<char>(), 5, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<string>(), 5, 0 };
- yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParametersAndModifiers<char>(), 5, 0 };
- yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParametersAndModifiers<string>(), 5, 0 };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<char>(), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(2)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "pOut")
+ }};
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<string>(), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(2)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pOut")
+ }};
+ yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParametersAndModifiers<char>(), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(2)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(5)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "pOut")
+ }};
+ yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParametersAndModifiers<string>(), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(2)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(5)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pOut")
+ }};
+
+ // No explicit marshalling for bool
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<bool>(), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(2)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pOut")
+ }};
+
+ yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParametersAndModifiers<bool>(), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(2)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(5)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pOut")
+ }};
- // No explicit marshaling for bool
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<bool>(), 5, 0 };
- yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParametersAndModifiers<bool>(), 5, 0 };
// Unsupported StringMarshalling configuration
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiersWithStringMarshalling<char>(StringMarshalling.Utf8), 5, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiersWithStringMarshalling<char>(StringMarshalling.Custom), 6, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiersWithStringMarshalling<string>(StringMarshalling.Custom), 6, 0 };
- yield return new object[] { ID(), CodeSnippets.CustomStringMarshallingParametersAndModifiers<char>(), 5, 0 };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiersWithStringMarshalling<char>(StringMarshalling.Utf8), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Marshalling char with 'StringMarshalling.Utf8' is not supported. Instead, manually convert the char type to the desired byte representation and pass to the source-generated P/Invoke.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(2)
+ .WithArguments("Marshalling char with 'StringMarshalling.Utf8' is not supported. Instead, manually convert the char type to the desired byte representation and pass to the source-generated P/Invoke.", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling char with 'StringMarshalling.Utf8' is not supported. Instead, manually convert the char type to the desired byte representation and pass to the source-generated P/Invoke.", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling char with 'StringMarshalling.Utf8' is not supported. Instead, manually convert the char type to the desired byte representation and pass to the source-generated P/Invoke.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(5)
+ .WithArguments("Marshalling char with 'StringMarshalling.Utf8' is not supported. Instead, manually convert the char type to the desired byte representation and pass to the source-generated P/Invoke.", "pOut")
+ }};
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiersWithStringMarshalling<char>(StringMarshalling.Custom), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.InvalidStringMarshallingConfiguration)
+ .WithLocation(0)
+ .WithArguments("Method", "'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'."),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Marshalling char with 'StringMarshalling.Custom' is not supported. To use a custom type marshaller, specify 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(2)
+ .WithArguments("Marshalling char with 'StringMarshalling.Custom' is not supported. To use a custom type marshaller, specify 'MarshalUsingAttribute'.", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling char with 'StringMarshalling.Custom' is not supported. To use a custom type marshaller, specify 'MarshalUsingAttribute'.", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling char with 'StringMarshalling.Custom' is not supported. To use a custom type marshaller, specify 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(5)
+ .WithArguments("Marshalling char with 'StringMarshalling.Custom' is not supported. To use a custom type marshaller, specify 'MarshalUsingAttribute'.", "pOut")
+ }};
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiersWithStringMarshalling<string>(StringMarshalling.Custom), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.InvalidStringMarshallingConfiguration)
+ .WithLocation(0)
+ .WithArguments("Method", "'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'."),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupported)
+ .WithLocation(1)
+ .WithArguments("string", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupported)
+ .WithLocation(2)
+ .WithArguments("string", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupported)
+ .WithLocation(3)
+ .WithArguments("string", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupported)
+ .WithLocation(4)
+ .WithArguments("string", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupported)
+ .WithLocation(5)
+ .WithArguments("string", "pOut")
+ }};
+ yield return new object[] { ID(), CodeSnippets.CustomStringMarshallingParametersAndModifiers<char>(), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling char with 'StringMarshalling.Custom' is not supported. To use a custom type marshaller, specify 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Marshalling char with 'StringMarshalling.Custom' is not supported. To use a custom type marshaller, specify 'MarshalUsingAttribute'.", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(2)
+ .WithArguments("Marshalling char with 'StringMarshalling.Custom' is not supported. To use a custom type marshaller, specify 'MarshalUsingAttribute'.", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling char with 'StringMarshalling.Custom' is not supported. To use a custom type marshaller, specify 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling char with 'StringMarshalling.Custom' is not supported. To use a custom type marshaller, specify 'MarshalUsingAttribute'.", "pOut")
+ }};
// Unsupported UnmanagedType
- yield return new object[] { ID(), CodeSnippets.MarshalAsParametersAndModifiers<char>(UnmanagedType.I1), 5, 0 };
- yield return new object[] { ID(), CodeSnippets.MarshalAsParametersAndModifiers<char>(UnmanagedType.U1), 5, 0 };
- yield return new object[] { ID(), CodeSnippets.MarshalAsParametersAndModifiers<int[]>(UnmanagedType.SafeArray), 10, 0 };
+ yield return new object[] { ID(), CodeSnippets.MarshalAsParametersAndModifiers<char>(UnmanagedType.I1), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments("MarshalAsAttribute", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(1)
+ .WithArguments("MarshalAsAttribute", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(2)
+ .WithArguments("MarshalAsAttribute", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(3)
+ .WithArguments("MarshalAsAttribute", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(4)
+ .WithArguments("MarshalAsAttribute", "pOut")
+ }};
+ yield return new object[] { ID(), CodeSnippets.MarshalAsParametersAndModifiers<char>(UnmanagedType.U1), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments("MarshalAsAttribute", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(1)
+ .WithArguments("MarshalAsAttribute", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(2)
+ .WithArguments("MarshalAsAttribute", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(3)
+ .WithArguments("MarshalAsAttribute", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(4)
+ .WithArguments("MarshalAsAttribute", "pOut")
+ }};
+ yield return new object[] { ID(), CodeSnippets.MarshalAsParametersAndModifiers<int[]>(UnmanagedType.SafeArray), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationValueNotSupported)
+ .WithLocation(10)
+ .WithArguments("SafeArray", "UnmanagedType"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationValueNotSupported)
+ .WithLocation(11)
+ .WithArguments("SafeArray", "UnmanagedType"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationValueNotSupported)
+ .WithLocation(12)
+ .WithArguments("SafeArray", "UnmanagedType"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationValueNotSupported)
+ .WithLocation(13)
+ .WithArguments("SafeArray", "UnmanagedType"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationValueNotSupported)
+ .WithLocation(14)
+ .WithArguments("SafeArray", "UnmanagedType"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments("MarshalAsAttribute", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(1)
+ .WithArguments("MarshalAsAttribute", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(2)
+ .WithArguments("MarshalAsAttribute", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(3)
+ .WithArguments("MarshalAsAttribute", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(4)
+ .WithArguments("MarshalAsAttribute", "pOut")
+ }};
// Unsupported MarshalAsAttribute usage
// * UnmanagedType.CustomMarshaler, MarshalTypeRef, MarshalType, MarshalCookie
- yield return new object[] { ID(), CodeSnippets.MarshalAsCustomMarshalerOnTypes, 16, 0 };
+ yield return new object[] { ID(), CodeSnippets.MarshalAsCustomMarshalerOnTypes, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationValueNotSupported)
+ .WithLocation(0)
+ .WithArguments("CustomMarshaler", "UnmanagedType"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments("MarshalAsAttribute.MarshalCookie"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments("MarshalAsAttribute.MarshalTypeRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationValueNotSupported)
+ .WithLocation(2)
+ .WithArguments("CustomMarshaler", "UnmanagedType"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationNotSupported)
+ .WithLocation(2)
+ .WithArguments("MarshalAsAttribute.MarshalCookie"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationNotSupported)
+ .WithLocation(2)
+ .WithArguments("MarshalAsAttribute.MarshalTypeRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationValueNotSupported)
+ .WithLocation(4)
+ .WithArguments("CustomMarshaler", "UnmanagedType"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationNotSupported)
+ .WithLocation(4)
+ .WithArguments("MarshalAsAttribute.MarshalCookie"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationNotSupported)
+ .WithLocation(4)
+ .WithArguments("MarshalAsAttribute.MarshalType"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationValueNotSupported)
+ .WithLocation(6)
+ .WithArguments("CustomMarshaler", "UnmanagedType"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationNotSupported)
+ .WithLocation(6)
+ .WithArguments("MarshalAsAttribute.MarshalCookie"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationNotSupported)
+ .WithLocation(6)
+ .WithArguments("MarshalAsAttribute.MarshalType"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnConfigurationNotSupported)
+ .WithLocation(1)
+ .WithArguments("MarshalAsAttribute", "Method1"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(3)
+ .WithArguments("MarshalAsAttribute", "t"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnConfigurationNotSupported)
+ .WithLocation(5)
+ .WithArguments("MarshalAsAttribute", "Method2"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(7)
+ .WithArguments("MarshalAsAttribute", "t")
+ }};
// Unsupported [In, Out] attributes usage
// Blittable array
- yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier<int[]>("Out"), 1, 0 };
- yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier<int[]>("In, Out"), 1, 0 };
+ yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier<int[]>("Out"), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The provided '[In]' and '[Out]' attributes on this parameter are unsupported on this parameter.", "p")
+ } };
+
+ yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier<int[]>("In, Out"), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The provided '[In]' and '[Out]' attributes on this parameter are unsupported on this parameter.", "p")
+ } };
// By ref with [In, Out] attributes
- yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("in int", "In"), 1, 0 };
- yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("ref int", "In"), 1, 0 };
- yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("ref int", "In, Out"), 1, 0 };
- yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("out int", "Out"), 1, 0 };
+ yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("in int", "In"), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead.", "p")
+ } };
+ yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("ref int", "In"), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead.", "p")
+ } };
+ yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("ref int", "In, Out"), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead.", "p")
+ } };
+ yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier("out int", "Out"), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead.", "p")
+ } };
// By value non-array with [In, Out] attributes
- yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier<byte>("In"), 1, 0 };
- yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier<byte>("Out"), 1, 0 };
- yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier<byte>("In, Out"), 1, 0 };
+ yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier<byte>("In"), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The '[In]' attribute is not supported unless the '[Out]' attribute is also used. The behavior of the '[In]' attribute without the '[Out]' attribute is the same as the default behavior.", "p")
+ } };
+ yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier<byte>("Out"), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The provided '[In]' and '[Out]' attributes on this parameter are unsupported on this parameter.", "p")
+ } };
+
+ yield return new object[] { ID(), CodeSnippets.ByValueParameterWithModifier<byte>("In, Out"), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The provided '[In]' and '[Out]' attributes on this parameter are unsupported on this parameter.", "p")
+ } };
// LCIDConversion
- yield return new object[] { ID(), CodeSnippets.LCIDConversionAttribute, 1, 0 };
+ yield return new object[] { ID(), CodeSnippets.LCIDConversionAttribute, new[] {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments("LCIDConversionAttribute")
+ } };
// No size information for array marshalling from unmanaged to managed
// * return, out, ref
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<byte[]>(CodeSnippets.DisableRuntimeMarshalling), 3, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<sbyte[]>(CodeSnippets.DisableRuntimeMarshalling), 3, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<short[]>(CodeSnippets.DisableRuntimeMarshalling), 3, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<ushort[]>(CodeSnippets.DisableRuntimeMarshalling), 3, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<char[]>(CodeSnippets.DisableRuntimeMarshalling), 3, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<string[]>(CodeSnippets.DisableRuntimeMarshalling), 5, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<int[]>(CodeSnippets.DisableRuntimeMarshalling), 3, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<uint[]>(CodeSnippets.DisableRuntimeMarshalling), 3, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<long[]>(CodeSnippets.DisableRuntimeMarshalling), 3, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<ulong[]>(CodeSnippets.DisableRuntimeMarshalling), 3, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<float[]>(CodeSnippets.DisableRuntimeMarshalling), 3, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<double[]>(CodeSnippets.DisableRuntimeMarshalling), 3, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<bool[]>(CodeSnippets.DisableRuntimeMarshalling), 5, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<IntPtr[]>(CodeSnippets.DisableRuntimeMarshalling), 3, 0 };
- yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<UIntPtr[]>(CodeSnippets.DisableRuntimeMarshalling), 3, 0 };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<byte[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pOut"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<sbyte[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pOut"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<short[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pOut"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<ushort[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pOut"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<char[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pOut"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<string[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(2)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pOut"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<int[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pOut"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<uint[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pOut"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<long[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pOut"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<ulong[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pOut"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<float[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pOut"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<double[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pOut"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<bool[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(2)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pOut"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<IntPtr[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pOut"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<UIntPtr[]>(CodeSnippets.DisableRuntimeMarshalling), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pOut"),
+ } };
// Collection with non-integer size param
- yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParameterWithSizeParam<float>(isByRef: false), 1, 0 };
- yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParameterWithSizeParam<double>(isByRef: false), 1, 0 };
- yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParameterWithSizeParam<bool>(isByRef: false), 2, 0 };
- yield return new object[] { ID(), CodeSnippets.MarshalUsingArrayParameterWithSizeParam<float>(isByRef: false), 1, 0 };
- yield return new object[] { ID(), CodeSnippets.MarshalUsingArrayParameterWithSizeParam<double>(isByRef: false), 1, 0 };
- yield return new object[] { ID(), CodeSnippets.MarshalUsingArrayParameterWithSizeParam<bool>(isByRef: false), 2, 0 };
+ yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParameterWithSizeParam<float>(isByRef: false), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("The specified collection size parameter for an collection must be an integer type. If the size information is applied to a nested collection, the size parameter must be a collection of one less level of nesting with an integral element.", "pRef")
+ } };
+ yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParameterWithSizeParam<double>(isByRef: false), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("The specified collection size parameter for an collection must be an integer type. If the size information is applied to a nested collection, the size parameter must be a collection of one less level of nesting with an integral element.", "pRef")
+ } };
+ yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParameterWithSizeParam<bool>(isByRef: false), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pRefSize"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("The specified collection size parameter for an collection must be an integer type. If the size information is applied to a nested collection, the size parameter must be a collection of one less level of nesting with an integral element.", "pRef")
+ } };
+ yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParameterWithSizeParam<float>(isByRef: true), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("The specified collection size parameter for an collection must be an integer type. If the size information is applied to a nested collection, the size parameter must be a collection of one less level of nesting with an integral element.", "pRef")
+ } };
+ yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParameterWithSizeParam<double>(isByRef: true), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("The specified collection size parameter for an collection must be an integer type. If the size information is applied to a nested collection, the size parameter must be a collection of one less level of nesting with an integral element.", "pRef")
+ } };
+ yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParameterWithSizeParam<bool>(isByRef: true), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Marshalling bool without explicit marshalling information is not supported. Specify either 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "pRefSize"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("The specified collection size parameter for an collection must be an integer type. If the size information is applied to a nested collection, the size parameter must be a collection of one less level of nesting with an integral element.", "pRef")
+ } };
// Custom type marshalling with invalid members
CustomStructMarshallingCodeSnippets customStructMarshallingCodeSnippets = new(new CodeSnippets());
- yield return new object[] { ID(), customStructMarshallingCodeSnippets.NonStaticMarshallerEntryPoint, 2, 0 };
- yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateless.ManagedToNativeOnlyOutParameter, 1, 0 };
- yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateless.ManagedToNativeOnlyReturnValue, 1, 0 };
- yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateless.NativeToManagedOnlyInParameter, 1, 0 };
- yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateless.StackallocOnlyRefParameter, 1, 0 };
- yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateful.ManagedToNativeOnlyOutParameter, 1, 0 };
- yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateful.ManagedToNativeOnlyReturnValue, 1, 0 };
- yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateful.NativeToManagedOnlyInParameter, 1, 0 };
- yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateful.StackallocOnlyRefParameter, 1, 0 };
-
- // Abstract SafeHandle type by reference
- yield return new object[] { ID(), CodeSnippets.BasicParameterWithByRefModifier("ref", "System.Runtime.InteropServices.SafeHandle"), 1, 0 };
+ yield return new object[] { ID(), customStructMarshallingCodeSnippets.NonStaticMarshallerEntryPoint, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupported).WithLocation(0).WithArguments("S", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported).WithLocation(10).WithArguments(""),
+ } };
+ yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateless.ManagedToNativeOnlyOutParameter, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The specified parameter needs to be marshalled from unmanaged to managed, but the marshaller type 'global::Marshaller' does not support it.", "p"),
+ } };
+ yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateless.ManagedToNativeOnlyReturnValue, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The specified parameter needs to be marshalled from unmanaged to managed, but the marshaller type 'global::Marshaller' does not support it.", "Method"),
+ } };
+ yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateless.NativeToManagedOnlyInParameter, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The specified parameter needs to be marshalled from managed to unmanaged, but the marshaller type 'global::Marshaller' does not support it.", "p"),
+ } };
+ yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateless.StackallocOnlyRefParameter, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The specified parameter needs to be marshalled from managed to unmanaged and unmanaged to managed, but the marshaller type 'global::Marshaller' does not support it.", "p"),
+ } };
+
+ // Abstract SafeHandle by reference
+ yield return new object[] { ID(), CodeSnippets.BasicParameterWithByRefModifier("ref", "System.Runtime.InteropServices.SafeHandle"), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The specified parameter needs to be marshalled from managed to unmanaged and unmanaged to managed, but the marshaller type 'global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller<global::System.Runtime.InteropServices.SafeHandle>' does not support it.", "p"),
+ } };
// SafeHandle array
- yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParametersAndModifiers("Microsoft.Win32.SafeHandles.SafeFileHandle"), 5, 0 };
+ yield return new object[] { ID(), CodeSnippets.MarshalAsArrayParametersAndModifiers("Microsoft.Win32.SafeHandles.SafeFileHandle"), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The specified parameter needs to be marshalled from unmanaged to managed, but the marshaller type 'global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller<global::Microsoft.Win32.SafeHandles.SafeFileHandle>' does not support it.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("The specified parameter needs to be marshalled from managed to unmanaged, but the marshaller type 'global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller<global::Microsoft.Win32.SafeHandles.SafeFileHandle>' does not support it.", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(2)
+ .WithArguments("The specified parameter needs to be marshalled from managed to unmanaged, but the marshaller type 'global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller<global::Microsoft.Win32.SafeHandles.SafeFileHandle>' does not support it.", "pIn"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("The specified parameter needs to be marshalled from managed to unmanaged and unmanaged to managed, but the marshaller type 'global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller<global::Microsoft.Win32.SafeHandles.SafeFileHandle>' does not support it.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(5)
+ .WithArguments("The specified parameter needs to be marshalled from unmanaged to managed, but the marshaller type 'global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller<global::Microsoft.Win32.SafeHandles.SafeFileHandle>' does not support it.", "pOut"),
+ } };
// SafeHandle with private constructor by ref or out
- yield return new object[] { ID(), CodeSnippets.SafeHandleWithCustomDefaultConstructorAccessibility(privateCtor: true), 3, 0 };
+ yield return new object[] { ID(), CodeSnippets.SafeHandleWithCustomDefaultConstructorAccessibility(privateCtor: true), new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("The specified parameter needs to be marshalled from unmanaged to managed, but the marshaller type 'global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller<global::MySafeHandle>' does not support it.", "Method"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("The specified parameter needs to be marshalled from managed to unmanaged and unmanaged to managed, but the marshaller type 'global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller<global::MySafeHandle>' does not support it.", "pRef"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("The specified parameter needs to be marshalled from unmanaged to managed, but the marshaller type 'global::System.Runtime.InteropServices.Marshalling.SafeHandleMarshaller<global::MySafeHandle>' does not support it.", "pOut"),
+ } };
// Collection with constant and element size parameter
- yield return new object[] { ID(), CodeSnippets.MarshalUsingCollectionWithConstantAndElementCount, 2, 0 };
-
+ yield return new object[] { ID(), CodeSnippets.MarshalUsingCollectionWithConstantAndElementCount, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments(""),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ } };
// Collection with null element size parameter name
- yield return new object[] { ID(), CodeSnippets.MarshalUsingCollectionWithNullElementName, 2, 0 };
+ yield return new object[] { ID(), CodeSnippets.MarshalUsingCollectionWithNullElementName, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationValueNotSupported)
+ .WithLocation(0)
+ .WithArguments("null", "CountElementName"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.", "pRef"),
+ } };
// Generic collection marshaller has different arity than collection.
CustomCollectionMarshallingCodeSnippets customCollectionMarshallingCodeSnippets = new(new CodeSnippets());
- yield return new object[] { ID(), customCollectionMarshallingCodeSnippets.Stateless.GenericCollectionMarshallingArityMismatch, 2, 0 };
-
- yield return new object[] { ID(), CodeSnippets.MarshalAsAndMarshalUsingOnReturnValue, 1, 0 };
- yield return new object[] { ID(), CodeSnippets.CustomElementMarshallingDuplicateElementIndirectionDepth, 1, 0 };
- yield return new object[] { ID(), CodeSnippets.CustomElementMarshallingUnusedElementIndirectionDepth, 1, 0 };
- yield return new object[] { ID(), CodeSnippets.RecursiveCountElementNameOnReturnValue, 2, 0 };
- yield return new object[] { ID(), CodeSnippets.RecursiveCountElementNameOnParameter, 2, 0 };
- yield return new object[] { ID(), CodeSnippets.MutuallyRecursiveCountElementNameOnParameter, 4, 0 };
- yield return new object[] { ID(), CodeSnippets.MutuallyRecursiveSizeParamIndexOnParameter, 4, 0 };
-
- // Ref returns
- yield return new object[] { ID(), CodeSnippets.RefReturn("int"), 2, 2 };
+ yield return new object[] { ID(), customCollectionMarshallingCodeSnippets.Stateless.GenericCollectionMarshallingArityMismatch, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupported)
+ .WithLocation(0)
+ .WithArguments("TestCollection<int>", "p"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported)
+ .WithLocation(10)
+ .WithArguments(""),
+ } };
+
+ yield return new object[] { ID(), CodeSnippets.MarshalAsAndMarshalUsingOnReturnValue, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments(""),
+ } };
+ yield return new object[] { ID(), CodeSnippets.CustomElementMarshallingDuplicateElementIndirectionDepth, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments(""),
+ } };
+ yield return new object[] { ID(), CodeSnippets.CustomElementMarshallingUnusedElementIndirectionDepth, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments(""),
+ } };
+ yield return new object[] { ID(), CodeSnippets.RecursiveCountElementNameOnReturnValue, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments(""),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("The specified collection size parameter for an collection must be an integer type. If the size information is applied to a nested collection, the size parameter must be a collection of one less level of nesting with an integral element.", "Method"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.RecursiveCountElementNameOnParameter, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments(""),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("The specified collection size parameter for an collection must be an integer type. If the size information is applied to a nested collection, the size parameter must be a collection of one less level of nesting with an integral element.", "arr"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.MutuallyRecursiveCountElementNameOnParameter, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments(""),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("The specified collection size parameter for an collection must be an integer type. If the size information is applied to a nested collection, the size parameter must be a collection of one less level of nesting with an integral element.", "arr"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported)
+ .WithLocation(2)
+ .WithArguments(""),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("The specified collection size parameter for an collection must be an integer type. If the size information is applied to a nested collection, the size parameter must be a collection of one less level of nesting with an integral element.", "arr2"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.MutuallyRecursiveSizeParamIndexOnParameter, new[]
+ {
+ VerifyCS.Diagnostic(GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments(""),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("The specified collection size parameter for an collection must be an integer type. If the size information is applied to a nested collection, the size parameter must be a collection of one less level of nesting with an integral element.", "arr"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported)
+ .WithLocation(2)
+ .WithArguments(""),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("The specified collection size parameter for an collection must be an integer type. If the size information is applied to a nested collection, the size parameter must be a collection of one less level of nesting with an integral element.", "arr2"),
+ } };
+ yield return new object[] { ID(), CodeSnippets.RefReturn("int"), new[]
+ {
+ DiagnosticResult.CompilerError("CS8795")
+ .WithLocation(0),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnConfigurationNotSupported)
+ .WithLocation(0)
+ .WithArguments("ref return", "Basic.RefReturn()"),
+ DiagnosticResult.CompilerError("CS8795")
+ .WithLocation(1),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnConfigurationNotSupported)
+ .WithLocation(1)
+ .WithArguments("ref return", "Basic.RefReadonlyReturn()"),
+ } };
}
[Theory]
[MemberData(nameof(CodeSnippetsToCompile))]
- public async Task ValidateSnippets(string id, string source, int expectedGeneratorErrors, int expectedCompilerErrors)
+ public async Task ValidateSnippets(string id, string source, DiagnosticResult[] diagnostics)
{
TestUtils.Use(id);
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
-
- // Verify the compilation failed with errors.
- IEnumerable<Diagnostic> generatorErrors = generatorDiags.Where(d => d.Severity == DiagnosticSeverity.Error);
- int generatorErrorCount = generatorErrors.Count();
- Assert.True(
- expectedGeneratorErrors == generatorErrorCount,
- $"Expected {expectedGeneratorErrors} errors, but encountered {generatorErrorCount}. Errors: {string.Join(Environment.NewLine, generatorErrors.Select(d => d.ToString()))}");
-
- IEnumerable<Diagnostic> compilerErrors = newComp.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error);
- int compilerErrorCount = compilerErrors.Count();
- Assert.True(
- expectedCompilerErrors == compilerErrorCount,
- $"Expected {expectedCompilerErrors} errors, but encountered {compilerErrorCount}. Errors: {string.Join(Environment.NewLine, compilerErrors.Select(d => d.ToString()))}");
+ // Each snippet will contain the expected diagnostic codes in their expected locations for the compile errors.
+ // The test case will pass in the expected generator diagnostics.
+ await VerifyCS.VerifySourceGeneratorAsync(source, diagnostics);
}
public static IEnumerable<object[]> CodeSnippetsToCompile_InvalidCode()
{
- yield return new object[] { ID(), CodeSnippets.RecursiveImplicitlyBlittableStruct, 0, 1 };
- yield return new object[] { ID(), CodeSnippets.MutuallyRecursiveImplicitlyBlittableStruct, 0, 2 };
- yield return new object[] { ID(), CodeSnippets.PartialPropertyName, 0, 2 };
- yield return new object[] { ID(), CodeSnippets.InvalidConstantForModuleName, 0, 1 };
- yield return new object[] { ID(), CodeSnippets.IncorrectAttributeFieldType, 0, 1 };
+ yield return new[] { ID(), CodeSnippets.RecursiveImplicitlyBlittableStruct };
+ yield return new[] { ID(), CodeSnippets.MutuallyRecursiveImplicitlyBlittableStruct };
+ yield return new[] { ID(), CodeSnippets.PartialPropertyName };
+ yield return new[] { ID(), CodeSnippets.InvalidConstantForModuleName };
+ yield return new[] { ID(), CodeSnippets.IncorrectAttributeFieldType };
}
[Theory]
[MemberData(nameof(CodeSnippetsToCompile_InvalidCode))]
- public async Task ValidateSnippets_InvalidCodeGracefulFailure(string id, string source, int expectedGeneratorErrors, int expectedCompilerErrors)
+ public async Task ValidateSnippets_InvalidCodeGracefulFailure(string id, string source)
{
TestUtils.Use(id);
- // Do not validate that the compilation has no errors that the generator will not fix.
- Compilation comp = await TestUtils.CreateCompilation(source);
-
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
-
- // Verify the compilation failed with errors.
- int generatorErrors = generatorDiags.Count(d => d.Severity == DiagnosticSeverity.Error);
- Assert.Equal(expectedGeneratorErrors, generatorErrors);
-
- int compilerErrors = newComp.GetDiagnostics().Count(d => d.Severity == DiagnosticSeverity.Error);
- Assert.Equal(expectedCompilerErrors, compilerErrors);
+ // Each snippet will contain the expected diagnostic codes in their expected locations for the compile errors.
+ // We expect there to be no generator diagnostics or failures.
+ await VerifyCS.VerifySourceGeneratorAsync(source);
}
[Fact]
public async Task ValidateDisableRuntimeMarshallingForBlittabilityCheckFromAssemblyReference()
{
+ // Emit the referenced assembly to a stream so we reference it through a metadata reference.
+ // Our check for strict blittability doesn't work correctly when using source compilation references.
+ // (There are sometimes false-positives.)
+ // This causes any diagnostics that depend on strict blittability being correctly calculated to
+ // not show up in the IDE experience. However, since they correctly show up when doing builds,
+ // either by running the Build command in the IDE or a command line build, we aren't allowing invalid code.
+ // This test validates the Build-like experience. In the future, we should update this test to validate the
+ // IDE-like experience once we fix that case
+ // (If the IDE experience works, then the command-line experience will also work.)
+ // This bug is tracked in https://github.com/dotnet/runtime/issues/84739.
string assemblySource = $$"""
- using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
{{CodeSnippets.ValidateDisableRuntimeMarshalling.NonBlittableUserDefinedTypeWithNativeType}}
""";
Compilation assemblyComp = await TestUtils.CreateCompilation(assemblySource);
- TestUtils.AssertPreSourceGeneratorCompilation(assemblyComp);
+ Assert.Empty(assemblyComp.GetDiagnostics());
var ms = new MemoryStream();
Assert.True(assemblyComp.Emit(ms).Success);
string testSource = CodeSnippets.ValidateDisableRuntimeMarshalling.TypeUsage(string.Empty);
- Compilation testComp = await TestUtils.CreateCompilation(testSource, refs: new[] { MetadataReference.CreateFromImage(ms.ToArray()) });
- TestUtils.AssertPreSourceGeneratorCompilation(testComp);
+ VerifyCS.Test test = new(referenceAncillaryInterop: false)
+ {
+ TestCode = testSource,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
- var newComp = TestUtils.RunGenerators(testComp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
+ test.TestState.AdditionalReferences.Add(MetadataReference.CreateFromImage(ms.ToArray()));
// The errors should indicate the DisableRuntimeMarshalling is required.
- Assert.True(generatorDiags.All(d => d.Id == "SYSLIB1051"));
-
- TestUtils.AssertPostSourceGeneratorCompilation(newComp);
+ test.ExpectedDiagnostics.Add(
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "Method"));
+ test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "p"));
+ test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(2)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "pIn"));
+ test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(3)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "pRef"));
+ test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(4)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "pOut"));
+
+ await test.RunAsync();
}
[Fact]
public async Task ValidateRequireAllowUnsafeBlocksDiagnostic()
{
- string source = CodeSnippets.TrivialClassDeclarations;
- Compilation comp = await TestUtils.CreateCompilation(new[] { source }, allowUnsafe: false);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
+ var test = new AllowUnsafeBlocksTest()
+ {
+ TestCode = CodeSnippets.TrivialClassDeclarations,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
+
+ test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic("SYSLIB1062"));
+ test.ExpectedDiagnostics.Add(DiagnosticResult.CompilerError("CS0227").WithLocation(0));
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
+ await test.RunAsync();
+ }
- // The errors should indicate the AllowUnsafeBlocks is required.
- Assert.True(generatorDiags.All(d => d.Id == "SYSLIB1062"));
+ class AllowUnsafeBlocksTest : VerifyCS.Test
+ {
+ public AllowUnsafeBlocksTest()
+ :base(referenceAncillaryInterop: false)
+ {
+ }
- // There should only be one SYSLIB1062, even if there are multiple LibraryImportAttribute uses.
- Assert.Equal(1, generatorDiags.Count());
+ protected override CompilationOptions CreateCompilationOptions() => ((CSharpCompilationOptions)base.CreateCompilationOptions()).WithAllowUnsafe(false);
}
}
}
using Xunit;
using SourceGenerators.Tests;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier<Microsoft.Interop.LibraryImportGenerator>;
+using Microsoft.CodeAnalysis.Testing;
+using System.Collections.Immutable;
+using System.Threading;
+using Microsoft.CodeAnalysis.Text;
+using System.Text;
+
namespace LibraryImportGenerator.UnitTests
{
public class Compiles
public async Task ValidateSnippets(string id, string source)
{
TestUtils.Use(id);
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- Assert.Empty(generatorDiags);
- TestUtils.AssertPostSourceGeneratorCompilation(newComp);
+ await VerifyCS.VerifySourceGeneratorAsync(source);
}
public static IEnumerable<object[]> CodeSnippetsToCompileWithPreprocessorSymbols()
public async Task ValidateSnippetsWithPreprocessorDefinitions(string id, string source, IEnumerable<string> preprocessorSymbols)
{
TestUtils.Use(id);
- Compilation comp = await TestUtils.CreateCompilation(source, preprocessorSymbols: preprocessorSymbols);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
+ var test = new PreprocessorTest(preprocessorSymbols)
+ {
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- Assert.Empty(generatorDiags);
+ await test.RunAsync();
+ }
- TestUtils.AssertPostSourceGeneratorCompilation(newComp);
+ private class PreprocessorTest : VerifyCS.Test
+ {
+ private readonly IEnumerable<string> _preprocessorSymbols;
+
+ public PreprocessorTest(IEnumerable<string> preprocessorSymbols)
+ :base(referenceAncillaryInterop: false)
+ {
+ _preprocessorSymbols = preprocessorSymbols;
+ }
+
+ protected override ParseOptions CreateParseOptions()
+ => ((CSharpParseOptions)base.CreateParseOptions()).WithPreprocessorSymbols(_preprocessorSymbols);
}
public static IEnumerable<object[]> CodeSnippetsToValidateFallbackForwarder()
{
- yield return new object[] { ID(), CodeSnippets.UserDefinedEntryPoint, TestTargetFramework.Net, true };
+ //yield return new object[] { ID(), CodeSnippets.UserDefinedEntryPoint, TestTargetFramework.Net, true };
// Confirm that all unsupported target frameworks can be generated.
{
string code = CodeSnippets.BasicParametersAndModifiers<byte>(CodeSnippets.LibraryImportAttributeDeclaration);
- yield return new object[] { ID(), code, TestTargetFramework.Net6, false };
+ //yield return new object[] { ID(), code, TestTargetFramework.Net6, false };
yield return new object[] { ID(), code, TestTargetFramework.Core, false };
yield return new object[] { ID(), code, TestTargetFramework.Standard, false };
yield return new object[] { ID(), code, TestTargetFramework.Framework, false };
public async Task ValidateSnippetsFallbackForwarder(string id, string source, TestTargetFramework targetFramework, bool expectFallbackForwarder)
{
TestUtils.Use(id);
- Compilation comp = await TestUtils.CreateCompilation(source, targetFramework);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(
- comp,
- new GlobalOptionsOnlyProvider(new TargetFrameworkConfigOptions(targetFramework)),
- out var generatorDiags,
- new Microsoft.Interop.LibraryImportGenerator());
+ var test = new FallbackForwarderTest(targetFramework, expectFallbackForwarder)
+ {
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
- Assert.Empty(generatorDiags);
+ await test.RunAsync();
+ }
- TestUtils.AssertPostSourceGeneratorCompilation(newComp);
+ class FallbackForwarderTest : VerifyCS.Test
+ {
+ private readonly bool _expectFallbackForwarder;
- // 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);
+ public FallbackForwarderTest(TestTargetFramework targetFramework, bool expectFallbackForwarder)
+ :base(targetFramework)
+ {
+ _expectFallbackForwarder = expectFallbackForwarder;
+ }
+ protected override void VerifyFinalCompilation(Compilation compilation)
+ {
+ SyntaxTree generatedCode = compilation.SyntaxTrees.Last();
+ SemanticModel model = compilation.GetSemanticModel(generatedCode);
+ var methods = generatedCode.GetRoot()
+ .DescendantNodes().OfType<MethodDeclarationSyntax>()
+ .ToList();
+ MethodDeclarationSyntax generatedMethod = Assert.Single(methods);
- IMethodSymbol method = model.GetDeclaredSymbol(generatedMethod)!;
+ 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);
+ // If we expect fallback forwarder, then the DllImportData will not be null.
+ Assert.Equal(_expectFallbackForwarder, method.GetDllImportData() is not null);
+ }
}
public static IEnumerable<object[]> FullyBlittableSnippetsToCompile()
public async Task ValidateSnippetsWithBlittableAutoForwarding(string id, string source)
{
TestUtils.Use(id);
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(
- comp,
- out var generatorDiags,
- new Microsoft.Interop.LibraryImportGenerator());
+ var test = new BlittableAutoForwarderTest()
+ {
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
- Assert.Empty(generatorDiags);
+ await test.RunAsync();
+ }
- TestUtils.AssertPostSourceGeneratorCompilation(newComp);
+ class BlittableAutoForwarderTest : VerifyCS.Test
+ {
+ public BlittableAutoForwarderTest()
+ :base(referenceAncillaryInterop: false)
+ {
+ }
- // 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();
+ protected override void VerifyFinalCompilation(Compilation compilation)
+ {
+ SyntaxTree generatedCode = compilation.SyntaxTrees.Last();
+ SemanticModel model = compilation.GetSemanticModel(generatedCode);
+ var methods = generatedCode.GetRoot()
+ .DescendantNodes().OfType<MethodDeclarationSyntax>()
+ .ToList();
- Assert.All(methods, method => Assert.NotNull(model.GetDeclaredSymbol(method)!.GetDllImportData()));
+ Assert.All(methods, method => Assert.NotNull(model.GetDeclaredSymbol(method)!.GetDllImportData()));
+ }
}
public static IEnumerable<object[]> SnippetsWithBlittableTypesButNonBlittableDataToCompile()
public async Task ValidateSnippetsWithBlittableTypesButNonBlittableMetadataDoNotAutoForward(string id, string source)
{
TestUtils.Use(id);
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(
- comp,
- out var generatorDiags,
- new Microsoft.Interop.LibraryImportGenerator());
-
- Assert.Empty(generatorDiags);
+ var test = new NonBlittableNoAutoForwardTest()
+ {
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
- TestUtils.AssertPostSourceGeneratorCompilation(newComp);
+ await test.RunAsync();
+ }
- // Verify that the generator generates stubs with inner DllImports for all methods.
- SyntaxTree generatedCode = newComp.SyntaxTrees.Last();
- SemanticModel model = newComp.GetSemanticModel(generatedCode);
- int numStubMethods = generatedCode.GetRoot()
- .DescendantNodes().OfType<MethodDeclarationSyntax>()
- .Count();
- int numInnerDllImports = generatedCode.GetRoot()
- .DescendantNodes().OfType<LocalFunctionStatementSyntax>()
- .Count();
+ class NonBlittableNoAutoForwardTest : VerifyCS.Test
+ {
+ public NonBlittableNoAutoForwardTest()
+ : base(referenceAncillaryInterop: false)
+ {
+ }
- Assert.Equal(numStubMethods, numInnerDllImports);
+ protected override void VerifyFinalCompilation(Compilation compilation)
+ {
+ SyntaxTree generatedCode = compilation.SyntaxTrees.Last();
+ SemanticModel model = compilation.GetSemanticModel(generatedCode);
+ int numStubMethods = generatedCode.GetRoot()
+ .DescendantNodes().OfType<MethodDeclarationSyntax>()
+ .Count();
+ int numInnerDllImports = generatedCode.GetRoot()
+ .DescendantNodes().OfType<LocalFunctionStatementSyntax>()
+ .Count();
+ Assert.Equal(numStubMethods, numInnerDllImports);
+ }
}
public static IEnumerable<object[]> CodeSnippetsToCompileWithMarshalType()
public async Task ValidateSnippetsWithMarshalType(string id, string source)
{
TestUtils.Use(id);
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(
- comp,
- new LibraryImportGeneratorOptionsProvider(TestTargetFramework.Net, useMarshalType: true, generateForwarders: false),
- out var generatorDiags,
- new Microsoft.Interop.LibraryImportGenerator());
-
- Assert.Empty(generatorDiags);
-
- TestUtils.AssertPostSourceGeneratorCompilation(newComp, "CS0117");
+ var test = new VerifyCS.Test(referenceAncillaryInterop: true)
+ {
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
+ test.SolutionTransforms.Add((solution, projectId) =>
+ solution.AddAnalyzerConfigDocument(DocumentId.CreateNewId(projectId),
+ "UseMarshalType.editorconfig",
+ SourceText.From("""
+ is_global = true
+ build_property.LibraryImportGenerator_UseMarshalType = true
+ """,
+ Encoding.UTF8),
+ filePath: "/UseMarshalType.editorconfig"));
+ await test.RunAsync();
}
public static IEnumerable<object[]> CodeSnippetsToCompileMultipleSources()
public async Task ValidateSnippetsWithMultipleSources(string id, string[] sources)
{
TestUtils.Use(id);
- Compilation comp = await TestUtils.CreateCompilation(sources);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- Assert.Empty(generatorDiags);
+ // To enable us to reuse snippets that have markup locations in our multiple-sources test, we'll strip out the markup locations.
+ // We need to do this as each snippet expects to be able to define all expected markup locations (starting from 0), so including multiple snippets
+ // results in multiple definitions for the same location (which doesn't work). Since we expect no diagnostics, we can strip out the locations.
+ await VerifyCS.VerifySourceGeneratorAsync(sources.Select(RemoveTestMarkup).ToArray());
+ }
- TestUtils.AssertPostSourceGeneratorCompilation(newComp);
+ private static string RemoveTestMarkup(string sourceWithMarkup)
+ {
+ TestFileMarkupParser.GetSpans(sourceWithMarkup, out string sourceWithoutMarkup, out ImmutableArray<TextSpan> _);
+ return sourceWithoutMarkup;
}
public static IEnumerable<object[]> CodeSnippetsToVerifyNoTreesProduced()
public async Task ValidateNoGeneratedOuptutForNoImport(string id, string source, TestTargetFramework framework)
{
TestUtils.Use(id);
- Compilation comp = await TestUtils.CreateCompilation(source, framework, allowUnsafe: false);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
+ var test = new NoChangeTest(framework)
+ {
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
+ };
+
+ await test.RunAsync();
+ }
- var newComp = TestUtils.RunGenerators(comp, new GlobalOptionsOnlyProvider(new TargetFrameworkConfigOptions(framework)), out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- Assert.Empty(generatorDiags);
+ class NoChangeTest : VerifyCS.Test
+ {
+ public NoChangeTest(TestTargetFramework framework)
+ :base(framework)
+ {
+ }
- // Assert we didn't generate any syntax trees, even empty ones
- Assert.Same(comp, newComp);
+ protected async override Task<(Compilation compilation, ImmutableArray<Diagnostic> generatorDiagnostics)> GetProjectCompilationAsync(Project project, IVerifier verifier, CancellationToken cancellationToken)
+ {
+ var originalCompilation = await project.GetCompilationAsync(cancellationToken);
+ var (newCompilation, diagnostics) = await base.GetProjectCompilationAsync(project, verifier, cancellationToken);
+ Assert.Same(originalCompilation, newCompilation);
+ return (newCompilation, diagnostics);
+ }
}
}
}
using static Microsoft.Interop.Analyzers.ConvertToLibraryImportAnalyzer;
-using VerifyCS = LibraryImportGenerator.UnitTests.Verifiers.CSharpAnalyzerVerifier<Microsoft.Interop.Analyzers.ConvertToLibraryImportAnalyzer>;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpAnalyzerVerifier<Microsoft.Interop.Analyzers.ConvertToLibraryImportAnalyzer>;
namespace LibraryImportGenerator.UnitTests
{
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.Interop.Analyzers;
using Xunit;
-using static Microsoft.Interop.Analyzers.ConvertToLibraryImportFixer;
-using VerifyCS = LibraryImportGenerator.UnitTests.Verifiers.CSharpCodeFixVerifier<
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpCodeFixVerifier<
Microsoft.Interop.Analyzers.ConvertToLibraryImportAnalyzer,
Microsoft.Interop.Analyzers.ConvertToLibraryImportFixer>;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
-using LibraryImportGenerator.UnitTests.Verifiers;
+using Microsoft.Interop.UnitTests.Verifiers;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Testing;
using Microsoft.Interop.Analyzers;
using Xunit;
using static Microsoft.Interop.Analyzers.CustomMarshallerAttributeAnalyzer;
-using VerifyCS = LibraryImportGenerator.UnitTests.Verifiers.CSharpCodeFixVerifier<
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpCodeFixVerifier<
Microsoft.Interop.Analyzers.CustomMarshallerAttributeAnalyzer,
Microsoft.Interop.Analyzers.CustomMarshallerAttributeFixer>;
using Xunit;
using static Microsoft.Interop.Analyzers.CustomMarshallerAttributeAnalyzer;
-using VerifyCS = LibraryImportGenerator.UnitTests.Verifiers.CSharpCodeFixVerifier<
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpCodeFixVerifier<
Microsoft.Interop.Analyzers.CustomMarshallerAttributeAnalyzer,
Microsoft.Interop.Analyzers.CustomMarshallerAttributeFixer>;
using Xunit;
using static Microsoft.Interop.Analyzers.CustomMarshallerAttributeAnalyzer;
-using VerifyCS = LibraryImportGenerator.UnitTests.Verifiers.CSharpCodeFixVerifier<
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpCodeFixVerifier<
Microsoft.Interop.Analyzers.CustomMarshallerAttributeAnalyzer,
Microsoft.Interop.Analyzers.CustomMarshallerAttributeFixer>;
using Xunit;
using static Microsoft.Interop.Analyzers.CustomMarshallerAttributeAnalyzer;
-using VerifyCS = LibraryImportGenerator.UnitTests.Verifiers.CSharpCodeFixVerifier<
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpCodeFixVerifier<
Microsoft.Interop.Analyzers.CustomMarshallerAttributeAnalyzer,
Microsoft.Interop.Analyzers.CustomMarshallerAttributeFixer>;
using Xunit;
using static Microsoft.Interop.Analyzers.CustomMarshallerAttributeAnalyzer;
-using VerifyCS = LibraryImportGenerator.UnitTests.Verifiers.CSharpCodeFixVerifier<
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpCodeFixVerifier<
Microsoft.Interop.Analyzers.CustomMarshallerAttributeAnalyzer,
Microsoft.Interop.Analyzers.CustomMarshallerAttributeFixer>;
using Microsoft.CodeAnalysis.Testing;
using Microsoft.Interop;
using Microsoft.Interop.UnitTests;
-using SourceGenerators.Tests;
using Xunit;
using StringMarshalling = Microsoft.Interop.StringMarshalling;
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier<Microsoft.Interop.LibraryImportGenerator>;
namespace LibraryImportGenerator.UnitTests
{
partial class Test
{
[LibraryImport("DoesNotExist")]
- public static partial void Method1(NS.MyClass c);
+ public static partial void Method1(NS.MyClass {|#0:c|});
[LibraryImport("DoesNotExist")]
- public static partial void Method2(int i, List<int> list);
+ public static partial void Method2(int i, List<int> {|#1:list|});
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- DiagnosticResult[] expectedDiags = new DiagnosticResult[]
- {
- (new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupported))
- .WithSpan(11, 51, 11, 52)
+ await VerifyCS.VerifySourceGeneratorAsync(source,
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupported)
+ .WithLocation(0)
.WithArguments("NS.MyClass", "c"),
- (new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupported))
- .WithSpan(14, 57, 14, 61)
- .WithArguments("System.Collections.Generic.List<int>", "list"),
- };
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
-
- var newCompDiags = newComp.GetDiagnostics();
- Assert.Empty(newCompDiags);
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupported)
+ .WithLocation(1)
+ .WithArguments("System.Collections.Generic.List<int>", "list"));
}
[Fact]
partial class Test
{
[LibraryImport("DoesNotExist")]
- public static partial NS.MyClass Method1();
+ public static partial NS.MyClass {|#0:Method1|}();
[LibraryImport("DoesNotExist")]
- public static partial List<int> Method2();
+ public static partial List<int> {|#1:Method2|}();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- DiagnosticResult[] expectedDiags = new DiagnosticResult[]
- {
- (new DiagnosticResult(GeneratorDiagnostics.ReturnTypeNotSupported))
- .WithSpan(11, 38, 11, 45)
+ await VerifyCS.VerifySourceGeneratorAsync(source,
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupported)
+ .WithLocation(0)
.WithArguments("NS.MyClass", "Method1"),
- (new DiagnosticResult(GeneratorDiagnostics.ReturnTypeNotSupported))
- .WithSpan(14, 37, 14, 44)
- .WithArguments("System.Collections.Generic.List<int>", "Method2"),
- };
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
-
- var newCompDiags = newComp.GetDiagnostics();
- Assert.Empty(newCompDiags);
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupported)
+ .WithLocation(1)
+ .WithArguments("System.Collections.Generic.List<int>", "Method2"));
}
[Fact]
partial class Test
{
[LibraryImport("DoesNotExist")]
- public static partial void Method(char c, string s);
+ public static partial void Method(char {|#0:c|}, string {|#1:s|});
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- DiagnosticResult[] expectedDiags = new DiagnosticResult[]
- {
- (new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails))
- .WithSpan(6, 44, 6, 45),
- (new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails))
- .WithSpan(6, 54, 6, 55),
- };
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
-
- var newCompDiags = newComp.GetDiagnostics();
- Assert.Empty(newCompDiags);
+ await VerifyCS.VerifySourceGeneratorAsync(source,
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "c"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "s"));
}
[Fact]
partial class Test
{
[LibraryImport("DoesNotExist")]
- public static partial char Method1();
+ public static partial char {|#0:Method1|}();
[LibraryImport("DoesNotExist")]
- public static partial string Method2();
+ public static partial string {|#1:Method2|}();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- DiagnosticResult[] expectedDiags = new DiagnosticResult[]
- {
- (new DiagnosticResult(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails))
- .WithSpan(6, 32, 6, 39),
- (new DiagnosticResult(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails))
- .WithSpan(9, 34, 9, 41),
- };
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
- var newCompDiags = newComp.GetDiagnostics();
- Assert.Empty(newCompDiags);
+ await VerifyCS.VerifySourceGeneratorAsync(source,
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(0)
+ .WithArguments("Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type.", "Method1"),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "Method2"));
}
[Fact]
partial class Test
{
[LibraryImport("DoesNotExist")]
- public static partial void Method1([MarshalAs(UnmanagedType.BStr)] int i1, int i2);
+ public static partial void Method1([MarshalAs(UnmanagedType.BStr)] int {|#0:i1|}, int i2);
[LibraryImport("DoesNotExist")]
- public static partial void Method2(int i1, [MarshalAs(UnmanagedType.FunctionPtr)] bool b2);
+ public static partial void Method2(int i1, [MarshalAs(UnmanagedType.FunctionPtr)] bool {|#1:b2|});
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- DiagnosticResult[] expectedDiags = new DiagnosticResult[]
- {
- (new DiagnosticResult(GeneratorDiagnostics.ParameterConfigurationNotSupported))
- .WithSpan(6, 76, 6, 78)
+ await VerifyCS.VerifySourceGeneratorAsync(source,
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(0)
.WithArguments(nameof(MarshalAsAttribute), "i1"),
- (new DiagnosticResult(GeneratorDiagnostics.ParameterConfigurationNotSupported))
- .WithSpan(9, 92, 9, 94)
- .WithArguments(nameof(MarshalAsAttribute), "b2"),
- };
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
-
- var newCompDiags = newComp.GetDiagnostics();
- Assert.Empty(newCompDiags);
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(1)
+ .WithArguments(nameof(MarshalAsAttribute), "b2"));
}
[Fact]
{
[LibraryImport("DoesNotExist")]
[return: MarshalAs(UnmanagedType.BStr)]
- public static partial int Method1(int i);
+ public static partial int {|#0:Method1|}(int i);
[LibraryImport("DoesNotExist")]
[return: MarshalAs(UnmanagedType.FunctionPtr)]
- public static partial bool Method2(int i);
+ public static partial bool {|#1:Method2|}(int i);
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- DiagnosticResult[] expectedDiags = new DiagnosticResult[]
- {
- (new DiagnosticResult(GeneratorDiagnostics.ReturnConfigurationNotSupported))
- .WithSpan(7, 31, 7, 38)
+ await VerifyCS.VerifySourceGeneratorAsync(source,
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnConfigurationNotSupported)
+ .WithLocation(0)
.WithArguments(nameof(MarshalAsAttribute), "Method1"),
- (new DiagnosticResult(GeneratorDiagnostics.ReturnConfigurationNotSupported))
- .WithSpan(11, 32, 11, 39)
- .WithArguments(nameof(MarshalAsAttribute), "Method2"),
- };
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
-
- var newCompDiags = newComp.GetDiagnostics();
- Assert.Empty(newCompDiags);
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnConfigurationNotSupported)
+ .WithLocation(1)
+ .WithArguments(nameof(MarshalAsAttribute), "Method2"));
}
[Fact]
partial class Test
{
[LibraryImport("DoesNotExist")]
- [return: MarshalAs(1)]
- public static partial int Method1(int i);
+ [return: {|#0:MarshalAs(1)|}]
+ public static partial int {|#1:Method1|}(int i);
[LibraryImport("DoesNotExist")]
- public static partial int Method2([MarshalAs((short)0)] bool b);
+ public static partial int Method2([{|#2:MarshalAs((short)0)|}] bool {|#3:b|});
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- DiagnosticResult[] expectedDiags = new DiagnosticResult[]
- {
- (new DiagnosticResult(GeneratorDiagnostics.ConfigurationValueNotSupported))
- .WithSpan(6, 14, 6, 26)
+ await VerifyCS.VerifySourceGeneratorAsync(source,
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationValueNotSupported)
+ .WithLocation(0)
.WithArguments(1, nameof(UnmanagedType)),
- (new DiagnosticResult(GeneratorDiagnostics.ReturnConfigurationNotSupported))
- .WithSpan(7, 31, 7, 38)
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ReturnConfigurationNotSupported)
+ .WithLocation(1)
.WithArguments(nameof(MarshalAsAttribute), "Method1"),
- (new DiagnosticResult(GeneratorDiagnostics.ConfigurationValueNotSupported))
- .WithSpan(10, 40, 10, 59)
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationValueNotSupported)
+ .WithLocation(2)
.WithArguments(0, nameof(UnmanagedType)),
- (new DiagnosticResult(GeneratorDiagnostics.ParameterConfigurationNotSupported))
- .WithSpan(10, 66, 10, 67)
- .WithArguments(nameof(MarshalAsAttribute), "b"),
- };
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
-
- var newCompDiags = newComp.GetDiagnostics();
- Assert.Empty(newCompDiags);
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterConfigurationNotSupported)
+ .WithLocation(3)
+ .WithArguments(nameof(MarshalAsAttribute), "b"));
}
[Fact]
partial class Test
{
[LibraryImport("DoesNotExist")]
- [return: MarshalAs(UnmanagedType.I4, SafeArraySubType=VarEnum.VT_I4)]
+ [return: {|#0:MarshalAs(UnmanagedType.I4, SafeArraySubType=VarEnum.VT_I4)|}]
public static partial int Method1(int i);
[LibraryImport("DoesNotExist")]
- public static partial int Method2([MarshalAs(UnmanagedType.I1, IidParameterIndex = 1)] bool b);
+ public static partial int Method2([{|#1:MarshalAs(UnmanagedType.I1, IidParameterIndex = 1)|}] bool b);
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- DiagnosticResult[] expectedDiags = new DiagnosticResult[]
- {
- (new DiagnosticResult(GeneratorDiagnostics.ConfigurationNotSupported))
- .WithSpan(6, 14, 6, 73)
+ await VerifyCS.VerifySourceGeneratorAsync(source,
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationNotSupported)
+ .WithLocation(0)
.WithArguments($"{nameof(MarshalAsAttribute)}{Type.Delimiter}{nameof(MarshalAsAttribute.SafeArraySubType)}"),
- (new DiagnosticResult(GeneratorDiagnostics.ConfigurationNotSupported))
- .WithSpan(10, 40, 10, 90)
- .WithArguments($"{nameof(MarshalAsAttribute)}{Type.Delimiter}{nameof(MarshalAsAttribute.IidParameterIndex)}"),
- };
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
- var newCompDiags = newComp.GetDiagnostics();
- Assert.Empty(newCompDiags);
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ConfigurationNotSupported)
+ .WithLocation(1)
+ .WithArguments($"{nameof(MarshalAsAttribute)}{Type.Delimiter}{nameof(MarshalAsAttribute.IidParameterIndex)}"));
}
[Fact]
partial class Test
{
[LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Utf8)]
- public static partial void Method1(string s);
+ public static partial void {|#0:Method1|}(string s);
[LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(Native))]
- public static partial void Method2(string s);
+ public static partial void Method2(string {|#1:s|});
struct Native
{
}
}
""" + CodeSnippets.LibraryImportAttributeDeclaration;
-
- // Compile against Standard so that we generate forwarders
- Compilation comp = await TestUtils.CreateCompilation(source, TestTargetFramework.Standard);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- Compilation newComp = TestUtils.RunGenerators(
- comp,
- new GlobalOptionsOnlyProvider(new TargetFrameworkConfigOptions(TestTargetFramework.Standard)),
- out var generatorDiags,
- new Microsoft.Interop.LibraryImportGenerator());
DiagnosticResult[] expectedDiags = new DiagnosticResult[]
{
- (new DiagnosticResult(GeneratorDiagnostics.CannotForwardToDllImport))
- .WithSpan(6, 32, 6, 39)
+ VerifyCS.Diagnostic(GeneratorDiagnostics.CannotForwardToDllImport)
+ .WithLocation(0)
.WithArguments($"{nameof(TypeNames.LibraryImportAttribute)}{Type.Delimiter}{nameof(StringMarshalling)}={nameof(StringMarshalling)}{Type.Delimiter}{nameof(StringMarshalling.Utf8)}"),
- (new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails))
- .WithSpan(9, 47, 9, 48)
+ VerifyCS.Diagnostic(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)
+ .WithLocation(1)
+ .WithArguments("Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.", "s")
+ };
+
+ var test = new VerifyCS.Test(TestTargetFramework.Standard)
+ {
+ TestCode = source,
+ TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck
};
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
- var newCompDiags = newComp.GetDiagnostics();
- Assert.Empty(newCompDiags);
+ test.ExpectedDiagnostics.AddRange(expectedDiags);
+ await test.RunAsync();
}
[Fact]
{{CodeSnippets.DisableRuntimeMarshalling}}
partial class Test
{
- [LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Custom)]
+ [{|#0:LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Custom)|}]
public static partial void Method1(out int i);
- [LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Utf8, StringMarshallingCustomType = typeof(Native))]
+ [{|#1:LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Utf8, StringMarshallingCustomType = typeof(Native))|}]
public static partial void Method2(out int i);
struct Native
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- DiagnosticResult[] expectedDiags = new DiagnosticResult[]
- {
- (new DiagnosticResult(GeneratorDiagnostics.InvalidStringMarshallingConfiguration))
- .WithSpan(6, 6, 6, 81),
- (new DiagnosticResult(GeneratorDiagnostics.InvalidStringMarshallingConfiguration))
- .WithSpan(9, 6, 9, 125)
- };
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
- var newCompDiags = newComp.GetDiagnostics();
- Assert.Empty(newCompDiags);
+ await VerifyCS.VerifySourceGeneratorAsync(source,
+ VerifyCS.Diagnostic(GeneratorDiagnostics.InvalidStringMarshallingConfiguration)
+ .WithLocation(0)
+ .WithArguments("Method1", "'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'."),
+ VerifyCS.Diagnostic(GeneratorDiagnostics.InvalidStringMarshallingConfiguration)
+ .WithLocation(1)
+ .WithArguments("Method2", "'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified."));
}
[Fact]
partial class Test
{
[LibraryImport("DoesNotExist")]
- public static void Method() { }
+ public static void {|#0:Method|}() { }
[LibraryImport("DoesNotExist")]
- public static extern void ExternMethod();
+ public static extern void {|#1:ExternMethod|}();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- DiagnosticResult[] expectedDiags = new DiagnosticResult[]
- {
- (new DiagnosticResult(GeneratorDiagnostics.InvalidAttributedMethodSignature))
- .WithSpan(6, 24, 6, 30)
+ await VerifyCS.VerifySourceGeneratorAsync(source,
+ VerifyCS.Diagnostic(GeneratorDiagnostics.InvalidAttributedMethodSignature)
+ .WithLocation(0)
.WithArguments("Method"),
- (new DiagnosticResult(GeneratorDiagnostics.InvalidAttributedMethodSignature))
- .WithSpan(9, 31, 9, 43)
- .WithArguments("ExternMethod"),
- };
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
- var newCompDiags = newComp.GetDiagnostics();
- Assert.Empty(newCompDiags);
+ VerifyCS.Diagnostic(GeneratorDiagnostics.InvalidAttributedMethodSignature)
+ .WithLocation(1)
+ .WithArguments("ExternMethod"));
}
[Fact]
partial class Test
{
[LibraryImport("DoesNotExist")]
- public partial void Method();
+ public partial void {|#0:Method|}();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- DiagnosticResult[] expectedDiags = new DiagnosticResult[]
- {
- (new DiagnosticResult(GeneratorDiagnostics.InvalidAttributedMethodSignature))
- .WithSpan(6, 25, 6, 31)
- .WithArguments("Method")
- };
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
- // Generator ignores the method
- TestUtils.AssertPreSourceGeneratorCompilation(newComp);
+ await VerifyCS.VerifySourceGeneratorAsync(source,
+ VerifyCS.Diagnostic(GeneratorDiagnostics.InvalidAttributedMethodSignature)
+ .WithLocation(0)
+ .WithArguments("Method"),
+ // Generator ignores the method
+ DiagnosticResult.CompilerError("CS8795")
+ .WithLocation(0));
}
[Fact]
partial class Test
{
[LibraryImport("DoesNotExist")]
- public static partial void Method1<T>();
+ public static partial void {|#0:Method1|}<T>();
[LibraryImport("DoesNotExist")]
- public static partial void Method2<T, U>();
+ public static partial void {|#1:Method2|}<T, U>();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- DiagnosticResult[] expectedDiags = new DiagnosticResult[]
- {
- (new DiagnosticResult(GeneratorDiagnostics.InvalidAttributedMethodSignature))
- .WithSpan(6, 32, 6, 39)
+ await VerifyCS.VerifySourceGeneratorAsync(source,
+ VerifyCS.Diagnostic(GeneratorDiagnostics.InvalidAttributedMethodSignature)
+ .WithLocation(0)
.WithArguments("Method1"),
- (new DiagnosticResult(GeneratorDiagnostics.InvalidAttributedMethodSignature))
- .WithSpan(9, 32, 9, 39)
+ VerifyCS.Diagnostic(GeneratorDiagnostics.InvalidAttributedMethodSignature)
+ .WithLocation(1)
.WithArguments("Method2"),
- };
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
-
- // Generator ignores the method
- TestUtils.AssertPreSourceGeneratorCompilation(newComp);
+ // Generator ignores the method
+ DiagnosticResult.CompilerError("CS8795")
+ .WithLocation(0),
+ DiagnosticResult.CompilerError("CS8795")
+ .WithLocation(1));
}
[Theory]
{{typeKind}} Test
{
[LibraryImport("DoesNotExist")]
- public static partial void Method();
+ public static partial void {|#0:Method|}();
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
-
- // Also expect CS0751: A partial method must be declared within a partial type
- string additionalDiag = "CS0751";
- TestUtils.AssertPreSourceGeneratorCompilation(comp, additionalDiag);
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- DiagnosticResult[] expectedDiags = new DiagnosticResult[]
- {
- (new DiagnosticResult(GeneratorDiagnostics.InvalidAttributedMethodContainingTypeMissingModifiers))
- .WithSpan(6, 32, 6, 38)
+ await VerifyCS.VerifySourceGeneratorAsync(source,
+ VerifyCS.Diagnostic(GeneratorDiagnostics.InvalidAttributedMethodContainingTypeMissingModifiers)
+ .WithLocation(0)
.WithArguments("Method", "Test"),
- };
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
-
- // Generator ignores the method
- TestUtils.AssertPreSourceGeneratorCompilation(newComp, additionalDiag);
+ // Generator ignores the method
+ DiagnosticResult.CompilerError("CS8795")
+ .WithLocation(0),
+ // Also expect CS0751: A partial method must be declared within a partial type
+ DiagnosticResult.CompilerError("CS0751")
+ .WithLocation(0));
}
[Theory]
partial class TestInner
{
[LibraryImport("DoesNotExist")]
- static partial void Method();
+ static partial void {|#0:Method|}();
}
}
""";
- Compilation comp = await TestUtils.CreateCompilation(source);
- TestUtils.AssertPreSourceGeneratorCompilation(comp);
-
- var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.LibraryImportGenerator());
- DiagnosticResult[] expectedDiags = new DiagnosticResult[]
- {
- (new DiagnosticResult(GeneratorDiagnostics.InvalidAttributedMethodContainingTypeMissingModifiers))
- .WithSpan(8, 29, 8, 35)
- .WithArguments("Method", "Test"),
- };
- VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags));
- // Generator ignores the method
- TestUtils.AssertPreSourceGeneratorCompilation(newComp);
+ await VerifyCS.VerifySourceGeneratorAsync(source,
+ VerifyCS.Diagnostic(GeneratorDiagnostics.InvalidAttributedMethodContainingTypeMissingModifiers)
+ .WithLocation(0)
+ .WithArguments("Method", "Test"));
}
private static void VerifyDiagnostics(DiagnosticResult[] expectedDiagnostics, Diagnostic[] actualDiagnostics)
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Testing;
+using Microsoft.CodeAnalysis.Text;
using Microsoft.Interop.UnitTests;
using Xunit;
using static Microsoft.Interop.LibraryImportGenerator;
{
private static readonly GeneratorDriverOptions EnableIncrementalTrackingDriverOptions = new GeneratorDriverOptions(IncrementalGeneratorOutputKind.None, trackIncrementalGeneratorSteps: true);
- public const string RequiresIncrementalSyntaxTreeModifySupport = "The GeneratorDriver treats all SyntaxTree replace operations on a Compilation as an Add/Remove operation instead of a Modify operation"
- + ", so all cached results based on that input are thrown out. As a result, we cannot validate that unrelated changes within the same SyntaxTree do not cause regeneration.";
-
[Fact]
public async Task AddingNewUnrelatedType_DoesNotRegenerateSource()
{
- string source = CodeSnippets.BasicParametersAndModifiers<int>();
+ string source = RemoveTestMarkup(CodeSnippets.BasicParametersAndModifiers<int>());
Compilation comp1 = await TestUtils.CreateCompilation(source);
string source = $$"""
namespace NS
{
- {{CodeSnippets.BasicParametersAndModifiers<int>()}}
+ {{RemoveTestMarkup(CodeSnippets.BasicParametersAndModifiers<int>())}}
}
""";
[Fact]
public async Task AddingFileWithNewLibraryImport_DoesNotRegenerateOriginalMethod()
{
- string source = CodeSnippets.BasicParametersAndModifiers<int>();
+ string source = RemoveTestMarkup(CodeSnippets.BasicParametersAndModifiers<int>());
Compilation comp1 = await TestUtils.CreateCompilation(source);
driver = driver.RunGenerators(comp1);
- Compilation comp2 = comp1.AddSyntaxTrees(CSharpSyntaxTree.ParseText(CodeSnippets.MarshalAsParametersAndModifiers<bool>(UnmanagedType.I1), new CSharpParseOptions(LanguageVersion.Preview)));
+ Compilation comp2 = comp1.AddSyntaxTrees(CSharpSyntaxTree.ParseText(RemoveTestMarkup(CodeSnippets.MarshalAsParametersAndModifiers<bool>(UnmanagedType.I1)), new CSharpParseOptions(LanguageVersion.Preview)));
GeneratorDriver driver2 = driver.RunGenerators(comp2);
GeneratorRunResult runResult = driver2.GetRunResult().Results[0];
[Fact]
public async Task ReplacingFileWithNewLibraryImport_DoesNotRegenerateStubsInOtherFiles()
{
- Compilation comp1 = await TestUtils.CreateCompilation(new string[] { CodeSnippets.BasicParametersAndModifiers<int>(), CodeSnippets.MarshalAsParametersAndModifiers<bool>(UnmanagedType.I1) });
+ Compilation comp1 = await TestUtils.CreateCompilation(new string[] { RemoveTestMarkup(CodeSnippets.BasicParametersAndModifiers<int>()), RemoveTestMarkup(CodeSnippets.MarshalAsParametersAndModifiers<bool>(UnmanagedType.I1)) });
Microsoft.Interop.LibraryImportGenerator generator = new();
GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator }, EnableIncrementalTrackingDriverOptions);
driver = driver.RunGenerators(comp1);
- Compilation comp2 = comp1.ReplaceSyntaxTree(comp1.SyntaxTrees.First(), CSharpSyntaxTree.ParseText(CodeSnippets.BasicParametersAndModifiers<ulong>(), new CSharpParseOptions(LanguageVersion.Preview)));
+ Compilation comp2 = comp1.ReplaceSyntaxTree(comp1.SyntaxTrees.First(), CSharpSyntaxTree.ParseText(RemoveTestMarkup(CodeSnippets.BasicParametersAndModifiers<ulong>()), new CSharpParseOptions(LanguageVersion.Preview)));
GeneratorDriver driver2 = driver.RunGenerators(comp2);
GeneratorRunResult runResult = driver2.GetRunResult().Results[0];
[Fact]
public async Task ChangingMarshallingStrategy_RegeneratesStub()
{
- string stubSource = CodeSnippets.BasicParametersAndModifiers("CustomType", CodeSnippets.DisableRuntimeMarshalling);
+ string stubSource = RemoveTestMarkup(CodeSnippets.BasicParametersAndModifiers("CustomType", CodeSnippets.DisableRuntimeMarshalling));
string customTypeImpl1 = "struct CustomType { System.IntPtr handle; }";
[Fact]
public async Task ChangingMarshallingAttributes_SameStrategy_DoesNotRegenerate()
{
- string source = CodeSnippets.BasicParametersAndModifiers<int>();
+ string source = RemoveTestMarkup(CodeSnippets.BasicParametersAndModifiers<int>());
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview));
SyntaxTree newTree = syntaxTree.WithRootAndOptions(
SyntaxFactory.ParseCompilationUnit(
- CodeSnippets.MarshalAsParametersAndModifiers<int>(System.Runtime.InteropServices.UnmanagedType.I4)),
+ RemoveTestMarkup(CodeSnippets.MarshalAsParametersAndModifiers<int>(System.Runtime.InteropServices.UnmanagedType.I4))),
syntaxTree.Options);
Compilation comp2 = comp1.ReplaceSyntaxTree(comp1.SyntaxTrees.First(), newTree);
public static IEnumerable<object[]> CompilationObjectLivenessSources()
{
// Basic stub
- yield return new[] { CodeSnippets.BasicParametersAndModifiers<int>() };
+ yield return new[] { RemoveTestMarkup(CodeSnippets.BasicParametersAndModifiers<int>()) };
// Stub with custom string marshaller
- yield return new[] { CodeSnippets.CustomStringMarshallingParametersAndModifiers<string>() };
+ yield return new[] { RemoveTestMarkup(CodeSnippets.CustomStringMarshallingParametersAndModifiers<string>()) };
}
// This test requires precise GC to ensure that we're accurately testing that we aren't
return (new WeakReference(comp2), driver2);
}
}
+
+ private static string RemoveTestMarkup(string sourceWithMarkup)
+ {
+ TestFileMarkupParser.GetSpans(sourceWithMarkup, out string sourceWithoutMarkup, out ImmutableArray<TextSpan> _);
+ return sourceWithoutMarkup;
+ }
}
}
Link="Verifiers\CSharpAnalyzerVerifier.cs"/>
<Compile Include="..\Common\Verifiers\CSharpCodeFixVerifier.cs"
Link="Verifiers\CSharpCodeFixVerifier.cs"/>
+ <Compile Include="..\Common\Verifiers\CSharpSourceGeneratorVerifier.cs"
+ Link="Verifiers\CSharpSourceGeneratorVerifier.cs"/>
<Compile Include="..\Common\Verifiers\CSharpVerifierHelper.cs"
Link="Verifiers\CSharpVerifierHelper.cs"/>
</ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="$(MicrosoftCodeAnalysisVersion)" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.XUnit" Version="$(CompilerPlatformTestingVersion)" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing.XUnit" Version="$(CompilerPlatformTestingVersion)" />
+ <PackageReference Include="Microsoft.CodeAnalysis.CSharp.SourceGenerators.Testing.XUnit" Version="$(CompilerPlatformTestingVersion)" />
</ItemGroup>
<ItemGroup>
using Xunit;
using static Microsoft.Interop.Analyzers.NativeMarshallingAttributeAnalyzer;
-using VerifyCS = LibraryImportGenerator.UnitTests.Verifiers.CSharpAnalyzerVerifier<
+using VerifyCS = Microsoft.Interop.UnitTests.Verifiers.CSharpAnalyzerVerifier<
Microsoft.Interop.Analyzers.NativeMarshallingAttributeAnalyzer>;
namespace LibraryImportGenerator.UnitTests
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using LibraryImportGenerator.UnitTests.Verifiers;
+using Microsoft.Interop.UnitTests.Verifiers;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Testing;