[ComInterfaceGenerator] Warn if StringMarshalling doesn't match base and warn if...
authorJackson Schuster <36744439+jtschuster@users.noreply.github.com>
Wed, 24 May 2023 17:44:05 +0000 (10:44 -0700)
committerGitHub <noreply@github.com>
Wed, 24 May 2023 17:44:05 +0000 (10:44 -0700)
29 files changed:
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceContext.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceInfo.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratedComInterfaceAttributeData.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/LocationInfo.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/Strings.resx
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.cs.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.de.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.es.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.fr.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.it.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ja.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ko.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pl.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pt-BR.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ru.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.tr.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hans.xlf
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hant.xlf
src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportData.cs
src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/InteropAttributeData.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CompileFails.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/GeneratedComInterfaceAttributeProvider.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/IComInterfaceAttributeProvider.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/IVirtualMethodIndexSignatureProvider.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/VirtualMethodIndexAttributeProvider.cs

index 0eee960..94a8fb6 100644 (file)
@@ -1,9 +1,13 @@
 // 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.Generic;
 using System.Collections.Immutable;
+using System.Diagnostics;
 using System.Threading;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
 
 namespace Microsoft.Interop
 {
@@ -12,15 +16,15 @@ namespace Microsoft.Interop
         /// <summary>
         /// Takes a list of ComInterfaceInfo, and creates a list of ComInterfaceContext.
         /// </summary>
-        public static ImmutableArray<ComInterfaceContext> GetContexts(ImmutableArray<ComInterfaceInfo> data, CancellationToken _)
+        public static ImmutableArray<(ComInterfaceContext? Context, Diagnostic? Diagnostic)> GetContexts(ImmutableArray<ComInterfaceInfo> data, CancellationToken _)
         {
-            Dictionary<string, ComInterfaceInfo> symbolToInterfaceInfoMap = new();
-            var accumulator = ImmutableArray.CreateBuilder<ComInterfaceContext>(data.Length);
+            Dictionary<string, ComInterfaceInfo> nameToInterfaceInfoMap = new();
+            var accumulator = ImmutableArray.CreateBuilder<(ComInterfaceContext? Context, Diagnostic? Diagnostic)>(data.Length);
             foreach (var iface in data)
             {
-                symbolToInterfaceInfoMap.Add(iface.ThisInterfaceKey, iface);
+                nameToInterfaceInfoMap.Add(iface.ThisInterfaceKey, iface);
             }
-            Dictionary<string, ComInterfaceContext> symbolToContextMap = new();
+            Dictionary<string, (ComInterfaceContext? Context, Diagnostic? Diagnostic)> nameToContextCache = new();
 
             foreach (var iface in data)
             {
@@ -28,9 +32,9 @@ namespace Microsoft.Interop
             }
             return accumulator.MoveToImmutable();
 
-            ComInterfaceContext AddContext(ComInterfaceInfo iface)
+            (ComInterfaceContext? Context, Diagnostic? Diagnostic) AddContext(ComInterfaceInfo iface)
             {
-                if (symbolToContextMap.TryGetValue(iface.ThisInterfaceKey, out var cachedValue))
+                if (nameToContextCache.TryGetValue(iface.ThisInterfaceKey, out var cachedValue))
                 {
                     return cachedValue;
                 }
@@ -38,18 +42,41 @@ namespace Microsoft.Interop
                 if (iface.BaseInterfaceKey is null)
                 {
                     var baselessCtx = new ComInterfaceContext(iface, null);
-                    symbolToContextMap[iface.ThisInterfaceKey] = baselessCtx;
-                    return baselessCtx;
+                    nameToContextCache[iface.ThisInterfaceKey] = (baselessCtx, null);
+                    return (baselessCtx, null);
                 }
 
-                if (!symbolToContextMap.TryGetValue(iface.BaseInterfaceKey, out var baseContext))
+                if (
+                    // Cached base info has a diagnostic - failure
+                    (nameToContextCache.TryGetValue(iface.BaseInterfaceKey, out var basePair) && basePair.Diagnostic is not null)
+                    // Cannot find base ComInterfaceInfo - failure (failed ComInterfaceInfo creation)
+                    || !nameToInterfaceInfoMap.TryGetValue(iface.BaseInterfaceKey, out var baseInfo)
+                    // Newly calculated base context pair has a diagnostic - failure
+                    || (AddContext(baseInfo) is { } baseReturnPair && baseReturnPair.Diagnostic is not null))
                 {
-                    baseContext = AddContext(symbolToInterfaceInfoMap[iface.BaseInterfaceKey]);
+                    // The base has failed generation at some point, so this interface cannot be generated
+                    (ComInterfaceContext, Diagnostic?) diagnosticPair = (null,
+                        Diagnostic.Create(
+                            GeneratorDiagnostics.BaseInterfaceIsNotGenerated,
+                            iface.DiagnosticLocation.AsLocation(), iface.ThisInterfaceKey, iface.BaseInterfaceKey));
+                    nameToContextCache[iface.ThisInterfaceKey] = diagnosticPair;
+                    return diagnosticPair;
                 }
+                var baseContext = basePair.Context ?? baseReturnPair.Context;
+                Debug.Assert(baseContext != null);
                 var ctx = new ComInterfaceContext(iface, baseContext);
-                symbolToContextMap[iface.ThisInterfaceKey] = ctx;
-                return ctx;
+                (ComInterfaceContext, Diagnostic?) contextPair = (ctx, null);
+                nameToContextCache[iface.ThisInterfaceKey] = contextPair;
+                return contextPair;
             }
         }
+
+        internal ComInterfaceContext GetTopLevelBase()
+        {
+            var currBase = Base;
+            while (currBase is not null)
+                currBase = currBase.Base;
+            return currBase;
+        }
     }
 }
index 4165e7a..5497794 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
+using System.Collections.Generic;
 using System.Collections.Immutable;
 using System.IO;
 using System.Linq;
@@ -52,13 +53,21 @@ namespace Microsoft.Interop
 
             var interfaceSymbolsWithoutDiagnostics = interfaceSymbolAndDiagnostics
                 .Where(data => data.Diagnostic is null)
-                .Select((data, ct) =>
-                (data.InterfaceInfo, data.Symbol));
+                .Select((data, ct) => (data.InterfaceInfo, data.Symbol));
 
-            var interfaceContexts = interfaceSymbolsWithoutDiagnostics
+            var interfaceContextsAndDiagnostics = interfaceSymbolsWithoutDiagnostics
                 .Select((data, ct) => data.InterfaceInfo!)
                 .Collect()
                 .SelectMany(ComInterfaceContext.GetContexts);
+            context.RegisterDiagnostics(interfaceContextsAndDiagnostics.Select((data, ct) => data.Diagnostic));
+            var interfaceContexts = interfaceContextsAndDiagnostics
+                .Where(data => data.Context is not null)
+                .Select((data, ct) => data.Context!);
+            // Filter down interface symbols to remove those with diagnostics from GetContexts
+            interfaceSymbolsWithoutDiagnostics = interfaceSymbolsWithoutDiagnostics
+                .Zip(interfaceContextsAndDiagnostics)
+                .Where(data => data.Right.Diagnostic is null)
+                .Select((data, ct) => data.Left);
 
             var comMethodsAndSymbolsAndDiagnostics = interfaceSymbolsWithoutDiagnostics.Select(ComMethodInfo.GetMethodsFromInterface);
             context.RegisterDiagnostics(comMethodsAndSymbolsAndDiagnostics.SelectMany(static (methodList, ct) => methodList.Select(m => m.Diagnostic)));
@@ -78,6 +87,10 @@ namespace Microsoft.Interop
                 .Collect()
                 .SelectMany(static (data, ct) =>
                 {
+                    return data.GroupBy(data => data.Left.GetTopLevelBase());
+                })
+                .SelectMany(static (data, ct) =>
+                {
                     return ComMethodContext.CalculateAllMethods(data, ct);
                 });
 
@@ -239,16 +252,6 @@ namespace Microsoft.Interop
                 }
             }
 
-            AttributeData? generatedComAttribute = null;
-            foreach (var attr in symbol.ContainingType.GetAttributes())
-            {
-                if (generatedComAttribute is null
-                    && attr.AttributeClass?.ToDisplayString() == TypeNames.GeneratedComInterfaceAttribute)
-                {
-                    generatedComAttribute = attr;
-                }
-            }
-
             var generatorDiagnostics = new GeneratorDiagnostics();
 
             if (lcidConversionAttr is not null)
@@ -257,12 +260,8 @@ namespace Microsoft.Interop
                 generatorDiagnostics.ReportConfigurationNotSupported(lcidConversionAttr, nameof(TypeNames.LCIDConversionAttribute));
             }
 
