| __`SYSLIB1078`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* |
| __`SYSLIB1079`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* |
| __`SYSLIB1080`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* |
+| __`SYSLIB1081`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* |
+| __`SYSLIB1082`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* |
+| __`SYSLIB1083`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* |
+| __`SYSLIB1084`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* |
+| __`SYSLIB1085`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* |
+| __`SYSLIB1086`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* |
+| __`SYSLIB1087`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* |
+| __`SYSLIB1088`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* |
+| __`SYSLIB1089`__ | *_`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator.* |
+| __`SYSLIB1090`__ | Invalid 'GeneratedComInterfaceAttribute' usage |
### Diagnostic Suppressions (`SYSLIBSUPPRESS****`)
--- /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 Microsoft.CodeAnalysis;
+namespace Microsoft.Interop.Analyzers
+{
+ public static class AnalyzerDiagnostics
+ {
+ public static class Ids
+ {
+ public const string Prefix = "SYSLIB";
+ public const string InvalidGeneratedComAttributeUsage = Prefix + "1090";
+ }
+
+ private const string Category = "ComInterfaceGenerator";
+
+ private static LocalizableResourceString GetResourceString(string resourceName)
+ {
+ return new LocalizableResourceString(resourceName, SR.ResourceManager, typeof(FxResources.Microsoft.Interop.ComInterfaceGenerator.SR));
+ }
+
+ public static readonly DiagnosticDescriptor InterfaceTypeNotSupported =
+ new DiagnosticDescriptor(
+ Ids.InvalidGeneratedComAttributeUsage,
+ GetResourceString(nameof(SR.InterfaceTypeNotSupportedTitle)),
+ GetResourceString(nameof(SR.InterfaceTypeNotSupportedMessage)),
+ Category,
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true,
+ description: GetResourceString(nameof(SR.InterfaceTypeNotSupportedMessage)));
+ }
+}
--- /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.Collections.Immutable;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Diagnostics;
+
+namespace Microsoft.Interop.Analyzers
+{
+ /// <summary>
+ /// Validates that if an interface has GeneratedComInterfaceAttribute and <see cref="InterfaceTypeAttribute"/>,
+ /// the <see cref="InterfaceTypeAttribute"/> is given a <see cref="ComInterfaceType"/> that is supported by the generator.
+ /// </summary>
+ [DiagnosticAnalyzer(LanguageNames.CSharp)]
+ public class GeneratedComInterfaceAttributeAnalyzer : DiagnosticAnalyzer
+ {
+ public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
+ = ImmutableArray.Create(AnalyzerDiagnostics.InterfaceTypeNotSupported);
+
+ public static readonly ImmutableArray<ComInterfaceType> SupportedComInterfaceTypes = ImmutableArray.Create(ComInterfaceType.InterfaceIsIUnknown);
+
+ public override void Initialize(AnalysisContext context)
+ {
+ context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+ context.EnableConcurrentExecution();
+ context.RegisterSymbolAction((context) =>
+ {
+ INamedTypeSymbol typeSymbol = (INamedTypeSymbol)context.Symbol;
+ if (typeSymbol.TypeKind != TypeKind.Interface)
+ return;
+
+ ImmutableArray<AttributeData> customAttributes = typeSymbol.GetAttributes();
+ if (customAttributes.Length == 0)
+ return;
+
+ // Interfaces with both GeneratedComInterfaceAttribute and InterfaceTypeAttribute should only have [InterfaceTypeAttribute(InterfaceIsIUnknown)]
+ if (GetAttribute(typeSymbol, TypeNames.GeneratedComInterfaceAttribute, out _)
+ && GetAttribute(typeSymbol, TypeNames.InterfaceTypeAttribute, out AttributeData? comInterfaceAttribute)
+ && !InterfaceTypeAttributeIsSupported(comInterfaceAttribute, out string unsupportedValue))
+ {
+ context.ReportDiagnostic(comInterfaceAttribute.CreateDiagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported, unsupportedValue));
+ }
+ }, SymbolKind.NamedType);
+ }
+
+ private static bool InterfaceTypeAttributeIsSupported(AttributeData comInterfaceAttribute, out string argument)
+ {
+ if (comInterfaceAttribute.ConstructorArguments.IsEmpty)
+ {
+ argument = "<empty>";
+ return false;
+ }
+ TypedConstant ctorArg0 = comInterfaceAttribute.ConstructorArguments[0];
+ ComInterfaceType interfaceType;
+
+ argument = ctorArg0.ToCSharpString();
+ switch (ctorArg0.Type.ToDisplayString())
+ {
+ case TypeNames.ComInterfaceTypeAttribute:
+ interfaceType = (ComInterfaceType)ctorArg0.Value;
+ break;
+ case TypeNames.System_Int16:
+ case TypeNames.@short:
+ interfaceType = (ComInterfaceType)(short)ctorArg0.Value;
+ break;
+ default:
+ return false;
+ }
+
+ return SupportedComInterfaceTypes.Contains(interfaceType);
+ }
+
+ private static bool GetAttribute(ISymbol symbol, string attributeDisplayName, [NotNullWhen(true)] out AttributeData? attribute)
+ {
+ foreach (AttributeData attr in symbol.GetAttributes())
+ {
+ if (attr.AttributeClass?.ToDisplayString() == attributeDisplayName)
+ {
+ attribute = attr;
+ return true;
+ }
+ }
+
+ attribute = null;
+ return false;
+ }
+ }
+}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using Microsoft.CodeAnalysis;
namespace Microsoft.Interop
{
isEnabledByDefault: true,
description: GetResourceString(nameof(SR.ConfigurationNotSupportedDescription)));
+
private readonly List<Diagnostic> _diagnostics = new List<Diagnostic>();
public IEnumerable<Diagnostic> Diagnostics => _diagnostics;
<data name="InvalidExceptionMarshallingValue" xml:space="preserve">
<value>The provided value is not a known flag of the 'ExceptionMarshalling' enum.</value>
</data>
+ <data name="InterfaceTypeNotSupportedTitle" xml:space="preserve">
+ <value>'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</value>
+ </data>
+ <data name="InterfaceTypeNotSupportedMessage" xml:space="preserve">
+ <value>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</value>
+ </data>
</root>
\ No newline at end of file
<target state="translated">Určenou konfiguraci nepodporují zdrojem generovaná volání P/Invokes.</target>
<note />
</trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedMessage">
+ <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
+ <target state="new">Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedTitle">
+ <source>'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</source>
+ <target state="new">'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</target>
+ <note />
+ </trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingModifiersMessage">
<source>Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'.</source>
<target state="translated">Metoda {0} je obsažena v typu {1}, který není označen jako „partial“. Generování zdrojů volání P/Invoke bude metodu {0} ignorovat.</target>
<target state="translated">Die angegebene Konfiguration wird von quellgenerierten P/Invokes nicht unterstützt.</target>
<note />
</trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedMessage">
+ <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
+ <target state="new">Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedTitle">
+ <source>'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</source>
+ <target state="new">'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</target>
+ <note />
+ </trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingModifiersMessage">
<source>Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'.</source>
<target state="translated">Die Methode \"{0}\" ist in einem Typ \"{1}\" enthalten, der nicht als \"partiell\" gekennzeichnet ist. Die P/Invoke-Quellgenerierung ignoriert die Methode \"{0}\".</target>
<target state="translated">La configuración especificada no está admitida por P/Invokes de un generador de código fuente.</target>
<note />
</trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedMessage">
+ <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
+ <target state="new">Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedTitle">
+ <source>'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</source>
+ <target state="new">'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</target>
+ <note />
+ </trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingModifiersMessage">
<source>Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'.</source>
<target state="translated">El método “{0}” está contenido en un tipo “{1}” que no está marcado como “partial”. La generación de código fuente P/Invoke omitirá el método “{0}”.</target>
<target state="translated">La configuration spécifiée n’est pas prise en charge par les P/Invokes générés par la source.</target>
<note />
</trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedMessage">
+ <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
+ <target state="new">Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedTitle">
+ <source>'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</source>
+ <target state="new">'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</target>
+ <note />
+ </trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingModifiersMessage">
<source>Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'.</source>
<target state="translated">La méthode « {0} » est contenue dans un type « {1} » qui n’est pas marqué comme étant « partial ». La génération source P/Invoke ignore la méthode « {0} ».</target>
<target state="translated">La configurazione specificata non è supportata dai P/Invoke generati dall'origine.</target>
<note />
</trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedMessage">
+ <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
+ <target state="new">Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedTitle">
+ <source>'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</source>
+ <target state="new">'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</target>
+ <note />
+ </trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingModifiersMessage">
<source>Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'.</source>
<target state="translated">Il metodo '{0}' è contenuto in un tipo '{1}' non contrassegnato come 'partial'. Durante la generazione dell'origine P/Invoke il metodo '{0}' verrà ignorato.</target>
<target state="translated">指定された構成は、ソースで生成された P/Invoke ではサポートされていません。</target>
<note />
</trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedMessage">
+ <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
+ <target state="new">Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedTitle">
+ <source>'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</source>
+ <target state="new">'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</target>
+ <note />
+ </trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingModifiersMessage">
<source>Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'.</source>
<target state="translated">メソッド '{0}' は、'partial' とマークされていない型 '{1}' に含まれています。P/Invoke ソース生成はメソッド '{0}' を無視します。</target>
<target state="translated">지정된 구성은 소스 생성 P/Invoke에서 지원되지 않습니다.</target>
<note />
</trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedMessage">
+ <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
+ <target state="new">Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedTitle">
+ <source>'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</source>
+ <target state="new">'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</target>
+ <note />
+ </trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingModifiersMessage">
<source>Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'.</source>
<target state="translated">메서드 '{0}'은(는) 'partial'로 표시되지 않은 '{1}' 형식에 포함되어 있습니다. P/Invoke 소스 생성은 '{0}' 메서드를 무시합니다.</target>
<target state="translated">Określona konfiguracja nie jest obsługiwana przez funkcję P/Invokes generowaną przez źródło.</target>
<note />
</trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedMessage">
+ <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
+ <target state="new">Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedTitle">
+ <source>'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</source>
+ <target state="new">'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</target>
+ <note />
+ </trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingModifiersMessage">
<source>Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'.</source>
<target state="translated">Metoda „{0}” jest zawarta w typie „{1}”, który nie jest oznaczony jako „częściowy”. Generowanie źródła funkcji P/Invoke zignoruje metodę „{0}”.</target>
<target state="translated">A configuração especificada não tem suporte de P/Invokes gerados pela origem.</target>
<note />
</trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedMessage">
+ <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
+ <target state="new">Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedTitle">
+ <source>'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</source>
+ <target state="new">'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</target>
+ <note />
+ </trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingModifiersMessage">
<source>Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'.</source>
<target state="translated">O '{0}' está contido em um tipo '{1}' que não está marcado como 'partial'. A geração de origem P/Invoke ignorará o método '{0}'.</target>
<target state="translated">Указанная конфигурация не поддерживается в P/Invoke с созданием источника.</target>
<note />
</trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedMessage">
+ <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
+ <target state="new">Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedTitle">
+ <source>'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</source>
+ <target state="new">'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</target>
+ <note />
+ </trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingModifiersMessage">
<source>Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'.</source>
<target state="translated">Метод \"{0}\" содержится в типе \"{1}\", который не помечен как \"partial\". Метод \"{0}\" будет игнорироваться при создании источника в P/Invoke.</target>
<target state="translated">Belirtilen yapılandırma, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor.</target>
<note />
</trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedMessage">
+ <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
+ <target state="new">Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedTitle">
+ <source>'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</source>
+ <target state="new">'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</target>
+ <note />
+ </trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingModifiersMessage">
<source>Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'.</source>
<target state="translated">'{0}'metodu, 'partial' olarak işaretlenmemiş olan bir '{1}' türünün içinde yer alıyor. P/Invoke kaynak oluşturma işlemi, '{0}' metodunu yok sayacak.</target>
<target state="translated">源生成的 P/Invoke 不支持指定的配置。</target>
<note />
</trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedMessage">
+ <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
+ <target state="new">Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedTitle">
+ <source>'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</source>
+ <target state="new">'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</target>
+ <note />
+ </trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingModifiersMessage">
<source>Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'.</source>
<target state="translated">方法“{0}”包含在未标记为 “partial” 的类型“{1}”中。P/Invoke 源生成将忽略方法“{0}”。</target>
<target state="translated">来源產生的 P/Invokes 不支援指定的設定。</target>
<note />
</trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedMessage">
+ <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
+ <target state="new">Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="InterfaceTypeNotSupportedTitle">
+ <source>'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</source>
+ <target state="new">'GeneratedComInterfaceType' does not support the 'ComInterfaceType' value supplied to 'InterfaceTypeAttribute' on the same type.</target>
+ <note />
+ </trans-unit>
<trans-unit id="InvalidAttributedMethodContainingTypeMissingModifiersMessage">
<source>Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'.</source>
<target state="translated">方法 '{0}' 包含在未標示為 'partial' 的類型'{1}'中。產生 P/Invoke 来源會忽略方法'{0}'。</target>
public const string System_Type = "System.Type";
+ public const string System_Int16 = "System.Int16";
+ public const string @short = "short";
+
public const string System_Runtime_InteropServices_StructLayoutAttribute = "System.Runtime.InteropServices.StructLayoutAttribute";
public const string System_Runtime_InteropServices_MarshalAsAttribute = "System.Runtime.InteropServices.MarshalAsAttribute";
public const string System_Runtime_InteropServices_DynamicInterfaceCastableImplementationAttribute = "System.Runtime.InteropServices.DynamicInterfaceCastableImplementationAttribute";
+ public const string GeneratedComInterfaceAttribute = "System.Runtime.InteropServices.Marshalling.GeneratedComInterfaceAttribute";
+ public const string InterfaceTypeAttribute = "System.Runtime.InteropServices.InterfaceTypeAttribute";
+ public const string ComInterfaceTypeAttribute = "System.Runtime.InteropServices.ComInterfaceType";
public const string System_Runtime_InteropServices_ComWrappers_ComInterfaceDispatch = "System.Runtime.InteropServices.ComWrappers.ComInterfaceDispatch";
}
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Runtime.InteropServices.Marshalling
+{
+ public interface IComObjectWrapper<T> { }
+
+ public class ComWrappers { }
+
+ public class ComObject : IDynamicInterfaceCastable, IComObjectWrapper<ComObject>
+ {
+ public bool IsInterfaceImplemented(RuntimeTypeHandle th, bool b) => true;
+ public RuntimeTypeHandle GetInterfaceImplementation(RuntimeTypeHandle th) => th;
+ // Implement support for casting through IUnknown.
+ // No thread-affinity aware support.
+ // No IDispatch support.
+ // No aggregation support.
+ }
+
+ public abstract class GeneratedComWrappersBase<TComObject> : ComWrappers
+ {
+ }
+
+ [AttributeUsage(AttributeTargets.Interface)]
+ public class GeneratedComInterfaceAttribute : Attribute
+ {
+ public GeneratedComInterfaceAttribute(Type comWrappersType)
+ => (ComWrappersType) = (comWrappersType);
+
+ public GeneratedComInterfaceAttribute(Type comWrappersType, bool generateManagedObjectWrapper, bool generateComObjectWrapper)
+ => (ComWrappersType, GenerateManagedObjectWrapper, GenerateComObjectWrapper)
+ = (comWrappersType, generateManagedObjectWrapper, generateComObjectWrapper);
+
+ public Type ComWrappersType { get; }
+
+ public bool GenerateManagedObjectWrapper { get; } = true;
+
+ public bool GenerateComObjectWrapper { get; } = true;
+
+ public bool ExportInterfaceDefinition { get; }
+ }
+}
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
Link="Common\CustomStructMarshallingCodeSnippets.cs" />
<Compile Include="..\Common\ICustomMarshallingSignatureTestProvider.cs"
Link="ICustomMarshallingSignatureTestProvider.cs" />
+ <Compile Include="..\Common\Verifiers\CSharpAnalyzerVerifier.cs"
+ Link="Verifiers\CSharpAnalyzerVerifier.cs"/>
+ <Compile Include="..\Common\Verifiers\CSharpCodeFixVerifier.cs"
+ Link="Verifiers\CSharpCodeFixVerifier.cs"/>
+ <Compile Include="..\Common\Verifiers\CSharpVerifierHelper.cs"
+ Link="Verifiers\CSharpVerifierHelper.cs"/>
</ItemGroup>
<ItemGroup>
--- /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.Runtime.InteropServices;
+using System.Threading.Tasks;
+using Microsoft.Interop;
+using Microsoft.Interop.Analyzers;
+using Xunit;
+
+using VerifyCS = LibraryImportGenerator.UnitTests.Verifiers.CSharpAnalyzerVerifier<Microsoft.Interop.Analyzers.GeneratedComInterfaceAttributeAnalyzer>;
+
+namespace ComInterfaceGenerator.Unit.Tests
+{
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/60650", TestRuntimes.Mono)]
+ public class GeneratedComInterfaceAnalyzerTests
+ {
+ static string _usings = $$"""
+ #pragma warning disable CS8019
+ using System.Runtime.InteropServices.Marshalling;
+ using System.Runtime.InteropServices;
+ #pragma warning restore CS8019
+ """;
+
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/60650", TestRuntimes.Mono)]
+ public class InterfaceHasInterfaceTypeAttributeOnly
+ {
+ [Fact]
+ public async Task IUnknown()
+ {
+ string snippet = $$$"""
+
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(_usings + snippet);
+ }
+
+ [Fact]
+ public async Task IUnknownShort()
+ {
+ string snippet = $$$"""
+
+ [InterfaceTypeAttribute((short)1)]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(_usings + snippet);
+ }
+
+ [Fact]
+ public async Task IDispatch()
+ {
+ string snippet =
+ $$$"""
+
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(_usings + snippet);
+ }
+
+ [Fact]
+ public async Task IDispatchShort()
+ {
+ string snippet =
+ $$$"""
+
+ [InterfaceTypeAttribute((short)2)]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(_usings + snippet);
+ }
+
+ [Fact]
+ public async Task IInspectable()
+ {
+ string snippet =
+ $$$"""
+
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIInspectable)]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(_usings + snippet);
+ }
+
+ [Fact]
+ public async Task IInspectableShort()
+ {
+ string snippet =
+ $$$"""
+
+ [InterfaceTypeAttribute((short)3)]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(_usings + snippet);
+ }
+
+ [Fact]
+ public async Task IDual()
+ {
+ string snippet =
+ $$$"""
+
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(_usings + snippet);
+ }
+
+ [Fact]
+ public async Task IDualShort()
+ {
+ string snippet =
+ $$$"""
+
+ [InterfaceTypeAttribute((short)0)]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(_usings + snippet);
+ }
+ }
+
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/60650", TestRuntimes.Mono)]
+ public class InterfaceHasGeneratedComInterfaceAttributeOnly
+ {
+ [Fact]
+ public async Task Test()
+ {
+ string snippet =
+ $$$"""
+
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(_usings + snippet);
+ }
+ }
+
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/60650", TestRuntimes.Mono)]
+ public class InterfaceHasGeneratedComInterfaceAttributeAndInterfaceTypeAttribute
+ {
+ [Fact]
+ public async Task IUnknown()
+ {
+ string snippet =
+ $$$"""
+
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(_usings + snippet);
+ }
+
+ [Fact]
+ public async Task IUnknownShort()
+ {
+ string snippet =
+ $$$"""
+
+ [InterfaceTypeAttribute((short)1)]
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(_usings + snippet);
+ }
+
+ [Fact]
+ public async Task IDispatch()
+ {
+ string snippet =
+ $$$"""
+
+ [{|#0:InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)|}]
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(
+ _usings + snippet,
+ VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
+ .WithLocation(0)
+ .WithArguments(TypeNames.ComInterfaceTypeAttribute + "." + nameof(ComInterfaceType.InterfaceIsIDispatch)));
+ }
+
+ [Fact]
+ public async Task IDispatchShort()
+ {
+ string snippet =
+ $$$"""
+
+ [{|#0:InterfaceTypeAttribute((short)2)|}]
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(
+ _usings + snippet,
+ VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
+ .WithLocation(0)
+ .WithArguments("2"));
+ }
+
+ [Fact]
+ public async Task IInspectable()
+ {
+ string snippet =
+ $$$"""
+
+ [{|#0:InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIInspectable)|}]
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(
+ _usings + snippet,
+ VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
+ .WithLocation(0)
+ .WithArguments(TypeNames.ComInterfaceTypeAttribute + "." + nameof(ComInterfaceType.InterfaceIsIInspectable)));
+ }
+
+ [Fact]
+ public async Task IInspectableShort()
+ {
+ string snippet =
+ $$$"""
+
+ [{|#0:InterfaceTypeAttribute((short)3)|}]
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(
+ _usings + snippet,
+ VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
+ .WithLocation(0)
+ .WithArguments("3"));
+ }
+
+ [Fact]
+ public async Task IDual()
+ {
+ string snippet =
+ $$$"""
+
+ [{|#0:InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)|}]
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(
+ _usings + snippet,
+ VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
+ .WithLocation(0)
+ .WithArguments(TypeNames.ComInterfaceTypeAttribute + "." + nameof(ComInterfaceType.InterfaceIsDual)));
+ }
+
+ [Fact]
+ public async Task IDualShort()
+ {
+ string snippet =
+ $$$"""
+
+ [{|#0:InterfaceTypeAttribute((short)0)|}]
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ interface IFoo
+ {
+ void Bar() {}
+ }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(
+ _usings + snippet,
+ VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
+ .WithLocation(0)
+ .WithArguments("0"));
+ }
+ }
+
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/60650", TestRuntimes.Mono)]
+ public class PartialInterfaceHasGeneratedComInterfaceAttributeAndInterfaceTypeAttribute
+ {
+ [Fact]
+ public async Task IUnknown()
+ {
+ string snippet =
+ $$$"""
+
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ partial interface IFoo
+ {
+ void Bar() {}
+ }
+
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ partial interface IFoo { }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(_usings + snippet);
+ }
+
+ [Fact]
+ public async Task IUnknownShort()
+ {
+ string snippet =
+ $$$"""
+
+ [InterfaceTypeAttribute((short)1)]
+ partial interface IFoo
+ {
+ void Bar() {}
+ }
+
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ partial interface IFoo { }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(_usings + snippet);
+ }
+
+ [Fact]
+ public async Task IDispatch()
+ {
+ string snippet =
+ $$$"""
+
+ [{|#0:InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)|}]
+ partial interface IFoo
+ {
+ void Bar() {}
+ }
+
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ partial interface IFoo { }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(
+ _usings + snippet,
+ VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
+ .WithLocation(0)
+ .WithArguments(TypeNames.ComInterfaceTypeAttribute + "." + nameof(ComInterfaceType.InterfaceIsIDispatch)));
+ }
+
+ [Fact]
+ public async Task IDispatchShort()
+ {
+ string snippet =
+ $$$"""
+
+ [{|#0:InterfaceTypeAttribute((short)2)|}]
+ partial interface IFoo
+ {
+ void Bar() {}
+ }
+
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ partial interface IFoo { }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(
+ _usings + snippet,
+ VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
+ .WithLocation(0)
+ .WithArguments("2"));
+ }
+
+ [Fact]
+ public async Task IInspectable()
+ {
+ string snippet =
+ $$$"""
+
+ [{|#0:InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIInspectable)|}]
+ partial interface IFoo
+ {
+ void Bar() {}
+ }
+
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ partial interface IFoo { }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(
+ _usings + snippet,
+ VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
+ .WithLocation(0)
+ .WithArguments(TypeNames.ComInterfaceTypeAttribute + "." + nameof(ComInterfaceType.InterfaceIsIInspectable)));
+ }
+
+ [Fact]
+ public async Task IInspectableShort()
+ {
+ string snippet =
+ $$$"""
+
+ [{|#0:InterfaceTypeAttribute((short)3)|}]
+ partial interface IFoo
+ {
+ void Bar() {}
+ }
+
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ partial interface IFoo { }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(
+ _usings + snippet,
+ VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
+ .WithLocation(0)
+ .WithArguments("3"));
+ }
+
+ [Fact]
+ public async Task IDual()
+ {
+ string snippet =
+ $$$"""
+
+ [{|#0:InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)|}]
+ partial interface IFoo
+ {
+ void Bar() {}
+ }
+
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ partial interface IFoo { }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(
+ _usings + snippet,
+ VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
+ .WithLocation(0)
+ .WithArguments(TypeNames.ComInterfaceTypeAttribute + "." + nameof(ComInterfaceType.InterfaceIsDual)));
+ }
+
+ [Fact]
+ public async Task IDualShort()
+ {
+ string snippet =
+ $$$"""
+
+ [{|#0:InterfaceTypeAttribute((short)0)|}]
+ partial interface IFoo
+ {
+ void Bar() {}
+ }
+
+ [GeneratedComInterface(typeof(MyComWrappers))]
+ partial interface IFoo { }
+
+ public partial class MyComWrappers : GeneratedComWrappersBase<ComObject>
+ {
+ }
+
+ """;
+ await VerifyCS.VerifyAnalyzerAsync(
+ _usings + snippet,
+ VerifyCS.Diagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported)
+ .WithLocation(0)
+ .WithArguments("0"));
+ }
+ }
+ }
+}
using System;
using System.Collections.Immutable;
+using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
-using Microsoft;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
new CompilationWithAnalyzersOptions(
options,
onAnalyzerException: null,
- concurrentAnalysis: true,
+ concurrentAnalysis: !Debugger.IsAttached,
logAnalyzerExecutionTime: true,
reportSuppressedDiagnostics: false,
analyzerExceptionFilter: ex =>
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
Link="Common\CustomStructMarshallingCodeSnippets.cs" />
<Compile Include="..\Common\ICustomMarshallingSignatureTestProvider.cs"
Link="ICustomMarshallingSignatureTestProvider.cs" />
+ <Compile Include="..\Common\Verifiers\CSharpAnalyzerVerifier.cs"
+ Link="Verifiers\CSharpAnalyzerVerifier.cs"/>
+ <Compile Include="..\Common\Verifiers\CSharpCodeFixVerifier.cs"
+ Link="Verifiers\CSharpCodeFixVerifier.cs"/>
+ <Compile Include="..\Common\Verifiers\CSharpVerifierHelper.cs"
+ Link="Verifiers\CSharpVerifierHelper.cs"/>
</ItemGroup>
<ItemGroup>