-            var generatedComInterfaceAttributeData = new InteropAttributeCompilationData();
-            if (generatedComAttribute is not null)
-            {
-                var args = generatedComAttribute.NamedArguments.ToImmutableDictionary();
-                generatedComInterfaceAttributeData = generatedComInterfaceAttributeData.WithValuesFromNamedArguments(args);
-            }
+            GeneratedComInterfaceCompilationData.TryGetGeneratedComInterfaceAttributeFromInterface(symbol.ContainingType, out var generatedComAttribute);
+            var generatedComInterfaceAttributeData = GeneratedComInterfaceCompilationData.GetDataFromAttribute(generatedComAttribute);
             // Create the stub.
             var signatureContext = SignatureContext.Create(
                 symbol,
index 23d56f7..533eb8c 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
+using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Microsoft.CodeAnalysis;
@@ -20,7 +21,8 @@ namespace Microsoft.Interop
         InterfaceDeclarationSyntax Declaration,
         ContainingSyntaxContext TypeDefinitionContext,
         ContainingSyntax ContainingSyntax,
-        Guid InterfaceId)
+        Guid InterfaceId,
+        LocationInfo DiagnosticLocation)
     {
         public static (ComInterfaceInfo? Info, Diagnostic? Diagnostic) From(INamedTypeSymbol symbol, InterfaceDeclarationSyntax syntax)
         {
@@ -58,14 +60,63 @@ namespace Microsoft.Interop
             if (!TryGetBaseComInterface(symbol, syntax, out INamedTypeSymbol? baseSymbol, out Diagnostic? baseDiagnostic))
                 return (null, baseDiagnostic);
 
-            return (new ComInterfaceInfo(
-                ManagedTypeInfo.CreateTypeInfoForTypeSymbol(symbol),
-                symbol.ToDisplayString(),
-                baseSymbol?.ToDisplayString(),
-                syntax,
-                new ContainingSyntaxContext(syntax),
-                new ContainingSyntax(syntax.Modifiers, syntax.Kind(), syntax.Identifier, syntax.TypeParameterList),
-                guid ?? Guid.Empty), null);
+            if (!StringMarshallingIsValid(symbol, syntax, baseSymbol, out Diagnostic? stringMarshallingDiagnostic))
+                return (null, stringMarshallingDiagnostic);
+
+            return (
+                new ComInterfaceInfo(
+                    ManagedTypeInfo.CreateTypeInfoForTypeSymbol(symbol),
+                    symbol.ToDisplayString(),
+                    baseSymbol?.ToDisplayString(),
+                    syntax,
+                    new ContainingSyntaxContext(syntax),
+                    new ContainingSyntax(syntax.Modifiers, syntax.Kind(), syntax.Identifier, syntax.TypeParameterList),
+                    guid ?? Guid.Empty,
+                    LocationInfo.From(symbol)),
+                null);
+        }
+
+        private static bool StringMarshallingIsValid(INamedTypeSymbol symbol, InterfaceDeclarationSyntax syntax, INamedTypeSymbol? baseSymbol, [NotNullWhen(false)] out Diagnostic? stringMarshallingDiagnostic)
+        {
+            var attrInfo = GeneratedComInterfaceData.From(GeneratedComInterfaceCompilationData.GetAttributeDataFromInterfaceSymbol(symbol));
+            if (attrInfo.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshalling) || attrInfo.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshallingCustomType))
+            {
+                if (attrInfo.StringMarshalling is StringMarshalling.Custom && attrInfo.StringMarshallingCustomType is null)
+                {
+                    stringMarshallingDiagnostic = Diagnostic.Create(
+                        GeneratorDiagnostics.InvalidStringMarshallingConfigurationOnInterface,
+                        syntax.Identifier.GetLocation(),
+                        symbol.ToDisplayString(),
+                        SR.InvalidStringMarshallingConfigurationMissingCustomType);
+                    return false;
+                }
+                if (attrInfo.StringMarshalling is not StringMarshalling.Custom && attrInfo.StringMarshallingCustomType is not null)
+                {
+                    stringMarshallingDiagnostic = Diagnostic.Create(
+                        GeneratorDiagnostics.InvalidStringMarshallingConfigurationOnInterface,
+                        syntax.Identifier.GetLocation(),
+                        symbol.ToDisplayString(),
+                        SR.InvalidStringMarshallingConfigurationNotCustom);
+                    return false;
+                }
+            }
+            if (baseSymbol is not null)
+            {
+                var baseAttrInfo = GeneratedComInterfaceData.From(GeneratedComInterfaceCompilationData.GetAttributeDataFromInterfaceSymbol(baseSymbol));
+                // The base can be undefined string marshalling
+                if ((baseAttrInfo.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshalling) || baseAttrInfo.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshallingCustomType))
+                    && baseAttrInfo != attrInfo)
+                {
+                    stringMarshallingDiagnostic = Diagnostic.Create(
+                        GeneratorDiagnostics.InvalidStringMarshallingMismatchBetweenBaseAndDerived,
+                        syntax.Identifier.GetLocation(),
+                        symbol.ToDisplayString(),
+                        SR.GeneratedComInterfaceStringMarshallingMustMatchBase);
+                    return false;
+                }
+            }
+            stringMarshallingDiagnostic = null;
+            return true;
         }
 
         /// <summary>
index daf7c14..f4aa897 100644 (file)
@@ -109,6 +109,7 @@ namespace Microsoft.Interop
                 .WithAttributeLists(List<AttributeListSyntax>())
                 .WithExplicitInterfaceSpecifier(ExplicitInterfaceSpecifier(
                     ParseName(OriginalDeclaringInterface.Info.Type.FullTypeName)))
+                .WithParameterList(ParameterList(SeparatedList(GenerationContext.SignatureContext.StubParameters)))
                 .WithExpressionBody(ArrowExpressionClause(
                     ThrowExpression(
                         ObjectCreationExpression(
diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratedComInterfaceAttributeData.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratedComInterfaceAttributeData.cs
new file mode 100644 (file)
index 0000000..f8c42b2
--- /dev/null
@@ -0,0 +1,68 @@
+// 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.Generic;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Text;
+using Microsoft.CodeAnalysis;
+
+namespace Microsoft.Interop
+{
+    /// <summary>
+    /// Contains the data related to a GeneratedComInterfaceAttribute, without references to Roslyn symbols.
+    /// See <seealso cref="GeneratedComInterfaceCompilationData"/> for a type with a reference to the StringMarshallingCustomType
+    /// </summary>
+    internal sealed record GeneratedComInterfaceData : InteropAttributeData
+    {
+        public static GeneratedComInterfaceData From(GeneratedComInterfaceCompilationData generatedComInterfaceAttr)
+            => new GeneratedComInterfaceData() with
+            {
+                IsUserDefined = generatedComInterfaceAttr.IsUserDefined,
+                SetLastError = generatedComInterfaceAttr.SetLastError,
+                StringMarshalling = generatedComInterfaceAttr.StringMarshalling,
+                StringMarshallingCustomType = generatedComInterfaceAttr.StringMarshallingCustomType is not null
+                    ? ManagedTypeInfo.CreateTypeInfoForTypeSymbol(generatedComInterfaceAttr.StringMarshallingCustomType)
+                    : null
+            };
+    }
+
+    /// <summary>
+    /// Contains the data related to a GeneratedComInterfaceAttribute, with references to Roslyn symbols.
+    /// Use <seealso cref="GeneratedComInterfaceData"/> instead when using for incremental compilation state to avoid keeping a compilation alive
+    /// </summary>
+    internal sealed record GeneratedComInterfaceCompilationData : InteropAttributeCompilationData
+    {
+        public static bool TryGetGeneratedComInterfaceAttributeFromInterface(INamedTypeSymbol interfaceSymbol, [NotNullWhen(true)] out AttributeData? generatedComInterfaceAttribute)
+        {
+            generatedComInterfaceAttribute = null;
+            foreach (var attr in interfaceSymbol.GetAttributes())
+            {
+                if (generatedComInterfaceAttribute is null
+                    && attr.AttributeClass?.ToDisplayString() == TypeNames.GeneratedComInterfaceAttribute)
+                {
+                    generatedComInterfaceAttribute = attr;
+                }
+            }
+            return generatedComInterfaceAttribute is not null;
+        }
+
+        public static GeneratedComInterfaceCompilationData GetAttributeDataFromInterfaceSymbol(INamedTypeSymbol interfaceSymbol)
+        {
+            bool found = TryGetGeneratedComInterfaceAttributeFromInterface(interfaceSymbol, out var attr);
+            Debug.Assert(found);
+            return GetDataFromAttribute(attr);
+        }
+
+        public static GeneratedComInterfaceCompilationData GetDataFromAttribute(AttributeData attr)
+        {
+            Debug.Assert(attr.AttributeClass.ToDisplayString() == TypeNames.GeneratedComInterfaceAttribute);
+            var generatedComInterfaceAttributeData = new GeneratedComInterfaceCompilationData();
+            var args = attr.NamedArguments.ToImmutableDictionary();
+            generatedComInterfaceAttributeData = generatedComInterfaceAttributeData.WithValuesFromNamedArguments(args);
+            return generatedComInterfaceAttributeData;
+        }
+    }
+}
index 69e6d91..2c47e3f 100644 (file)
@@ -24,6 +24,7 @@ namespace Microsoft.Interop
             public const string InvalidGeneratedComInterfaceAttributeUsage = Prefix + "1092";
             public const string MultipleComInterfaceBaseTypes = Prefix + "1093";
             public const string AnalysisFailed = Prefix + "1094";
+            public const string BaseInterfaceFailedGeneration = Prefix + "1095";
         }
 
         private const string Category = "ComInterfaceGenerator";
@@ -58,11 +59,31 @@ namespace Microsoft.Interop
             isEnabledByDefault: true,
             description: GetResourceString(nameof(SR.InvalidAttributedMethodDescription)));
 
-        public static readonly DiagnosticDescriptor InvalidStringMarshallingConfiguration =
+        public static readonly DiagnosticDescriptor InvalidStringMarshallingMismatchBetweenBaseAndDerived =
+            new DiagnosticDescriptor(
+                Ids.InvalidGeneratedComInterfaceAttributeUsage,
+            GetResourceString(nameof(SR.InvalidGeneratedComInterfaceAttributeUsageTitle)),
+            GetResourceString(nameof(SR.InvalidStringMarshallingConfigurationOnInterfaceMessage)),
+            Category,
+            DiagnosticSeverity.Error,
+            isEnabledByDefault: true,
+            description: GetResourceString(nameof(SR.GeneratedComInterfaceStringMarshallingMustMatchBase)));
+
+        public static readonly DiagnosticDescriptor InvalidStringMarshallingConfigurationOnMethod =
             new DiagnosticDescriptor(
             Ids.InvalidLibraryImportAttributeUsage,
             GetResourceString(nameof(SR.InvalidVirtualMethodIndexAttributeUsage)),
-            GetResourceString(nameof(SR.InvalidStringMarshallingConfigurationMessage)),
+            GetResourceString(nameof(SR.InvalidStringMarshallingConfigurationOnMethodMessage)),
+            Category,
+            DiagnosticSeverity.Error,
+            isEnabledByDefault: true,
+            description: GetResourceString(nameof(SR.InvalidStringMarshallingConfigurationDescription)));
+
+        public static readonly DiagnosticDescriptor InvalidStringMarshallingConfigurationOnInterface =
+            new DiagnosticDescriptor(
+            Ids.InvalidGeneratedComInterfaceAttributeUsage,
+            GetResourceString(nameof(SR.InvalidGeneratedComInterfaceAttributeUsageTitle)),
+            GetResourceString(nameof(SR.InvalidStringMarshallingConfigurationOnInterfaceMessage)),
             Category,
             DiagnosticSeverity.Error,
             isEnabledByDefault: true,
@@ -214,7 +235,7 @@ namespace Microsoft.Interop
                 GetResourceString(nameof(SR.AnalysisFailedTitle)),
                 GetResourceString(nameof(SR.AnalysisFailedMethodMessage)),
                 Category,
-                DiagnosticSeverity.Warning,
+                DiagnosticSeverity.Error,
                 isEnabledByDefault: true,
                 description: GetResourceString(nameof(SR.AnalysisFailedDescription)));
 
@@ -224,10 +245,20 @@ namespace Microsoft.Interop
                 GetResourceString(nameof(SR.AnalysisFailedTitle)),
                 GetResourceString(nameof(SR.AnalysisFailedInterfaceMessage)),
                 Category,
-                DiagnosticSeverity.Warning,
+                DiagnosticSeverity.Error,
                 isEnabledByDefault: true,
                 description: GetResourceString(nameof(SR.AnalysisFailedDescription)));
 
+        public static readonly DiagnosticDescriptor BaseInterfaceIsNotGenerated =
+            new DiagnosticDescriptor(
+                Ids.BaseInterfaceFailedGeneration,
+                GetResourceString(nameof(SR.BaseInterfaceCannotBeGeneratedTitle)),
+                GetResourceString(nameof(SR.BaseInterfaceCannotBeGeneratedMessage)),
+                Category,
+                DiagnosticSeverity.Error,
+                isEnabledByDefault: true,
+                description: GetResourceString(nameof(SR.BaseInterfaceCannotBeGeneratedDescription)));
+
         private readonly List<Diagnostic> _diagnostics = new List<Diagnostic>();
 
         public IEnumerable<Diagnostic> Diagnostics => _diagnostics;
@@ -246,7 +277,7 @@ namespace Microsoft.Interop
         {
             _diagnostics.Add(
                 attributeData.CreateDiagnostic(
-                    GeneratorDiagnostics.InvalidStringMarshallingConfiguration,
+                    GeneratorDiagnostics.InvalidStringMarshallingConfigurationOnMethod,
                     methodName,
                     detailsMessage));
         }
diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/LocationInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/LocationInfo.cs
new file mode 100644 (file)
index 0000000..982e1ca
--- /dev/null
@@ -0,0 +1,29 @@
+// 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.Text;
+
+namespace Microsoft.Interop
+{
+    /// <summary>
+    /// Contains data required to reconstruct a <see cref="Location"/> without keeping any symbols or references to a <see cref="Compilation"/>
+    /// </summary>
+    internal sealed record LocationInfo(
+        LinePositionSpan LinePositionSpan,
+        string FilePath,
+        TextSpan TextSpan)
+    {
+        public Location AsLocation() => Location.Create(FilePath, TextSpan, LinePositionSpan);
+
+        public static LocationInfo From(ISymbol symbol)
+        {
+            var location = symbol.Locations[0];
+            var lineSpan = location.GetLineSpan().Span;
+            var filePath = location.SourceTree.FilePath;
+            var textSpan = location.SourceSpan;
+
+            return new LocationInfo(lineSpan, filePath, textSpan);
+        }
+    }
+}
index ad3eaf5..f797fce 100644 (file)
@@ -1,17 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
 <root>
-  <!--
-    Microsoft ResX Schema
-
+  <!-- 
+    Microsoft ResX Schema 
+    
     Version 2.0
-
-    The primary goals of this format is to allow a simple XML format
-    that is mostly human readable. The generation and parsing of the
-    various data types are done through the TypeConverter classes
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
     associated with the data types.
-
+    
     Example:
-
+    
     ... ado.net/XML headers & schema ...
     <resheader name="resmimetype">text/microsoft-resx</resheader>
     <resheader name="version">2.0</resheader>
         <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
         <comment>This is a comment</comment>
     </data>
-
-    There are any number of "resheader" rows that contain simple
+                
+    There are any number of "resheader" rows that contain simple 
     name/value pairs.
-
-    Each data row contains a name, and value. The row also contains a
-    type or mimetype. Type corresponds to a .NET class that support
-    text/value conversion through the TypeConverter architecture.
-    Classes that don't support this are serialized and stored with the
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
     mimetype set.
-
-    The mimetype is used for serialized objects, and tells the
-    ResXResourceReader how to depersist the object. This is currently not
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
     extensible. For a given mimetype the value must be set accordingly:
-
-    Note - application/x-microsoft.net.object.binary.base64 is the format
-    that the ResXResourceWriter will generate, however the reader can
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
     read any of the formats listed below.
-
+    
     mimetype: application/x-microsoft.net.object.binary.base64
-    value   : The object must be serialized with
+    value   : The object must be serialized with 
             : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
             : and then encoded with base64 encoding.
-
+    
     mimetype: application/x-microsoft.net.object.soap.base64
-    value   : The object must be serialized with
+    value   : The object must be serialized with 
             : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
             : and then encoded with base64 encoding.
 
     mimetype: application/x-microsoft.net.object.bytearray.base64
-    value   : The object must be serialized into a byte array
+    value   : The object must be serialized into a byte array 
             : using a System.ComponentModel.TypeConverter
             : and then encoded with base64 encoding.
     -->
   <data name="InvalidStringMarshallingConfigurationDescription" xml:space="preserve">
     <value>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid.</value>
   </data>
-  <data name="InvalidStringMarshallingConfigurationMessage" xml:space="preserve">
+  <data name="InvalidStringMarshallingConfigurationOnMethodMessage" xml:space="preserve">
     <value>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</value>
     <comment>{1} is a message containing additional details about what is not valid</comment>
   </data>
   <data name="AnalysisFailedTitle" xml:space="preserve">
     <value>Analysis for generation has failed.</value>
   </data>
-</root>
+  <data name="GeneratedComInterfaceStringMarshallingMustMatchBase" xml:space="preserve">
+    <value>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</value>
+  </data>
+  <data name="BaseInterfaceCannotBeGeneratedDescription" xml:space="preserve">
+    <value>COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</value>
+  </data>
+  <data name="BaseInterfaceCannotBeGeneratedMessage" xml:space="preserve">
+    <value>COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</value>
+  </data>
+  <data name="BaseInterfaceCannotBeGeneratedTitle" xml:space="preserve">
+    <value>The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</value>
+  </data>
+  <data name="InvalidStringMarshallingConfigurationOnInterfaceMessage" xml:space="preserve">
+    <value>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</value>
+  </data>
+</root>
\ No newline at end of file
index 04074de..1c0d66c 100644 (file)
         <target state="translated">Analýza pro generování se nezdařila</target>
         <note />
       </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedDescription">
+        <source>COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</source>
+        <target state="new">COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedMessage">
+        <source>COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</source>
+        <target state="new">COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedTitle">
+        <source>The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</source>
+        <target state="new">The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="needs-review-translation">Zdrojem generovaná volání P/Invokes budou ignorovat všechny nepodporované konfigurace.</target>
         <target state="needs-review-translation">Určenou konfiguraci nepodporují zdrojem generovaná volání P/Invokes.</target>
         <note />
       </trans-unit>
+      <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="InterfaceTypeNotSupportedMessage">
         <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
         <target state="translated">Použití GeneratedComInterfaceAttribute a InterfaceTypeAttribute se nepodporuje s hodnotou ComInterfaceType {0}.</target>
         <target state="translated">Konfigurace StringMarshalling a StringMarshallingCustomType je neplatná.</target>
         <note />
       </trans-unit>
-      <trans-unit id="InvalidStringMarshallingConfigurationMessage">
-        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
-        <target state="translated">Konfigurace StringMarshalling a StringMarshallingCustomType u metody {0} je neplatná. {1}</target>
-        <note>{1} is a message containing additional details about what is not valid</note>
-      </trans-unit>
       <trans-unit id="InvalidStringMarshallingConfigurationMissingCustomType">
         <source>'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'.</source>
         <target state="translated">StringMarshallingCustomType musí být určený, pokud je StringMarshalling nastavený na StringMarshalling.Custom.</target>
         <target state="translated">StringMarshalling by měl být nastavený na StringMarshalling.Custom, když je pokud je určený StringMarshallingCustomType.</target>
         <note />
       </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnInterfaceMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnMethodMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</target>
+        <note>{1} is a message containing additional details about what is not valid</note>
+      </trans-unit>
       <trans-unit id="InvalidVirtualMethodIndexAttributeUsage">
         <source>Invalid 'VirtualMethodIndexAttribute' usage</source>
         <target state="translated">Neplatné použití VirtualMethodIndexAttribute</target>
index f87f9a5..1f498be 100644 (file)
         <target state="translated">Fehler bei der Analyse für die Generierung.</target>
         <note />
       </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedDescription">
+        <source>COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</source>
+        <target state="new">COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedMessage">
+        <source>COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</source>
+        <target state="new">COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedTitle">
+        <source>The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</source>
+        <target state="new">The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="needs-review-translation">Quellgenerierte P/Invokes ignorieren alle Konfigurationen, die nicht unterstützt werden.</target>
         <target state="needs-review-translation">Die angegebene Konfiguration wird von quellgenerierten P/Invokes nicht unterstützt.</target>
         <note />
       </trans-unit>
+      <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="InterfaceTypeNotSupportedMessage">
         <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
         <target state="translated">Die Verwendung von „GeneratedComInterfaceAttribute“ und „InterfaceTypeAttribute“ wird mit dem ComInterfaceType-Wert „{0}“ nicht unterstützt.</target>
         <target state="translated">Die Konfiguration von \"StringMarshalling\" und \"StringMarshallingCustomType\" ist ungültig.</target>
         <note />
       </trans-unit>
-      <trans-unit id="InvalidStringMarshallingConfigurationMessage">
-        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
-        <target state="translated">Die Konfiguration von \"StringMarshalling\" und \"StringMarshallingCustomType\" für die Methode \"{0}\" ist ungültig. {1}</target>
-        <note>{1} is a message containing additional details about what is not valid</note>
-      </trans-unit>
       <trans-unit id="InvalidStringMarshallingConfigurationMissingCustomType">
         <source>'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'.</source>
         <target state="translated">\"StringMarshallingCustomType\" muss angegeben werden, wenn \"StringMarshalling\" auf \"StringMarshalling.Custom\" festgelegt ist.</target>
         <target state="translated">\"StringMarshalling\" muss auf \"StringMarshalling.Custom\" festgelegt werden, wenn \"StringMarshallingCustomType\" angegeben ist.</target>
         <note />
       </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnInterfaceMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnMethodMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</target>
+        <note>{1} is a message containing additional details about what is not valid</note>
+      </trans-unit>
       <trans-unit id="InvalidVirtualMethodIndexAttributeUsage">
         <source>Invalid 'VirtualMethodIndexAttribute' usage</source>
         <target state="translated">Ungültige Verwendung von „VirtualMethodIndexAttribute“</target>
index ab93921..47607c0 100644 (file)
         <target state="translated">Error en el análisis de generación.</target>
         <note />
       </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedDescription">
+        <source>COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</source>
+        <target state="new">COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedMessage">
+        <source>COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</source>
+        <target state="new">COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedTitle">
+        <source>The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</source>
+        <target state="new">The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="needs-review-translation">Los P/Invoke de un generador de código fuente omitirán cualquier configuración que no esté admitida.</target>
         <target state="needs-review-translation">La configuración especificada no está admitida por P/Invokes de un generador de código fuente.</target>
         <note />
       </trans-unit>
+      <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="InterfaceTypeNotSupportedMessage">
         <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
         <target state="translated">No se admite el uso de "GeneratedComInterfaceAttribute" e "InterfaceTypeAttribute" con el valor "ComInterfaceType" '{0}'.</target>
         <target state="translated">La configuración de “StringMarshalling” y “StringMarshallingCustomType” no es válida.</target>
         <note />
       </trans-unit>
-      <trans-unit id="InvalidStringMarshallingConfigurationMessage">
-        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
-        <target state="translated">La configuración de “StringMarshalling” y “StringMarshallingCustomType” en el método “{0}” no es válida. {1}</target>
-        <note>{1} is a message containing additional details about what is not valid</note>
-      </trans-unit>
       <trans-unit id="InvalidStringMarshallingConfigurationMissingCustomType">
         <source>'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'.</source>
         <target state="translated">Se debe especificar “StringMarshallingCustomType” cuando “StringMarshalling” esté establecido en “StringMarshalling.Custom”.</target>
         <target state="translated">“StringMarshalling” debe establecerse en “StringMarshalling.Custom” cuando “StringMarshallingCustomType” esté especificado.</target>
         <note />
       </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnInterfaceMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnMethodMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</target>
+        <note>{1} is a message containing additional details about what is not valid</note>
+      </trans-unit>
       <trans-unit id="InvalidVirtualMethodIndexAttributeUsage">
         <source>Invalid 'VirtualMethodIndexAttribute' usage</source>
         <target state="translated">Uso de ”VirtualMethodIndexAttribute” no válido</target>
index fa3d3b3..6d23021 100644 (file)
         <target state="translated">Échec de l’analyse de la génération.</target>
         <note />
       </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedDescription">
+        <source>COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</source>
+        <target state="new">COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedMessage">
+        <source>COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</source>
+        <target state="new">COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedTitle">
+        <source>The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</source>
+        <target state="new">The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="needs-review-translation">Les P/Invokes générés par la source ignorent toute configuration qui n’est pas prise en charge.</target>
         <target state="needs-review-translation">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="GeneratedComInterfaceStringMarshallingMustMatchBase">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="InterfaceTypeNotSupportedMessage">
         <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
         <target state="translated">L’utilisation de 'GeneratedComInterfaceAttribute' et 'InterfaceTypeAttribute' n’est pas prise en charge avec la valeur 'ComInterfaceType' '{0}'.</target>
         <target state="translated">La configuration de « StringMarshalling » et de « StringMarshallingCustomType » n’est pas valide.</target>
         <note />
       </trans-unit>
-      <trans-unit id="InvalidStringMarshallingConfigurationMessage">
-        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
-        <target state="translated">La configuration de « StringMarshalling » et de « StringMarshallingCustomType » n’est sur la méthode « {0} » pas valide. {1}</target>
-        <note>{1} is a message containing additional details about what is not valid</note>
-      </trans-unit>
       <trans-unit id="InvalidStringMarshallingConfigurationMissingCustomType">
         <source>'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'.</source>
         <target state="translated">« StringMarshallingCustomType » doit être spécifié quand « StringMarshalling » a la valeur « StringMarshalling.Custom ».</target>
         <target state="translated">« StringMarshalling » doit être défini sur « StringMarshalling.Custom » quand « StringMarshallingCustomType » est spécifié.</target>
         <note />
       </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnInterfaceMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnMethodMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</target>
+        <note>{1} is a message containing additional details about what is not valid</note>
+      </trans-unit>
       <trans-unit id="InvalidVirtualMethodIndexAttributeUsage">
         <source>Invalid 'VirtualMethodIndexAttribute' usage</source>
         <target state="translated">Utilisation de « VirtualMethodIndexAttribute » non valide</target>
index 54ebc3b..67fb4de 100644 (file)
         <target state="translated">L'analisi per la generazione non è riuscita.</target>
         <note />
       </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedDescription">
+        <source>COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</source>
+        <target state="new">COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedMessage">
+        <source>COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</source>
+        <target state="new">COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedTitle">
+        <source>The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</source>
+        <target state="new">The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="needs-review-translation">I P/Invoke generati dall'origine ignoreranno qualsiasi configurazione non supportata.</target>
         <target state="needs-review-translation">La configurazione specificata non è supportata dai P/Invoke generati dall'origine.</target>
         <note />
       </trans-unit>
+      <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="InterfaceTypeNotSupportedMessage">
         <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
         <target state="translated">L'uso di 'GeneratedComInterfaceAttribute' e 'InterfaceTypeAttribute' non è supportato con il valore '{0}' di 'ComInterfaceType'.</target>
         <target state="translated">La configurazione di 'StringMarshalling' e 'StringMarshallingCustomType' non è valida.</target>
         <note />
       </trans-unit>
-      <trans-unit id="InvalidStringMarshallingConfigurationMessage">
-        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
-        <target state="translated">La configurazione di 'StringMarshalling' e 'StringMarshallingCustomType' nel metodo '{0}' non è valida. {1}</target>
-        <note>{1} is a message containing additional details about what is not valid</note>
-      </trans-unit>
       <trans-unit id="InvalidStringMarshallingConfigurationMissingCustomType">
         <source>'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'.</source>
         <target state="translated">È necessario specificare 'StringMarshallingCustomType' quando 'StringMarshalling' è impostato su 'StringMarshalling.Custom'.</target>
         <target state="translated">'StringMarshalling' deve essere impostato su 'StringMarshalling.Custom' quando è specificato 'StringMarshallingCustomType'.</target>
         <note />
       </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnInterfaceMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnMethodMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</target>
+        <note>{1} is a message containing additional details about what is not valid</note>
+      </trans-unit>
       <trans-unit id="InvalidVirtualMethodIndexAttributeUsage">
         <source>Invalid 'VirtualMethodIndexAttribute' usage</source>
         <target state="translated">Utilizzo di 'VirtualMethodIndexAttribute' non valido</target>
index ee0c05e..49f864b 100644 (file)
         <target state="translated">生成の分析に失敗しました。</target>
         <note />
       </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedDescription">
+        <source>COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</source>
+        <target state="new">COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedMessage">
+        <source>COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</source>
+        <target state="new">COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedTitle">
+        <source>The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</source>
+        <target state="new">The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="needs-review-translation">ソース生成済みの P/Invoke は、サポートされていない構成を無視します。</target>
         <target state="needs-review-translation">指定された構成は、ソースで生成された P/Invoke ではサポートされていません。</target>
         <note />
       </trans-unit>
+      <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="InterfaceTypeNotSupportedMessage">
         <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
         <target state="translated">'GeneratedComInterfaceAttribute' および 'InterfaceTypeAttribute' は、'ComInterfaceType' の値 '{0}' ではサポートされていません。</target>
         <target state="translated">'StringMarshalling' と 'StringMarshallingCustomType' の構成が無効です。</target>
         <note />
       </trans-unit>
-      <trans-unit id="InvalidStringMarshallingConfigurationMessage">
-        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
-        <target state="translated">メソッド '{0}' の 'StringMarshalling' と 'StringMarshallingCustomType' の構成が無効です。{1}</target>
-        <note>{1} is a message containing additional details about what is not valid</note>
-      </trans-unit>
       <trans-unit id="InvalidStringMarshallingConfigurationMissingCustomType">
         <source>'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'.</source>
         <target state="translated">'StringMarshalling' が 'StringMarshalling.Custom' に設定されている場合は、'StringMarshallingCustomType' を指定する必要があります。</target>
         <target state="translated">'StringMarshallingCustomType' が指定されている場合、'StringMarshalling' を 'StringMarshalling.Custom' に設定する必要があります。</target>
         <note />
       </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnInterfaceMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnMethodMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</target>
+        <note>{1} is a message containing additional details about what is not valid</note>
+      </trans-unit>
       <trans-unit id="InvalidVirtualMethodIndexAttributeUsage">
         <source>Invalid 'VirtualMethodIndexAttribute' usage</source>
         <target state="translated">'VirtualMethodIndexAttribute' の使用法が無効です</target>
index 36208a9..cc35991 100644 (file)
         <target state="translated">생성에 필요한 분석이 실패했습니다.</target>
         <note />
       </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedDescription">
+        <source>COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</source>
+        <target state="new">COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedMessage">
+        <source>COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</source>
+        <target state="new">COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedTitle">
+        <source>The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</source>
+        <target state="new">The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="needs-review-translation">소스 생성 P/Invoke는 지원되지 않는 구성을 무시합니다.</target>
         <target state="needs-review-translation">지정된 구성은 소스 생성 P/Invoke에서 지원되지 않습니다.</target>
         <note />
       </trans-unit>
+      <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="InterfaceTypeNotSupportedMessage">
         <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
         <target state="translated">'GeneratedComInterfaceAttribute' 및 'InterfaceTypeAttribute'는 'ComInterfaceType' 값 '{0}'에서 지원되지 않습니다.</target>
         <target state="translated">'StringMarshalling' 및 'StringMarshallingCustomType'의 구성이 잘못되었습니다.</target>
         <note />
       </trans-unit>
-      <trans-unit id="InvalidStringMarshallingConfigurationMessage">
-        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
-        <target state="translated">'{0}' 메서드의 'StringMarshalling' 및 'StringMarshallingCustomType' 구성이 잘못되었습니다. {1}</target>
-        <note>{1} is a message containing additional details about what is not valid</note>
-      </trans-unit>
       <trans-unit id="InvalidStringMarshallingConfigurationMissingCustomType">
         <source>'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'.</source>
         <target state="translated">'StringMarshalling'이 'StringMarshalling.Custom'으로 설정된 경우 'StringMarshallingCustomType'을 지정해야 합니다.</target>
         <target state="translated">'StringMarshallingCustomType'이 지정된 경우 'StringMarshalling'은 'StringMarshalling.Custom'으로 설정되어야 합니다.</target>
         <note />
       </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnInterfaceMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnMethodMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</target>
+        <note>{1} is a message containing additional details about what is not valid</note>
+      </trans-unit>
       <trans-unit id="InvalidVirtualMethodIndexAttributeUsage">
         <source>Invalid 'VirtualMethodIndexAttribute' usage</source>
         <target state="translated">잘못된 'VirtualMethodIndexAttribute' 사용</target>
index 09d52e5..c9b2075 100644 (file)
         <target state="translated">Analiza generowania nie powiodła się.</target>
         <note />
       </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedDescription">
+        <source>COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</source>
+        <target state="new">COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedMessage">
+        <source>COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</source>
+        <target state="new">COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedTitle">
+        <source>The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</source>
+        <target state="new">The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="needs-review-translation">Funkcja P/Invokes generowana przez źródło zignoruje każdą nieobsługiwaną konfigurację.</target>
         <target state="needs-review-translation">Określona konfiguracja nie jest obsługiwana przez funkcję P/Invokes generowaną przez źródło.</target>
         <note />
       </trans-unit>
+      <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="InterfaceTypeNotSupportedMessage">
         <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
         <target state="translated">Użycie atrybutów „GeneratedComInterfaceAttribute” i „InterfaceTypeAttribute” nie jest obsługiwane w przypadku wartości „ComInterfaceType” „{0}”.</target>
         <target state="translated">Konfiguracja elementów „StringMarshalling” i „StringMarshallingCustomType” jest nieprawidłowa.</target>
         <note />
       </trans-unit>
-      <trans-unit id="InvalidStringMarshallingConfigurationMessage">
-        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
-        <target state="translated">Konfiguracja elementów „StringMarshalling” i „StringMarshallingCustomType” w metodzie „{0}” jest nieprawidłowa. {1}</target>
-        <note>{1} is a message containing additional details about what is not valid</note>
-      </trans-unit>
       <trans-unit id="InvalidStringMarshallingConfigurationMissingCustomType">
         <source>'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'.</source>
         <target state="translated">Element „StringMarshallingCustomType” należy określić, gdy element „StringMarshalling” ma wartość „StringMarshalling.Custom”.</target>
         <target state="translated">Element „StringMarshalling” należy ustawić na wartość „StringMarshalling.Custom”, gdy określono element „StringMarshallingCustomType”.</target>
         <note />
       </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnInterfaceMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnMethodMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</target>
+        <note>{1} is a message containing additional details about what is not valid</note>
+      </trans-unit>
       <trans-unit id="InvalidVirtualMethodIndexAttributeUsage">
         <source>Invalid 'VirtualMethodIndexAttribute' usage</source>
         <target state="translated">Nieprawidłowe użycie elementu "VirtualMethodIndexAttribute"</target>
index 1cc6443..94df264 100644 (file)
         <target state="translated">Falha na análise de geração.</target>
         <note />
       </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedDescription">
+        <source>COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</source>
+        <target state="new">COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedMessage">
+        <source>COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</source>
+        <target state="new">COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedTitle">
+        <source>The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</source>
+        <target state="new">The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="needs-review-translation">P/Invokes gerados pela origem ignorarão qualquer configuração sem suporte.</target>
         <target state="needs-review-translation">A configuração especificada não tem suporte de P/Invokes gerados pela origem.</target>
         <note />
       </trans-unit>
+      <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="InterfaceTypeNotSupportedMessage">
         <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
         <target state="translated">Não há suporte para o uso de 'GeneratedComInterfaceAttribute' e 'InterfaceTypeAttribute' com o valor 'ComInterfaceType' '{0}'.</target>
         <target state="translated">A configuração de 'StringMarshalling' e 'StringMarshallingCustomType' é inválida.</target>
         <note />
       </trans-unit>
-      <trans-unit id="InvalidStringMarshallingConfigurationMessage">
-        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
-        <target state="translated">A configuração de 'StringMarshalling' e 'StringMarshallingCustomType' no método '{0}' é inválida. {1}</target>
-        <note>{1} is a message containing additional details about what is not valid</note>
-      </trans-unit>
       <trans-unit id="InvalidStringMarshallingConfigurationMissingCustomType">
         <source>'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'.</source>
         <target state="translated">'StringMarshallingCustomType' deve ser especificado quando 'StringMarshalling' está definido como 'StringMarshalling.Custom'.</target>
         <target state="translated">'StringMarshalling' deve ser definido como 'StringMarshalling.Custom' quando 'StringMarshallingCustomType' for especificado.</target>
         <note />
       </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnInterfaceMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnMethodMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</target>
+        <note>{1} is a message containing additional details about what is not valid</note>
+      </trans-unit>
       <trans-unit id="InvalidVirtualMethodIndexAttributeUsage">
         <source>Invalid 'VirtualMethodIndexAttribute' usage</source>
         <target state="translated">Uso inválido de 'VirtualMethodIndexAttribute'</target>
index 453512d..f6cb2cb 100644 (file)
         <target state="translated">Сбой анализа для создания.</target>
         <note />
       </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedDescription">
+        <source>COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</source>
+        <target state="new">COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedMessage">
+        <source>COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</source>
+        <target state="new">COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedTitle">
+        <source>The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</source>
+        <target state="new">The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="needs-review-translation">P/Invoke с созданием источника будут игнорировать все неподдерживаемые конфигурации.</target>
         <target state="needs-review-translation">Указанная конфигурация не поддерживается в P/Invoke с созданием источника.</target>
         <note />
       </trans-unit>
+      <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="InterfaceTypeNotSupportedMessage">
         <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
         <target state="translated">Использование GeneratedComInterfaceAttribute и InterfaceTypeAttribute не поддерживается со значением ComInterfaceType "{0}".</target>
         <target state="translated">Конфигурация \"StringMarshalling\" и \"StringMarshallingCustomType\" недопустима.</target>
         <note />
       </trans-unit>
-      <trans-unit id="InvalidStringMarshallingConfigurationMessage">
-        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
-        <target state="translated">Конфигурация \"StringMarshalling\" и \"StringMarshallingCustomType\" в методе \"{0}\" недопустима. {1}</target>
-        <note>{1} is a message containing additional details about what is not valid</note>
-      </trans-unit>
       <trans-unit id="InvalidStringMarshallingConfigurationMissingCustomType">
         <source>'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'.</source>
         <target state="translated">Если для \"StringMarshalling\" задано значение \"StringMarshalling.Custom\", необходимо указать \"StringMarshallingCustomType\".</target>
         <target state="translated">Если указано \"StringMarshallingCustomType\", для \"StringMarshalling\" следует задать значение \"StringMarshalling.Custom\".</target>
         <note />
       </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnInterfaceMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnMethodMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</target>
+        <note>{1} is a message containing additional details about what is not valid</note>
+      </trans-unit>
       <trans-unit id="InvalidVirtualMethodIndexAttributeUsage">
         <source>Invalid 'VirtualMethodIndexAttribute' usage</source>
         <target state="translated">Недопустимое использование VirtualMethodIndexAttribute</target>
index 4370821..e9bf892 100644 (file)
         <target state="translated">Oluşturma analizi başarısız oldu.</target>
         <note />
       </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedDescription">
+        <source>COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</source>
+        <target state="new">COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedMessage">
+        <source>COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</source>
+        <target state="new">COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedTitle">
+        <source>The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</source>
+        <target state="new">The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="needs-review-translation">Kaynak tarafından oluşturulan P/Invokes desteklenmeyen yapılandırmaları yok sayar.</target>
         <target state="needs-review-translation">Belirtilen yapılandırma, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor.</target>
         <note />
       </trans-unit>
+      <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="InterfaceTypeNotSupportedMessage">
         <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
         <target state="translated">'GeneratedComInterfaceAttribute' ve 'InterfaceTypeAttribute' kullanımı, 'ComInterfaceType' değeri '{0}' ile desteklenmiyor.</target>
         <target state="translated">'StringMarshalling' ve 'StringMarshallingCustomType' yapılandırması geçersiz.</target>
         <note />
       </trans-unit>
-      <trans-unit id="InvalidStringMarshallingConfigurationMessage">
-        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
-        <target state="translated">'{0}' metodundaki 'StringMarshalling' ve 'StringMarshallingCustomType' yapılandırması geçersiz. {1}</target>
-        <note>{1} is a message containing additional details about what is not valid</note>
-      </trans-unit>
       <trans-unit id="InvalidStringMarshallingConfigurationMissingCustomType">
         <source>'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'.</source>
         <target state="translated">'StringMarshalling' 'StringMarshalling.Custom' olarak ayarlandığında 'StringMarshallingCustomType' belirtilmelidir.</target>
         <target state="translated">'StringMarshallingCustomType' belirtilirken 'StringMarshalling', 'StringMarshalling.Custom' olarak ayarlanmalıdır.</target>
         <note />
       </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnInterfaceMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnMethodMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</target>
+        <note>{1} is a message containing additional details about what is not valid</note>
+      </trans-unit>
       <trans-unit id="InvalidVirtualMethodIndexAttributeUsage">
         <source>Invalid 'VirtualMethodIndexAttribute' usage</source>
         <target state="translated">Geçersiz 'VirtualMethodIndexAttribute' kullanımı</target>
index 466366b..8fae13e 100644 (file)
         <target state="translated">生成分析失败。</target>
         <note />
       </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedDescription">
+        <source>COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</source>
+        <target state="new">COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedMessage">
+        <source>COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</source>
+        <target state="new">COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedTitle">
+        <source>The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</source>
+        <target state="new">The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="needs-review-translation">源生成的 P/Invoke 将忽略任何不受支持的配置。</target>
         <target state="needs-review-translation">源生成的 P/Invoke 不支持指定的配置。</target>
         <note />
       </trans-unit>
+      <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="InterfaceTypeNotSupportedMessage">
         <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
         <target state="translated">“ComInterfaceType”值“{0}”不支持使用“GeneratedComInterfaceAttribute”和“InterfaceTypeAttribute”。</target>
         <target state="translated">“StringMarshalling” 和 “StringMarshallingCustomType” 的配置无效。</target>
         <note />
       </trans-unit>
-      <trans-unit id="InvalidStringMarshallingConfigurationMessage">
-        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
-        <target state="translated">方法“{0}”上的 “StringMarshalling” 和 “StringMarshallingCustomType” 的配置无效。{1}</target>
-        <note>{1} is a message containing additional details about what is not valid</note>
-      </trans-unit>
       <trans-unit id="InvalidStringMarshallingConfigurationMissingCustomType">
         <source>'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'.</source>
         <target state="translated">在 “StringMarshalling” 设置为 “StringMarshalling.Custom” 时,必须指定 “StringMarshallingCustomType”。</target>
         <target state="translated">在指定 “StringMarshallingCustomType” 时,应将 “StringMarshalling” 设置为 “StringMarshalling.Custom”。</target>
         <note />
       </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnInterfaceMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnMethodMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</target>
+        <note>{1} is a message containing additional details about what is not valid</note>
+      </trans-unit>
       <trans-unit id="InvalidVirtualMethodIndexAttributeUsage">
         <source>Invalid 'VirtualMethodIndexAttribute' usage</source>
         <target state="translated">“VirtualMethodIndexAttribute” 使用情况无效</target>
index 5accdc6..1bc4bef 100644 (file)
         <target state="translated">產生分析失敗。</target>
         <note />
       </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedDescription">
+        <source>COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</source>
+        <target state="new">COM interface source generation requires all base COM interfaces to be valid interfaces. Fix any issues on the base interface to resolve this diagnostic.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedMessage">
+        <source>COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</source>
+        <target state="new">COM interface {0} inherits from {1}, which has errors. ComInterfaceGenerator will not generate source for {0}.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="BaseInterfaceCannotBeGeneratedTitle">
+        <source>The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</source>
+        <target state="new">The base COM interface failed to generate source. ComInterfaceGenerator will not generate source for this interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="ConfigurationNotSupportedDescription">
         <source>Source-generated COM will ignore any configuration that is not supported.</source>
         <target state="needs-review-translation">来源產生的 P/Invokes 將會忽略任何不支援的設定。</target>
         <target state="needs-review-translation">来源產生的 P/Invokes 不支援指定的設定。</target>
         <note />
       </trans-unit>
+      <trans-unit id="GeneratedComInterfaceStringMarshallingMustMatchBase">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="InterfaceTypeNotSupportedMessage">
         <source>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</source>
         <target state="translated">'ComInterfaceType' 值 '{0}' 不支援使用 'GeneratedComInterfaceAttribute' 和 'InterfaceTypeAttribute'。</target>
         <target state="translated">'StringMarshalling' 和 'StringMarshallingCustomType' 的設定無效。</target>
         <note />
       </trans-unit>
-      <trans-unit id="InvalidStringMarshallingConfigurationMessage">
-        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
-        <target state="translated">方法 '{0}' 上的 'StringMarshalling' 和 'StringMarshallingCustomType' 設定無效。{1}</target>
-        <note>{1} is a message containing additional details about what is not valid</note>
-      </trans-unit>
       <trans-unit id="InvalidStringMarshallingConfigurationMissingCustomType">
         <source>'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'.</source>
         <target state="translated">當 'StringMarshalling' 設定為 'StringMarshalling.Custom' 時,必須指定 'StringMarshallingCustomType'。</target>
         <target state="translated">指定 'StringMarshallingCustomType' 時,'StringMarshalling' 應設定為 'StringMarshalling.Custom'。</target>
         <note />
       </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnInterfaceMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on interface '{0}' is invalid. {1}</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="InvalidStringMarshallingConfigurationOnMethodMessage">
+        <source>The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</source>
+        <target state="new">The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1}</target>
+        <note>{1} is a message containing additional details about what is not valid</note>
+      </trans-unit>
       <trans-unit id="InvalidVirtualMethodIndexAttributeUsage">
         <source>Invalid 'VirtualMethodIndexAttribute' usage</source>
         <target state="translated">'VirtualMethodIndexAttribute' 使用方式無效</target>
index 65691fa..16a3b06 100644 (file)
@@ -17,7 +17,10 @@ namespace Microsoft.Interop
                 EntryPoint = libraryImport.EntryPoint,
                 IsUserDefined = libraryImport.IsUserDefined,
                 SetLastError = libraryImport.SetLastError,
-                StringMarshalling = libraryImport.StringMarshalling
+                StringMarshalling = libraryImport.StringMarshalling,
+                StringMarshallingCustomType = libraryImport.StringMarshallingCustomType is not null
+                    ? ManagedTypeInfo.CreateTypeInfoForTypeSymbol(libraryImport.StringMarshallingCustomType)
+                    : null,
             };
     }
 
index ecbb184..53ac617 100644 (file)
@@ -32,6 +32,7 @@ namespace Microsoft.Interop
         public InteropAttributeMember IsUserDefined { get; init; }
         public bool SetLastError { get; init; }
         public StringMarshalling StringMarshalling { get; init; }
+        public ManagedTypeInfo? StringMarshallingCustomType { get; init; }
     }
 
     /// <summary>
index 38f9f9f..f6f5451 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
+using System.Collections.Generic;
 using System.Linq;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
@@ -38,7 +39,8 @@ namespace ComInterfaceGenerator.Unit.Tests
 
         private string UnmanagedObjectUnwrapper(Type t) => _attributeProvider.UnmanagedObjectUnwrapper(t);
 
-        private string GeneratedComInterface => _attributeProvider.GeneratedComInterface;
+        private string GeneratedComInterface(StringMarshalling? stringMarshalling = null, Type? stringMarshallingCustomType = null)
+            => _attributeProvider.GeneratedComInterface(stringMarshalling, stringMarshallingCustomType);
 
         private string UnmanagedCallConv(Type[]? CallConvs = null)
         {
@@ -55,7 +57,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             using System.Runtime.InteropServices.Marshalling;
 
             {{UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{VirtualMethodIndex(0)}}
@@ -70,7 +72,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             using System.Runtime.InteropServices.Marshalling;
 
             {{UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{VirtualMethodIndex(0, ImplicitThisParameter: false)}}
@@ -86,7 +88,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             using System.Runtime.InteropServices.Marshalling;
 
             {{UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface INativeAPI
             {
 
@@ -122,7 +124,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             [assembly:DisableRuntimeMarshalling]
 
             {{UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{VirtualMethodIndex(0)}}
@@ -140,7 +142,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             [assembly:DisableRuntimeMarshalling]
 
             {{UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{VirtualMethodIndex(0, Direction: MarshalDirection.ManagedToUnmanaged)}}
@@ -159,7 +161,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             [assembly:DisableRuntimeMarshalling]
 
             {{UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{VirtualMethodIndex(0)}}
@@ -175,7 +177,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             using System.Runtime.InteropServices.Marshalling;
 
             {{UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{VirtualMethodIndex(0, ImplicitThisParameter: false)}}
@@ -193,7 +195,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             [assembly:DisableRuntimeMarshalling]
 
             {{UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{VirtualMethodIndex(0)}}
@@ -219,7 +221,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             {{preDeclaration}}
 
             {{UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{VirtualMethodIndex(0, ExceptionMarshalling: ExceptionMarshalling.Com)}}
@@ -236,7 +238,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             {{preDeclaration}}
 
             {{UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{VirtualMethodIndex(0, ExceptionMarshallingType: Type.GetType(customExceptionType))}}
@@ -250,12 +252,12 @@ namespace ComInterfaceGenerator.Unit.Tests
             using System.Runtime.InteropServices;
             using System.Runtime.InteropServices.Marshalling;
 
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface IComInterface
             {
                 void Method();
             }
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface IComInterface2 : IComInterface
             {
                 void Method2();
@@ -266,25 +268,54 @@ namespace ComInterfaceGenerator.Unit.Tests
             using System.Runtime.InteropServices;
             using System.Runtime.InteropServices.Marshalling;
 
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface IComInterface
             {
                 void Method();
             }
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface IOtherComInterface
             {
                 void MethodA();
             }
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface {|#0:IComInterface2|} : IComInterface, IOtherComInterface
             {
                 void Method2();
             }
             """;
 
+        public string DerivedWithStringMarshalling(params
+            (StringMarshalling StringMarshalling, Type? StringMarshallingCustomType)[] attributeArguments)
+        {
+            List<string> declarations = new();
+            int i = 0;
+            foreach (var args in attributeArguments)
+            {
+                declarations.Add($$"""
+                    {{GeneratedComInterface(args.StringMarshalling, args.StringMarshallingCustomType)}}
+                    internal partial interface {|#{{i}}:IStringMarshalling{{i}}|} {{(i > 0 ? $": IStringMarshalling{i - 1}" : "")}}
+                    {
+                        public string GetString{{i}}();
+                        public void SetString{{i}}(string value);
+                    }
+                """);
+                i++;
+            }
+            return $$"""
+                using System;
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+
+                namespace Test
+                {
+                    {{string.Join("\n\n", declarations)}}
+                }
+                """;
+        }
+
         public string ComInterfaceParameters => BasicParametersAndModifiers("IComInterface2") + $$"""
-            {{GeneratedComInterface}}
+            {{GeneratedComInterface()}}
             partial interface IComInterface2
             {
                 void Method2();
index acc11f6..ee1c280 100644 (file)
@@ -17,8 +17,8 @@ using Xunit;
 using System.Diagnostics;
 
 using VerifyComInterfaceGenerator = Microsoft.Interop.UnitTests.Verifiers.CSharpSourceGeneratorVerifier<Microsoft.Interop.ComInterfaceGenerator>;
-using Newtonsoft.Json.Bson;
-using System.Diagnostics.CodeAnalysis;
+using StringMarshalling = System.Runtime.InteropServices.StringMarshalling;
+using System.Runtime.InteropServices.Marshalling;
 
 namespace ComInterfaceGenerator.Unit.Tests
 {
@@ -95,6 +95,237 @@ namespace ComInterfaceGenerator.Unit.Tests
             yield return new object[] { ID(), customStructMarshallingCodeSnippets.Stateful.ByValueInParameter, new[] { invalidUnmanagedToManagedParameterDiagnostic } };
         }
 
+        public static IEnumerable<object[]> StringMarshallingCodeSnippets(GeneratorKind generator)
+        {
+            const string CustomStringMarshallingWithNoCustomTypeMessage = @"'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'.";
+            const string CustomTypeSpecifiedWithNoStringMarshallingCustom = @"'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified.";
+            const string StringMarshallingMustMatchBase = "The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' must match the base COM interface.";
+
+            CodeSnippets codeSnippets = new(GetAttributeProvider(generator));
+            (StringMarshalling, Type?) utf8Marshalling = (StringMarshalling.Utf8, null);
+            (StringMarshalling, Type?) utf16Marshalling = (StringMarshalling.Utf16, null);
+            (StringMarshalling, Type?) customUtf16Marshalling = (StringMarshalling.Custom, typeof(Utf16StringMarshaller));
+            (StringMarshalling, Type?) customWithNoType = (StringMarshalling.Custom, null);
+            (StringMarshalling, Type?) utf8WithType = (StringMarshalling.Utf8, typeof(Utf16StringMarshaller));
+            DiagnosticResult[] emptyDiagnostics = new DiagnosticResult[] { };
+
+            // StringMarshalling.Custom / StringMarshallingCustomType invalid
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(customWithNoType),
+                new DiagnosticResult[]
+                {
+                    VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.InvalidStringMarshallingConfigurationOnInterface)
+                        .WithLocation(0)
+                        .WithArguments("Test.IStringMarshalling0", CustomStringMarshallingWithNoCustomTypeMessage)
+                }
+            };
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(utf8WithType),
+                new DiagnosticResult[]
+                {
+                    VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.InvalidStringMarshallingConfigurationOnInterface)
+                        .WithLocation(0)
+                        .WithArguments("Test.IStringMarshalling0", CustomTypeSpecifiedWithNoStringMarshallingCustom)
+                }
+            };
+
+            // Inheritance no diagnostic
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(utf16Marshalling, utf16Marshalling),
+                emptyDiagnostics
+            };
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(utf8Marshalling, utf8Marshalling),
+                emptyDiagnostics
+            };
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(customUtf16Marshalling, customUtf16Marshalling),
+                emptyDiagnostics
+            };
+
+            // mismatches
+            DiagnosticResult[] mismatchAt1 = MismatchesWithLocations(1);
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(utf8Marshalling, utf16Marshalling),
+                mismatchAt1
+            };
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(utf16Marshalling, utf8Marshalling),
+                mismatchAt1
+            };
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(utf16Marshalling, customUtf16Marshalling),
+                mismatchAt1
+            };
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(customUtf16Marshalling, utf16Marshalling),
+                mismatchAt1
+            };
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(utf8Marshalling, customUtf16Marshalling),
+                mismatchAt1
+            };
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(customUtf16Marshalling, utf8Marshalling),
+                mismatchAt1
+            };
+
+            // Three levels inheritance
+            // Matching
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(utf8Marshalling, utf8Marshalling, utf8Marshalling),
+                emptyDiagnostics
+            };
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(utf16Marshalling, utf16Marshalling, utf16Marshalling),
+                emptyDiagnostics
+            };
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(customUtf16Marshalling, customUtf16Marshalling, customUtf16Marshalling),
+                emptyDiagnostics
+            };
+
+            //Mismatches
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(utf8Marshalling, utf8Marshalling, utf16Marshalling),
+                MismatchesWithLocations(2)
+            };
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(utf8Marshalling, utf16Marshalling, utf16Marshalling),
+                MismatchesWithLocations(1).Concat(BaseCannotBeGeneratedWithLocations(2)).ToArray()
+            };
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(utf8Marshalling, utf16Marshalling, utf8Marshalling),
+                MismatchesWithLocations(1, 2)
+            };
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(utf8Marshalling, utf16Marshalling, customUtf16Marshalling),
+                MismatchesWithLocations(1, 2)
+            };
+
+            // Base has no StringMarshalling and Derived does is okay
+            string source = $$"""
+                using System;
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+                namespace Test
+                {
+                    [GeneratedComInterface]
+                    [Guid("0E7204B5-4B61-4E06-B872-82BA652F2ECA")]
+                    internal partial interface INoStringMarshalling
+                    {
+                        public int GetInt();
+                        public void SetInt(int value);
+                    }
+                    [GeneratedComInterface(StringMarshalling = StringMarshalling.Utf8)]
+                    [Guid("0E7204B5-4B61-5E06-B872-82BA652F2ECA")]
+                    internal partial interface IStringMarshalling : INoStringMarshalling
+                    {
+                        public string GetString();
+                        public void SetString(string value);
+                    }
+                }
+                """;
+            yield return new object[] { ID(), source, emptyDiagnostics };
+
+            source = $$"""
+                using System;
+                using System.Runtime.InteropServices;
+                using System.Runtime.InteropServices.Marshalling;
+                namespace Test
+                {
+                    [GeneratedComInterface]
+                    [Guid("0E7204B5-4B61-4E06-B872-82BA652F2ECA")]
+                    internal partial interface INoStringMarshalling
+                    {
+                        [return: MarshalUsing(typeof(Utf8StringMarshaller))]
+                        public string GetString();
+                        public void SetString([MarshalUsing(typeof(Utf8StringMarshaller))] string value);
+                    }
+                    [GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)]
+                    [Guid("0E7204B5-4B61-5E06-B872-82BA652F2ECA")]
+                    internal partial interface IStringMarshalling : INoStringMarshalling
+                    {
+                        public string GetString2();
+                        public void SetString2(string value);
+                    }
+                }
+                """;
+            yield return new object[] { ID(), source, emptyDiagnostics };
+
+            // Base many levels up fails, all inheriting fail
+            yield return new object[]
+            {
+                ID(),
+                codeSnippets.DerivedWithStringMarshalling(customWithNoType, customUtf16Marshalling, customUtf16Marshalling, customUtf16Marshalling, customUtf16Marshalling, customUtf16Marshalling),
+                new DiagnosticResult[]
+                {
+                    VerifyComInterfaceGenerator.Diagnostic(GeneratorDiagnostics.InvalidStringMarshallingConfigurationOnInterface)
+                        .WithLocation(0)
+                        .WithArguments("Test.IStringMarshalling0", CustomStringMarshallingWithNoCustomTypeMessage)
+                }
+                   .Concat(MismatchesWithLocations(1))
+                   .Concat(BaseCannotBeGeneratedWithLocations(2, 3, 4, 5))
+                   .ToArray()
+            };
+
+            DiagnosticResult[] MismatchesWithLocations(params int[] locations)
+            {
+                return locations
+                    .Select(i =>
+                        new DiagnosticResult(GeneratorDiagnostics.InvalidStringMarshallingMismatchBetweenBaseAndDerived)
+                            .WithLocation(i)
+                            .WithArguments($"Test.IStringMarshalling{i}", StringMarshallingMustMatchBase))
+                    .ToArray();
+            }
+
+            DiagnosticResult[] BaseCannotBeGeneratedWithLocations(params int[] locations)
+            {
+                return locations
+                    .Select(i =>
+                        new DiagnosticResult(GeneratorDiagnostics.BaseInterfaceIsNotGenerated)
+                            .WithLocation(i)
+                            .WithArguments($"Test.IStringMarshalling{i}", $"Test.IStringMarshalling{i - 1}"))
+                   .ToArray();
+            }
+        }
+
         public static IEnumerable<object[]> InvalidManagedToUnmanagedCodeSnippetsToCompile(GeneratorKind generator)
         {
             // Marshallers with only support for their expected places in the signatures in
@@ -135,6 +366,14 @@ namespace ComInterfaceGenerator.Unit.Tests
             await VerifyComInterfaceGenerator.VerifySourceGeneratorAsync(source, expectedDiagnostic);
         }
 
+        [Theory]
+        [MemberData(nameof(StringMarshallingCodeSnippets), GeneratorKind.ComInterfaceGenerator)]
+        public async Task ValidateStringMarshallingDiagnostics(string id, string source, DiagnosticResult[] expectedDiagnostics)
+        {
+            _ = id;
+            await VerifyComInterfaceGenerator.VerifySourceGeneratorAsync(source, expectedDiagnostics);
+        }
+
         [Fact]
         public async Task ValidateInterfaceWithoutGuidWarns()
         {
index 83bac9f..b1bcef7 100644 (file)
@@ -22,7 +22,15 @@ namespace ComInterfaceGenerator.Unit.Tests
 
         public string UnmanagedObjectUnwrapper(Type t) => "";
 
-        public string GeneratedComInterface => @$"[global::System.Runtime.InteropServices.Marshalling.GeneratedComInterface, global::System.Runtime.InteropServices.Guid(""0A52B77C-E08B-4274-A1F4-1A2BF2C07E60"")]";
+        public string GeneratedComInterface(StringMarshalling? stringMarshalling = null, Type? stringMarshallingCustomType = null)
+        {
+            string comma = stringMarshalling is not null && stringMarshallingCustomType is not null ? ", " : "";
+            return @$"[global::System.Runtime.InteropServices.Marshalling.GeneratedComInterface("
+                + (stringMarshalling is not null ? $"StringMarshalling = {typeof(StringMarshalling).FullName}.{stringMarshalling!.Value}" : "")
+                + comma
+                + (stringMarshallingCustomType is not null ? $"StringMarshallingCustomType = typeof({stringMarshallingCustomType!.FullName})" : "")
+                + @$"), global::System.Runtime.InteropServices.Guid(""0A52B77C-E08B-4274-A1F4-1A2BF2C07E60"")]";
+        }
 
         public string AdditionalUserRequiredInterfaces(string userDefinedInterfaceName) => "";
     }
index f2df492..84a0c09 100644 (file)
@@ -33,7 +33,7 @@ namespace ComInterfaceGenerator.Unit.Tests
         /// <summary>
         /// Returns the [GeneratedComInterface] to be put into a snippet, if desired. Otherwise, returns <see cref="string.Empty" />.
         /// </summary>
-        string GeneratedComInterface { get; }
+        string GeneratedComInterface(StringMarshalling? stringMarshalling = null, Type? stringMarshallingCustomType = null);
 
         /// <summary>
         /// Returns any additional code to be appended to the snippet that provides any additional interfaces the user must implement
index 0474607..fde5787 100644 (file)
@@ -30,7 +30,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             [assembly:DisableRuntimeMarshalling]
             
             {{AttributeProvider.UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{AttributeProvider.GeneratedComInterface}}
+            {{AttributeProvider.GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
@@ -47,7 +47,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             [assembly:DisableRuntimeMarshalling]
             
             {{AttributeProvider.UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{AttributeProvider.GeneratedComInterface}}
+            {{AttributeProvider.GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
@@ -63,7 +63,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             {{preDeclaration}}
             
             {{AttributeProvider.UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{AttributeProvider.GeneratedComInterface}}
+            {{AttributeProvider.GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
@@ -81,7 +81,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             [assembly:DisableRuntimeMarshalling]
             
             {{AttributeProvider.UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{AttributeProvider.GeneratedComInterface}}
+            {{AttributeProvider.GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
@@ -96,7 +96,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             {{preDeclaration}}
             
             {{AttributeProvider.UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{AttributeProvider.GeneratedComInterface}}
+            {{AttributeProvider.GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
@@ -111,7 +111,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             {{preDeclaration}}
             
             {{AttributeProvider.UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{AttributeProvider.GeneratedComInterface}}
+            {{AttributeProvider.GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
@@ -131,7 +131,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             [assembly:DisableRuntimeMarshalling]
             
             {{AttributeProvider.UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{AttributeProvider.GeneratedComInterface}}
+            {{AttributeProvider.GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
@@ -156,7 +156,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             [assembly:DisableRuntimeMarshalling]
             
             {{AttributeProvider.UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{AttributeProvider.GeneratedComInterface}}
+            {{AttributeProvider.GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
@@ -182,7 +182,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             [assembly:DisableRuntimeMarshalling]
             
             {{AttributeProvider.UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{AttributeProvider.GeneratedComInterface}}
+            {{AttributeProvider.GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
@@ -202,7 +202,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             [assembly:DisableRuntimeMarshalling]
             
             {{AttributeProvider.UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{AttributeProvider.GeneratedComInterface}}
+            {{AttributeProvider.GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
@@ -221,7 +221,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             [assembly:DisableRuntimeMarshalling]
             
             {{AttributeProvider.UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{AttributeProvider.GeneratedComInterface}}
+            {{AttributeProvider.GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
@@ -239,7 +239,7 @@ namespace ComInterfaceGenerator.Unit.Tests
             [assembly:DisableRuntimeMarshalling]
             
             {{AttributeProvider.UnmanagedObjectUnwrapper(typeof(UnmanagedObjectUnwrapper.TestUnwrapper))}}
-            {{AttributeProvider.GeneratedComInterface}}
+            {{AttributeProvider.GeneratedComInterface()}}
             partial interface INativeAPI
             {
                 {{AttributeProvider.VirtualMethodIndex(0, ImplicitThisParameter: ImplicitThisParameter, Direction: Direction)}}
index 0c31f2d..9455372 100644 (file)
@@ -23,15 +23,15 @@ namespace ComInterfaceGenerator.Unit.Tests
                         + (ImplicitThisParameter.HasValue ? $", ImplicitThisParameter = {ImplicitThisParameter.Value.ToString().ToLower()}" : "")
                         + (Direction is not null ? $", Direction = {typeof(MarshalDirection).FullName}.{Direction.Value}" : "")
                         + (StringMarshalling is not null ? $", StringMarshalling = {typeof(StringMarshalling).FullName}.{StringMarshalling!.Value}" : "")
-                        + (StringMarshallingCustomType is not null ? $", StringMarshallingCustomType = {StringMarshallingCustomType!.FullName}" : "")
+                        + (StringMarshallingCustomType is not null ? $", StringMarshallingCustomType = typeof({StringMarshallingCustomType!.FullName})" : "")
                         + (SetLastError is not null ? $", SetLastError = {SetLastError.Value.ToString().ToLower()}" : "")
                         + (ExceptionMarshalling is not null ? $", ExceptionMarshalling = {typeof(ExceptionMarshalling).FullName}.{ExceptionMarshalling.Value}" : "")
-                        + (ExceptionMarshallingType is not null ? $", ExceptionMarshallingCustomType = {ExceptionMarshallingType!.FullName}" : "")
+                        + (ExceptionMarshallingType is not null ? $", ExceptionMarshallingCustomType = typeof({ExceptionMarshallingType!.FullName})" : "")
                         + ")]";
 
         public string UnmanagedObjectUnwrapper(Type t) => $"[global::System.Runtime.InteropServices.Marshalling.UnmanagedObjectUnwrapperAttribute<{t.FullName!.Replace('+', '.')}>]";
 
-        public string GeneratedComInterface => "";
+        public string GeneratedComInterface(StringMarshalling? stringMarshalling = null, Type? stringMarshallingCustomType = null) => "";
 
         public string AdditionalUserRequiredInterfaces(string userDefinedInterfaceName) => """
             partial interface INativeAPI : IUnmanagedInterfaceType
@@ -40,4 +40,4 @@ namespace ComInterfaceGenerator.Unit.Tests
             }
             """;
     }
-}
\ No newline at end of file
+}